rabbitmq.“消费端确认收到”和“推送者确认”(4)

预取值设定
 由于信息是异步发送的,同一时刻,可能不止一个信息在通道中传输。手动应答本质上也是异步的。所以有一个变动的信息未确认时间窗口期。开发者通常希望限制这个窗口的大小,避免消费端缓存越界问题。这点可以用basic.qos方法设置预取值得到。这个值是允许通道中存在未确认消息的最大值。一旦达到这个最大值,RabbitMQ将不再向通道中传递信息,直到通道中信息被应答的。

 比如有5,6,7,8几个未应答的信息在通道ch中,切最大预取值是4,则直到通道中的消息被应答前,RabbitMQ不会再向这个ch通道投递。当一个标签8的应答帧到达,RabbitMQ将注意到并再发一个信息到这个通道。

 需要再次强调的是投递和手动应答过程都是异步的。所以,在传递信息的过程中预取的值变化可能会看未应答的信息数量大于预取值。

    对于basic.get ("pull API")获取信息的方式,QoS预取值并不会有作用,即使是手动确认模式也是如此。

消费者应答模式,预取和吞吐量

    应答模式和预取值对于消费者者的吞吐量有至关重要的影响。通常,提高预取值有利于提升传输速率。自动应答拥有最好的传输速率。然而,有两种情况,传递出去但是未处理的消息将增加,这会导致RAM的消耗。

 无论自动应答还是手动应答模式,选取不加限制的预取值都应再三考虑。消费者消费大量的消息,但是未进行应答将导致消费节点链接节点大量内存消耗。选择一个合适的预存值是一个不断尝试的过程,不同的系统负载有不同的情况。100到300通常是一个理想的数值,不会大的肯能压跨消费端。更高的值通常进入“边际收益递减规律”

 值设置未1是最保守的选择。这的确可以明显的减少负载,特别是连接耗时高环境系下。对一些应用来说,高些的值是恰当的、理想的。

消费者失败或者链接中断:自动重连

 当使用自动应答模式的时候,通道关闭,未应答的消息自动重排。包括客户端丢失tcp连接、客户端应用垮掉和通道层的协议错误。

 注意,发现不可用的客户端需要些时间。

 正因如此,客户端应该能够处理重传和保证幂等。重传有一个RabbitMQ设置的特殊属性redeliver。第一次投递这个值是false。注意一个消费端可能获取之前传递给另一个消费端的消息。

客户端错误:重新肯定应答、未知标签

 客户端应该多次应答一个传递标签么,RabbitMQ将报PRECONDITION_FAILED - unknown delivery tag 100此类的错误信息。未知的标签也会看到这个错误信息。

 另一个场景,也会视为未知标签:应答通知和对应的消息不在一个通道上。哪个通道消息的应答通知必须在其通道上传递。

投递确认

 网络可能问题可能不明显,发现失败的要耗些时间。所以,传递消息到socket的客户端不可以假定消息成功到服务端并被成功的处理。它可能已经丢失或者可以被延迟传递。

 使用标准AMQP 0-9-1,唯一可以保证消息成功的方式是事务提交。这种情况下,事务是不必要的重负,增加约250倍的负载。为了解决这个问题,确认机制被引入。这是模仿已经爱协议中存在的消费端确认机制。

 开启确认模式,客户端需要调用confirm.select方法。根据是否设置no-wait,中专站可能回复confirm.select-ok。一旦通道使用confirm.select,就可以称为确认模式。确认模式和事务模式通道只能二选一。

 只要通道是确认模式,服务节点和客户端都会统计消息数量(从第一次confirm.select,又1开始统计)。中转端处理完会发送basic.ack进行确认。传递标签字段包含已确认消息的序列号。中转端也可能在basic.ack设置multiple字段,表明包括这个带有序列号的所有传递消息已被处理。

 

原文:

Channel Prefetch Setting (QoS)

Because messages are sent (pushed) to clients asynchronously, there is usually more than one message "in flight" on a channel at any given moment. In addition, manual acknowledgements from clients are also inherently asynchronous in nature. So there's a sliding window of delivery tags that are unacknowledged. Developers would often prefer to cap the size of this window to avoid the unbounded buffer problem on the consumer end. This is done by setting a "prefetch count" value using the basic.qos method. The value defines the max number of unacknowledged deliveries that are permitted on a channel. Once the number reaches the configured count, RabbitMQ will stop delivering more messages on the channel unless at least one of the outstanding ones is acknowledged.

