mandatory和immediate是channel.basicPublish方法的两个参数,都有消息传递过程中不可达目的地时将消息返回给生产者的功能。
告诉服务器至少将该消息路由到一个队列中,否则将消息返回给生产者。
Rabbitmq3.0去掉了对immediate参数支持,建议采用TTL和DLX方法替代
生产者发送消息不设置mandatory,消息未被路由会丢失,设置了,需要添加ReturnListener。如果不想编程复杂也不想消息丢失使用备份交换器。
使用:
特殊情况:
通过队列属性设置,队列中所有消息都有相同的过期时间(一旦过期,就从队列中抹去,消息已经在队列头部,只要定期从队列头部开始扫描即可)
channel.queueDeclare方法中加入x-message-ttl参数实现,单位ms
Map<String,Object> args = new HashMap<String,Object>();
args.put("x-message-ttl",6000);
channel.queueDeclare(queueName,durable,exclusive,autoDelete,args);
通过Policy方式设置ttl
rabbitmqctl set_policy TTL ".*" '{"message-ttl":6000}' --apply-to queue
通过调用http api接口设置
通过对消息本身单独设置,每条消息的ttl可以不同(即使过期,也不会马上抹去,是否过期是在即将投递到消费者之前判定的)
如果两个方法一起使用,消息的ttl以两者之间较小的数值为准,消息在队列中一旦超过设置的ttl时,就会变成死信,消费者将无法再收到该消息
不设置ttl,表示此消息不会过期,ttl=0,表示除非此时可以直接将消息投递到消费者,否则立即丢弃。
channel.queueDeclare方法中的x-expires参数可以控制队列被自动删除前处于未使用状态的时间(未使用:队列上没有任何消费者,队列也没有被重新声明,并在过期时间段内也未调用过Basic.Get命令)
Map<String, Object> args = new HashMap<String,Object>();
args.put("x-expires", 1800000);
channel.queueDeclare("myqueue",false,false,false,args);
当消息在一个队列中变成死信后,能被重新被发送到另一个交换器中,这个交换器就是DLX,死信交换器,绑定DLX的队列就是死信队列
消息变成死信情况
当队列中存在死信时,rabbitmq会自动将这个消息重新发布到设置的DLX上去,进而被路由到另一个队列,死信队列,可以监听这个队列的消息进行相应处理
设置方法
延迟队列存储的对象是对应的延迟消息(当消息被发送以后,并不想让消费者立刻拿到消息,而是等待特定时间后,消费者才能拿到这个消息进行消费)。
场景:
通过DLX 和TTL模拟延迟队列的功能。
假设一个应用中需要将每条消息都设置为10秒延迟,生产者通过exchange.normal交换器将发送的消息存储在queue.normal队列,消费者订阅的是queue.dlx队列,当消息从queue.normal整个队列中过期之后被存入queue.dlx队列,消费者恰巧消费到了延迟10秒的这条消息。
实现:通过设置队列的x-max-priority参数实现
默认最低优先级为0,越高越优先消费
前提:如果在消费速度大于生成者的速度且broker中没有消息堆积的情况下,对发送的消息设置优先级就没什么意义了。
客户端发送请求消息,服务端回复响应的消息,为了接收响应的消息,需要在请求消息中发送一个回调队列
String callbackQueueName = channel.queueDeclare().getQueue();
BasicProperties props = new BasicProperties.Builder().replyTo(callbackQueueName).build();
channel.basicPublish("","rpc_queue",props,message.getBytes());
可以为每一个客户端创建一个单一的回调队列。
将交换器、队列、消息都设置持久化后不能保证数据百分百丢失。
确定消息到底有没有正确到达服务器。可以通过事务机制和发送方确认机制
rabbitmq客户端与事务机制相关方法
开启事务流程
缺点:会有性能损失
事务机制在一条消息发送后会使发送端阻塞,等待rabbitmq回应后才发下一条消息,而发送发确认机制最大好处是异步的。生产者通过回调方法处理该确认消息。如果rabbitmq因自身内部错误导致消息丢失,会发送一条nack命令,生产者应用程序同样可以在回调方法中处理nack命令。
publisher confirm优势
rabbitmq队列拥有多个消费者时,队列收到的消息将以轮询的分发方式发送给消费者,每条消息只会发送给订阅列表里的一个消费者。
指消费者消费到的消息和发送者发布的消息的顺序是一致的。
打破顺序性的情形
要保证消息的顺序性,需要业务方使用rabbitmq之后进一步处理,例如在消息体内添加全局有序标识实现。
缺陷
一般消息中间件消息传输保障分为三个层级
rabbitmq支持其中的最多一次和最少一次,其中最少一次投递实现需要考虑
参考:《RabbitMQ实战指南》