SpringBoot消费RabbitMQ 通过死信保证无法消费的消息不会丢失

由于最近刚刚接触RabbitMQ  自己在测试服务器搭建了一个RabbitMQ的服务

具体说明详见我的博客

 

大家再用RabbitMQ 的时候经常会遇到消费Mq的消息失败的情况,一般情况下会根据不同的业务场景通过不同的办法去记录下无法消费的消息的数据,本文简单介绍了下springBoot集成RabbitMQ的一个示例, 并且通过代码简单的配置集成死信队列防止无法消费的数据丢失的情况,其实参考了网上许多案例,但是网上写的太杂,大多是复制过来简单改改~而且正确性也无法保证

Mq依赖如下

 <!--RabbitMQ 依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
            <version>1.3.7.RELEASE</version>
        </dependency>

SpringBoot的配置文件如下 

spring:
  rabbitmq:
    host: 10.10.20.103
    port: 5672
    username: user
    password: userPwd
    listener:
      simple:
        retry:
          enabled: true
          max-attempts: 5
          initial-interval: 2000
        default-requeue-rejected: false

重点说明下配置文件default-requeue-rejected这个字段一定要设置成 false 不然无法消费的数据不会进入死信队列的

 

Mq的全局配置代码如下

import com.xxxx.xxxxxx.contants.SysContants;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.Map;

/**
 * 消息队列的全局配置,当前每个数据最多尝试消费五次,每次2秒 如果五次都没有办法消费掉
 * 那么数据进入死信队列中,防止无法消费的数据丢失
 * @Author xj
 */
@Configuration
public class RabbitConfig {

    // 死信的交换机名
    final String DEAD_LETTER_EXCHANGE="xxxx_xxxx_dead_exchange";

    @Bean
    public Queue maintainQueue() {
        Map<String,Object> args=new HashMap<>();
        // 设置该Queue的死信的信箱
        args.put("x-dead-letter-exchange", DEAD_LETTER_EXCHANGE);
        // 设置死信routingKey
        args.put("x-dead-letter-routing-key", SysContants.DEAD_ROUTING_KEY);
        return new Queue(SysContants.ROUTING_KEY,true,false,false,args);
    }

    @Bean
    public Binding maintainBinding() {
        return BindingBuilder.bind(maintainQueue()).to(DirectExchange.DEFAULT)
            .with(SysContants.ROUTING_KEY);
    }

    @Bean
    public Queue deadLetterQueue(){
        return new Queue(SysContants.DEAD_ROUTING_KEY);
    }

    @Bean
    public DirectExchange deadLetterExchange() {
        return new DirectExchange(DEAD_LETTER_EXCHANGE, true, false);
    }

    @Bean
    public Binding deadLetterBindding(){
        return BindingBuilder.bind(deadLetterQueue()).to(deadLetterExchange()).with(SysContants.DEAD_ROUTING_KEY);
    }

}

Ps:其中SysContants.ROUTING_KEY和SysContants.DEAD_ROUTING_KEY是二个String常量 大家可以根据自己的需要去随便定义

 

消息的消费者代码如下

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
@RabbitListener(queues = SysContants.ROUTING_KEY)
@Slf4j
public class Receiver {

    @Autowired
    XXXXXService xxxService;

    @RabbitHandler
    public void process(String workOrderData) {
        try {
            log.info("receive  data {} ", workOrderData);
            OrderRequest request = JSON.parseObject(workOrderData, OrderRequest.class);
            BaseResult baseResult=xxxService.save(request);
            log.info("save  data {},result {}", workOrderData,baseResult.toString());
        }catch (Exception e){
            log.warn("cousumers ribbitmq message {} error",workOrderData);
            throw new Exception(ErrorCode.COUSUMERS_MQ_MESSAGE_FAIL);
        }
    }
}

很多同学把异常给吃掉了 这里面的异常可以catch 并且log 但是需要后面主动抛出异常。不然消息就会被当做消费成功处理了

其中SysContants.ROUTING_KEY就是RabbitConfig里面的那个String常量 假设我代码在try块里面出现异常的话 那么这个消息会尝试再一次消费,  直到重试到spring.rabbitmq.listener.simple.retry.max-attempts设置的次数位置,  其中每次尝试的间隔为spring.rabbitmq.listener.simple.retry.initial-interval设置的毫秒数,如果消息仍然没有被消费掉 那么消息就会进去我们设置的死信队列中去。这样我们就能保证我们无法消费的数据不会再加上重试机制之后丢弃了。。  
 

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值