发送者确认
发送者确认分两种
一是将消息发送到交换机时可能交换机不存在挂了,需要确认
二是交换机收到消息了,但在路由到队列时,找不到队列也需要确认
对应publisherConfirm
和publisherReturns
publisherConfirm:
确认发送到交换机。需要在发送者设置publisherConfirm
spring:
rabbitmq:
addresses: localhost
port: 5672
username: guest
password: guest
publisher-confirm-type: correlated #发布确认(发布的交换机不存在)
一共有三种值,这里设置为correlated
public enum ConfirmType {
/**
*在作用域操作中使用RabbitTemplate#waitForConfirms() (或waitForConfirmsOrDie()
*/
SIMPLE,
/**
* 与CorrelationData一起使用将确认与发送的消息相关联
*/
CORRELATED,
/**
* 发布者确认被禁用(默认)
*/
NONE
}
RabbitTemplate的waitForConfirms()
waitForConfirmsOrDie()
/*
等到自上次调用以来发布的所有消息都被代理确认或拒绝; 或直到超时。 如果超时到期,则抛出 TimeoutException。 在非确认通道上调用时,waitForConfirms 会抛出 IllegalStateException。
返回:
是否所有消息都被确认(并且没有消息被确认
*/
boolean waitForConfirms(long timeout) throws InterruptedException, TimeoutException;
/*
等到自上次调用以来发布的所有消息都被代理确认或拒绝; 或直到超时。 如果超时到期,则抛出 TimeoutException。 如果任何消息被拒绝,waitForConfirmsOrDie 将抛出一个 IOException。 当在非确认通道上调用时,它会抛出一个 IllegalStateException
*/
void waitForConfirmsOrDie(long timeout) throws IOException, InterruptedException, TimeoutException;
两种需要分别实现接口,然后添加到rabbitTemplate中,发布后会回调方法
默认消费者是自动确认的,一共三种确认方式
public class MyPubConfirm implements RabbitTemplate.ConfirmCallback{
@Resource
RabbitTemplate rabbitTemplate;
@PostConstruct
public void set(){
rabbitTemplate.setConfirmCallback(this);
}
//发送消息到exchange(交换机不存在)
@Override
public void confirm(CorrelationData correlationData, boolean ack, @Nullable String cause) {
}
}
publisherReturns
需要开启publisherReturns和mandatory
spring:
rabbitmq:
addresses: localhost
port: 5672
username: guest
password: guest
publisher-confirm-type: correlated #发布确认(发布的交换机不存在)
publisher-returns: true #从交换机发到队列,队列不存在会触发返回消息给生产者,需要开启mandatory,默认false不开启
template:
mandatory: true
继承RabbitTemplate.ReturnsCallback并添加到rabbitTemplate
public class MyPubConfirm implements RabbitTemplate.ReturnsCallback {
@Resource
RabbitTemplate rabbitTemplate;
@PostConstruct
public void set(){
rabbitTemplate.setReturnsCallback(this);
}
//消息从exchange路由到队列(routingKey错误或队列不存在)
@Override
public void returnedMessage(ReturnedMessage returnedMessage) {
}
}
当从交换机路由到队列时会回调
消费者确认
public enum AcknowledgeMode {
NONE,
MANUAL,
AUTO;
}
这里只说手动方式,将acknowledgeMode设置为manual
spring:
rabbitmq:
addresses: localhost
port: 5672
username: guest
password: guest
listener:
simple:
acknowledge-mode: manual
消费者代码:
@RabbitListener(queues = "direct_queueA")
public void consumer1(Message message, Channel channel) throws IOException {
channel.basicNack(message.getMessageProperties().getDeliveryTag(),
false,
true);
// channel.basicAck(message.getMessageProperties().getDeliveryTag(),
false);
// channel.basicReject(message.getMessageProperties().getDeliveryTag(),
false);
System.out.println("consumer1----->"+new String(message.getBody()));
}
消费者可以确认消息,拒绝消息
确认消息
:
basicAck(long deliveryTag, boolean multiple),
参数一
是消息中的一个属性,类似于id;
参数二
是否批量确认,比如消费者批量接受了多条消息(deliveryTag分别是1、2、3),那么在确认deliveryTag为3的消息时候就会把之前的1、2消息也会被确认
拒绝消息
:
basicNack(long deliveryTag, boolean multiple, boolean requeue)(批量)
basicReject(long deliveryTag, boolean requeue)
两个方法区别就是批量,basicReject只能一条一条拒绝,basicNack可通过设置multiple参数批量拒绝