赞
踩
生产者开启消息确认及return监听回调配置
- spring:
- rabbitmq:
- host: ip
- port: 5672
- username: guest
- password: guest
- ##消息发送确认回调
- publisher-confirms: true
- ##采用confirm以及return机制发送返回监听回调
- publisher-confirm-type: correlated
- ##Return机制确保消息从交换机发送到指定的队列
- publisher-returns: true
MQ配置
-
- /**
- * RabbitMQ配置信息,绑定交换器、队列、路由键设置
- *
- * <p>
- * 如果我们希望即使在RabbitMQ服务重启的情况下,也不会丢失消息,可以将交换机、队列、消息都进行持久化,这样可以保证绝大部分情况下消息不会丢失。
- * 但还是会有小概率发生消息丢失的情况(比如RabbitMQ服务器已经接收到生产者的消息,但还没来得及持久化该消息时RabbitMQ服务器就断电了),
- * 如果我们需要对这种小概率事件也要管理起来,那么我们要用到事务。(transaction/confirm机制)
- *
- * <p>
- * 说明:
- * 1. 队列持久化:需要在声明队列的时候设置durable=true,如果只对队列进行持久化,那么mq重启之后队列里面的消息不会保存
- * 如果需要队列里面的消息也保存下来,那么还需要对消息进行持久化;
- * <p>
- * 2. 消息持久化:设置消息的deliveryMode = 2,消费者重启之后还能够继续消费持久化之后的消息;
- * 使用convertAndSend方式发送消息,消息默认就是持久化的,下面是源码:
- * new MessageProperties() --> DEFAULT_DELIVERY_MODE = MessageDeliveryMode.PERSISTENT --> deliveryMode = 2;
- * <p>
- * 3.重启mq: CMD命令行下执行 net stop RabbitMQ && net start RabbitMQ
- */
- @Component
- public class RabbitMQConfig {
- private static final String DURABLE_QUEUE_NAME = "durable_queue_name";
- private static final String DURABLE_EXCHANGE_NAME = "durable_exchange_name";
- private static final String ROUTING_KEY = "user.#";
-
- private static final String QUEUE_NAME = "not_durable_queue_name";
- private static final String EXCHANGE_NAME = "not_durable_exchange_name";
-
- @Bean
- public Queue durableQueue() {
- // public Queue(String name) {
- // this(name, true, false, false);
- // }
- // public Queue(String name, boolean durable, boolean exclusive, boolean autoDelete)
- //不指定durable的话默认好像也是true
-
- //public Queue(String name, boolean durable)
- //durable:是否将队列持久化 true表示需要持久化 false表示不需要持久化
- return new Queue(DURABLE_QUEUE_NAME, true);
- }
-
- @Bean
- public TopicExchange durableExchange() {
- // public AbstractExchange(String name) {
- // this(name, true, false);
- // }
- // public AbstractExchange(String name, boolean durable, boolean autoDelete) {
- // this(name, durable, autoDelete, (Map)null);
- // }
- //声明交换机的时候默认也是持久化的
- return new TopicExchange(DURABLE_EXCHANGE_NAME);
- }
-
- @Bean
- public Binding durableBinding() {
- //如果exchange和queue都是持久化的,那么它们之间的binding也是持久化的。如果exchange和queue两者之间有一个持久化,一个非持久化,就不允许建立绑定
- return BindingBuilder.bind(durableQueue()).to(durableExchange()).with(ROUTING_KEY);
- }
-
-
- @Bean
- public Queue queue() {
- //public Queue(String name, boolean durable)
- //durable:是否将队列持久化 true表示需要持久化 false表示不需要持久化
- return new Queue(QUEUE_NAME, false);
- }
-
- @Bean
- public TopicExchange exchange() {
- return new TopicExchange(EXCHANGE_NAME,true,false);
- }
-
- @Bean
- public Binding binding() {
- return BindingBuilder.bind(queue()).to(exchange()).with(ROUTING_KEY);
- }
-
- }
消费者手动确认消息配置
- listener:
- type: simple
- simple:
- #手动接收消息方式,# none:关闭ack;manual:手动ack;auto:自动ack
- acknowledge-mode: manual
一般消息失败后需要重试,我们在yml中配置
- listener: # 开启消费者确认其机制
- simple:
- prefetch: 1 #消费者每次只能获取一条消息,处理完才能获取下一条(可实现能者多劳)
- acknowledge-mode: manual # none:关闭ack;manual:手动ack;auto:自动ack
- retry:
- enabled: true #开启消费者失败重试
- initial-interval: 1000ms #初始的失败等待时长为1秒
- multiplier: 1 #下次失败的等待时长倍数,下次等待时长 = multiplier * last-interval
- max-attempts: 3 #最大重试次数
- stateless: true #true无状态;false有状态。如果业务中包含事务,这里改为false
在开启重试模式后,重试次数耗尽后消息消费仍然失败,则需要通过MessageRecoverer接口来处理,它包含三种不同的实现:
1、RejectAndDontRequeueRecoverer:重试耗尽后,默认方式:直接丢弃消息,不符合多数业务需求
2、ImmediateRequeueMessageRecoverer:重试耗尽后,返回nack,消息重新入队,容易造成队列死循环消费,不推荐
3、RepublishMessageRecoverer:重试耗尽后,将失败消息投递到指定的交换机,人工再处理,推荐使用
以下介绍第三种处理方式:
- /**
- * 接收错误消费的日志
- */
- @RabbitListener(bindings = @QueueBinding(value = @Queue(name = "errorQueue"),
- exchange = @Exchange(name = "errorExchange", type = ExchangeTypes.DIRECT, ignoreDeclarationExceptions = "true"),
- key = "errorRouting"
- ))
- public void receiveErrorMessage(String message) {
- log.info("消费者收到发送错误的消息: " + message);
- }
- /**
- * 定义错误消息接收
- */
- @Configuration
- @Slf4j
- public class ErrorConfig {
- @Bean
- public MessageRecoverer messageRecoverer(RabbitTemplate rabbitTemplate){
- log.debug("加载RepublishMessageRecoverer");
- return new RepublishMessageRecoverer(rabbitTemplate,"errorExchange","errorRouting");
- }
- }
这个就开启了消费者失败重试机制,并设置MessageRecoverer,多次重试失败后将消息投递到异常交换机,交由人工处理。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。