RabbitMQ入门_12_发布方确认
参考资料:https://www.rabbitmq.com/confirms.html
通过 ack 机制,我们可以确保队列中的消息一定能被消费到。那我们有办法保证消息发布方一定把消息发送到队列了吗?
遵照 AMQP 协议,RabbitMQ 提供了事务机制可以确保发布方消息必达。但是吞吐量会降为越来的 1/250,这个性能损耗是无法接受的。
好在 RabbitMQ 提供了类似于消费方 ack 的机制,用于确保发布方消息必达。
gordon.study.rabbitmq.features.TestPublisherConfirm.java
public class TestPublisherConfirm {
private static final String QUEUE_NAME = "publisherConfirm";
public static void main(String[] argv) throws Exception {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
Connection connection = factory.newConnection();
Channel senderChannel = connection.createChannel();
senderChannel.queueDeclare(QUEUE_NAME, false, false, true, null);
senderChannel.confirmSelect();
senderChannel.addConfirmListener(new ConfirmListener() {
@Override
public void handleNack(long deliveryTag, boolean multiple) throws IOException {
System.out.printf("nack: %s %s\n", deliveryTag, multiple);
}
@Override
public void handleAck(long deliveryTag, boolean multiple) throws IOException {
System.out.printf("ack: %s %s\n", deliveryTag, multiple);
}
});
for (int i = 0; i < 10;) {
String message = "NO. " + ++i;
senderChannel.basicPublish("", QUEUE_NAME, null, message.getBytes("UTF-8"));
}
boolean isConfirm = senderChannel.waitForConfirms();
System.out.println("isConfirm: " + isConfirm);
connection.close();
}
}
代码第12行 confirmSelect 方法将当前信道设置为确认模式,该信道就启动了发布者确认特性。此时,RabbitMQ 会在消息被所有目标队列接收后,向发布者发送 ack,通知发布者消息已成功送达队列。如果中间出现异常,RabbitMQ 会发送 nack 通知发布者,发布者即可选择重新发送消息。
第30行 waitForConfirms 方法会阻塞住,直到两次 waitForConfirms 方法之间发送的所有消息都由 RabbitMQ 返回 ack 或 nack 通知。
除了官方文档中提到的 waitForConfirms 方法,还可以通过 ConfirmListener 来实现更高效的确认(无阻塞)。代码第13行开始创建了一个 ConfirmListener 并注册到信道中,之后, RabbitMQ 发回的 ack / nack 消息会触发相应的 handle 回调函数。