消费者取消通知
概述
当channel从队列中消费消息时,有众多原因会导致消费停止。一个十分显而易见的原因是,若在同一个channel中,客户端发起basic.cancel,会造成消费者取消且服务器回复basic.cancel-ok。其他情况,例如队列被删除,或者集群中该队列所在节点出现故障,都对造成消费者被取消,但是客户端channel不会被通知到。
为了解决该问题,我们引入了一个扩展,一旦预期之外的消费者取消发生,broker会发送basic.cancel给客户端,broker接收到客户端发送的basic.cancel时broker不会发送该消息。
AMQP 0-9-1客户端默认情况下不会异步接收来自broker的basic.cancel方法,因此要启用此行为,客户端必须在其客户端属性(client-properties)中提供一个功能表,其中有一个 key consumer_cancel_notify 和一个布尔值 true。详情请参阅功能部分。
我们支持的客户端默认向broker提供这种功能,因此代理会发送异步的 basic.cancel 方法,客户端会将该方法提交给消费者回调。例如,在我们的 Java 客户端中,消费者接口有一个 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 和broker发送异步通知之间可能存在竞争关系。在这种情况下,当收到 basic.cancel 时,代理不会出错,而是正常回复 basic.cancel-ok。
译者注:客户端主动取消消费者,发送basic.cancel给broker,但恰好同时队列被删除,broker异步发送消费者取消通知basic.cancel给客户端,此时broker会正常向客户端回复basic.cancel-ok
消费者取消和复制队列
当队列被删除或者不可用时,支持消费者取消通知的客户端总会被通知。
当复制队列leader发生变化时消费者可能会请求其应被取消。