消费者取消通知
概述
当某个通道正在从队列中消费消息时,可能会由于各种原因导致消费停止。其中一个显而易见的原因是,如果客户端在同一个通道上发出 basic.cancel
,这将导致消费者被取消,并且服务器会回复 basic.cancel-ok
。其他事件,例如队列被删除,或者在集群场景中,队列所在的节点发生故障,都会导致消费被取消,但客户端通道不会收到通知,这通常是不方便的。
为了解决这个问题,我们引入了一个扩展,在发生此类意外的消费者取消时,代理会向客户端发送 basic.cancel
。如果代理从客户端接收到 basic.cancel
,则不会发送此消息。AMQP 0-9-1 客户端默认情况下不希望异步地从代理接收 basic.cancel
方法,因此,为了启用此行为,客户端必须在其 client-properties
中提供一个 capabilities
表,其中包含一个键 consumer_cancel_notify
和一个布尔值 true
。有关详细信息,请参阅关于功能的部分。
我们支持的客户端默认情况下会向代理提供此功能,因此代理会向其发送异步 basic.cancel
方法,然后客户端将其呈现给消费者回调。例如,在我们的 Java 客户端中,Consumer
接口有一个 handleCancel
回调,可以通过子类化 DefaultConsumer
类来覆盖它。
channel.queueDeclare(queue, false, true, false, null);
Consumer consumer = new DefaultConsumer(channel) {
@Override
public void handleCancel(String consumerTag) throws IOException {
// consumer has been cancelled unexpectedly
}
};
channel.basicConsume(queue, consumer);
如果客户端对一个意外取消的消费者(例如,由于队列删除)发出 basic.cancel
,则不会出错。根据定义,客户端发出 basic.cancel
和代理发送异步通知之间存在竞争条件的可能性。在这种情况下,当代理接收到 basic.cancel
时不会出错,并像往常一样回复 basic.cancel-ok
。
消费者取消和复制队列
支持消费者取消通知的客户端将在队列被删除或不可用时始终收到通知。消费者可以请求在复制队列的领导者发生变化时取消它们。