消息确认机制
- 生产者通过消息确认机制,来确认消息是否被成功消费
- 配置信息
spring:
rabbitmq:
connection-timeout: 5000 #消息超时时间
publisher-confirms: true #消息成功确认
publisher-returns: true #消息失败确认
template:
mandatory: true #手动签收机制
- 通过实现RabbitTemplate.ConfirmCallback,RabbitTemplate.ReturnCallback这两个接口方法,进行消息确认和消息补偿
消费者ACK消息自动确认的时机
AutoAck的消息确认时机
手动提交Ack
// String queue, boolean autoAck, Consumer callback
channel.basicConsume(QUEUE_NAME, false, consumer);
// 拒绝消息
// requeue:是否重新入队列,true:是;false:直接丢弃,相当于告诉队列可以直接删除掉
// TODO 如果只有这一个消费者,requeue 为true 的时候会造成消息重复消费
channel.basicReject(envelope.getDeliveryTag(), false);
// requeue:是否重新入队列
// TODO 如果只有这一个消费者,requeue 为true 的时候会造成消息重复消费
channel.basicNack(envelope.getDeliveryTag(), true, false);
// 如果不应答,队列中的消息会一直存在,重新连接的时候会重复消费
channel.basicAck(envelope.getDeliveryTag(), true);
开启消息者消费手动ACK
@Bean
public SimpleMessageListenerContainer messageContainer(ConnectionFactory connectionFactory) {
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory);
container.setQueues(getSecondQueue(), getThirdQueue()); //监听的队列
container.setConcurrentConsumers(1); // 最小消费者数
container.setMaxConcurrentConsumers(5); // 最大的消费者数量
container.setDefaultRequeueRejected(false); //是否重回队列
container.setAcknowledgeMode(AcknowledgeMode.AUTO); //签收模式,问题:如何单独设置某个队列的消费者为手动签收?
container.setExposeListenerChannel(true);
container.setConsumerTagStrategy(new ConsumerTagStrategy() { //消费端的标签策略
@Override
public String createConsumerTag(String queue) {
return queue + "_" + UUID.randomUUID().toString();
}
});
return container;
}
ACK消息生产者消费失败?
消息的补偿机制
- 消息重发
- 重发的消息是否相同?
- 消息重发可能出现的问题