For example, given that there are delivery tags 5, 6, 7, and 8 unacknowledged on channel Ch and channel Ch's prefetch count is set to 4, RabbitMQ will not push any more deliveries on Ch unless at least one of the outstanding deliveries is acknowledged. When an acknowledgement frame arrives on that channel with delivery_tag set to 8, RabbitMQ will notice and deliver one more message.

It's worth reiterating that the flow of deliveries and manual client acknowledgements is entirely asynchronous. Therefore if prefetch value is changed while there already are deliveries in flight, a natural race condition arises and there can temporarily be more than prefetch count unacknowledged messages on a channel.

The QoS prefetch setting has no effect on messages fetched using the basic.get ("pull API"), even in manual confirmation mode.

The QoS setting can be configured for a channel or a consumer. See Consumer Prefetch for details.

Consumer Acknowledgement Modes, Prefetch and Throughput

Acknowledgement mode and QoS prefetch value have significant effect on consumer throughput. In general, increasing prefetch will improve the rate of message delivery to consumers. Automatic acknowledgement mode yields best possible rate of delivery. However, in both cases the number of delivered but not-yet-processed messages will also increase, thus increasing consumer RAM consumption.

Automatic acknowledgement mode or manual acknowledgement mode with unlimited prefetch should be used with care. Consumers that consume a lot of messages without acknowledging will lead to memory consumption growth on the node they are connected to. Finding a suitable prefetch value is a matter of trial and error and will vary from workload to workload. Values in the 100 through 300 range usually offer optimal throughput and do not run significant risk of overwhelming consumers. Higher values often run into the law of diminishing returns.

Prefetch value of 1 is the most conservative. It will significantly reduce throughput, in particular in environments where consumer connection latency is high. For many applications, a higher value would be appropriate and optimal.

When Consumers Fail or Lose Connection: Automatic Requeueing

When manual acknowledgements are used, any delivery (message) that was not acked is automatically requeued when the channel (or connection) on which the delivery happened is closed. This includes TCP connection loss by clients, consumer application (process) failures, and channel-level protocol exceptions (covered below).

Note that it takes a period of time to detect an unavailable client.

Due to this behavior, consumers must be prepared to handle redeliveries and otherwise be implemented with idempotence in mind. Redeliveries will have a special boolean property, redeliver, set to true by RabbitMQ. For first time deliveries it will be set to false. Note that a consumer can receive a message that was previously delivered to another consumer.

Client Errors: Double Acking and Unknown Tags

Should a client acknowledge the same delivery tag more than once, RabbitMQ will result a channel error such as PRECONDITION_FAILED - unknown delivery tag 100. The same channel exception will be thrown if an unknown delivery tag is used.

Another scenario in which the broker will complain about an "unknown delivery tag" is when an acknowledgement, whether positive or negative, is attempted on a channel different from that on which the delivery was received on. Deliveries must be acknowledged on the same channel.

Publisher Confirms

Networks can fail in less-than-obvious ways and detecting some failures takes time. Therefore a client that's written a protocol frame or a set of frames (e.g. a published message) to its socket cannot assume that the message has reached the server and was successfully processed. It could have been lost along the way or its delivery can be significantly delayed.

Using standard AMQP 0-9-1, the only way to guarantee that a message isn't lost is by using transactions -- make the channel transactional then for each message or set of messages publish, commit. In this case, transactions are unnecessarily heavyweight and decrease throughput by a factor of 250. To remedy this, a confirmation mechanism was introduced. It mimics the consumer acknowledgements mechanism already present in the protocol.

To enable confirms, a client sends the confirm.select method. Depending on whether no-wait was set or not, the broker may respond with a confirm.select-ok. Once the confirm.select method is used on a channel, it is said to be in confirm mode. A transactional channel cannot be put into confirm mode and once a channel is in confirm mode, it cannot be made transactional.

Once a channel is in confirm mode, both the broker and the client count messages (counting starts at 1 on the first confirm.select). The broker then confirms messages as it handles them by sending a basic.ack on the same channel. The delivery-tag field contains the sequence number of the confirmed message. The broker may also set the multiple field in basic.ack to indicate that all messages up to and including the one with the sequence number have been handled.

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值