RabbitMQ消息可靠性(一)

一、消息发送可靠性(推荐使用消息确认模式,事务方式效率低)

1.1 通过事务确保消息发送成功
@Configuration
public class RabbitmqConfig {

    @Bean
    DirectExchange directExchange(){
        return new DirectExchange("direct_change");
    }
    @Bean
    Queue queue1(){
        return new Queue("queue",true,false,false);
    }

    @Bean
    Binding binding(){
        return BindingBuilder.bind(queue1()).to(directExchange()).with("a");
    }


    @Bean
    RabbitTransactionManager rabbitTransactionManager(ConnectionFactory factory){
        return new RabbitTransactionManager(factory);
    }

    @Bean
    RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory){
        RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
        rabbitTemplate.setChannelTransacted(true);
        return rabbitTemplate;
    }
}

   @Autowired
    RabbitTemplate rabbitTemplate;

    @Transactional(rollbackFor = Exception.class)
    public void sendMsg(){
        rabbitTemplate.convertAndSend("direct_change","a","hello queue");
    }
1.2 消息确认机制
spring:
  rabbitmq:
    virtual-host: /
    host: 127.0.0.1
    port: 5672
    username: guest
    password: guest
    publisher-confirm-type: correlated
    publisher-returns: true

@Configuration
public class RabbitConfig implements RabbitTemplate.ConfirmCallback,RabbitTemplate.ReturnsCallback {

    public static final Logger logger = LoggerFactory.getLogger(RabbitConfig.class);

    @Autowired
    RabbitTemplate rabbitTemplate;

    @PostConstruct
    public void init(){
        rabbitTemplate.setConfirmCallback(this::confirm);
        rabbitTemplate.setReturnsCallback(this::returnedMessage);
    }

    @Bean
    DirectExchange directExchange(){
        return new DirectExchange("exchange_name",true,false);
    }
    @Bean
    Queue queue1(){
        return new Queue("queue_name",true,false,false);
    }


    @Bean
    Binding binding(){
        return BindingBuilder.bind(queue1()).to(directExchange()).with("a");
    }

    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String cause) {
      if(ack){
          logger.info("{}消息成功到达交换机",correlationData.getId());
      }else {
          logger.info("{}消息未到达交换机,{}",correlationData.getId(),cause);
      }
    }

    /**
     * 消息未到达队列触发
     * @param returned
     */
    @Override
    public void returnedMessage(ReturnedMessage returned) {
         logger.info("消息未到达队列");
    }
}

二、消息失败重试

2.1 通过配置rabbit实现消息失败重试
spring:
  rabbitmq:
    template:
      retry:
        ## 启用重试
        enabled: true
        ## 重试时间间隔
        initial-interval: 1000ms
        ## 最大重试次数
        max-attempts: 5
        ## 重试时间累加  如第一次 1000ms  第二次就是1200 以此类推
        multiplier: 1.2
        ## 最大重试间隔
        max-interval: 5000ms
2.2 业务重试机制

针对消息没有成功到交换机,针对这种情况,回调做相关的业务逻辑即可.
具体思路:
可以使用数据库在每次发送消息的时候写入库里给此条消息增加一个状态,在交换机回调处,做相应的处理逻辑.
1.收到失败回调对此消息做数据库的修改,是重试几次后,还是发送失败那么就不在重新发送此条消息,改变此条消息的状态即可。
2.如果消息收到此条消息发送成功就改变次条消息的状态。
3.当然了,发送失败的消息,重试次数超过后,定时器去找失败的消息,做业务处理即可。
注意:这里会有消息重复发送的情况,在消费方做好消息的幂等性即可。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值