Rabbitm使用死信队列完成消息延迟发送

思路:
需要1个普通交换机、1个普通队列、1个死信交换机、1个死信队列
1、生产者生成消息,添加过期时间,将消息发送给普通队列,等到消息过期后,将消息发送给死信队列。
2、消费者监听死信队列,有消息进入,进行消息消费。
缺点:
队列按照消息进入顺序进行消费,处理消息时会判断消息过期时间。即使后面的消息先过期,也要等到先进来的消息处理结束。会有个现象是,先进来的消息一处理完,后进来的消息也立即处理完,几乎同时。
解决:
1、多设置几个过期时间的节点消息队列。程序中按照过期时间,将消息分发到不同过期时间的队列中

1、交换机、队列定义与绑定
@Configuration
public class RabbitMQConfig {

    /**
     * iot告警交换机
     */
    private static final String EXCHANGE_NAME = "iot_fault_exchange";

    /**
     * iot告警队列
     */
    private static final String QUEUE_NAME = "iot_fault_queue";

    /**
     * iot告警死信交换机
     */
    private static final String DLX_EXCHANGE_NAME = "iot_fault_dlx_exchange";

    /**
     * iot告警死信队列
     */
    private static final String DLX_QUEUE_NAME = "iot_fault_dlx_queue";

    /**
     * iot告警路由Key
     */
    private static final String ROUTING_KEY = "iot_fault_routing_key";

	 /**
     * 定义普通交换机
     */
    @Bean
    public DirectExchange exchange() {
        return new DirectExchange(EXCHANGE_NAME);
    }

	/**
     * 定义普通队列
     * 绑定死信交换机,过期、错误、拒绝的消息会发给它
     * 不设置路由key
     */
    @Bean
    public Queue queue() {
        return QueueBuilder.durable(QUEUE_NAME)
            .withArgument("x-dead-letter-exchange", DLX_EXCHANGE_NAME)
            .withArgument("x-dead-letter-routing-key", "")
            .build();
    }

	/**
     * 定义死信交换机
     */
    @Bean
    public DirectExchange dlxExchange() {
        return new DirectExchange(DLX_EXCHANGE_NAME);
    }

	/**
     * 定义死信队列
     */
    @Bean
    public Queue dlxQueue() {
        return new Queue(DLX_QUEUE_NAME);
    }

	/**
     * 普通队列与普通交换机绑定
     * 设置路由key为ROUTING_KEY,进入普通交换机的消息,带有路由key的消息发给普通队列
     */
    @Bean
    public Binding binding(Queue queue, DirectExchange exchange) {
        return BindingBuilder.bind(queue).to(exchange).with(ROUTING_KEY);
    }

	/**
     * 死信队列与死信交换机绑定
     * 不设置路由key,进入死信交换机的消息,直接给死信队列
     */
    @Bean
    public Binding dlxBinding(Queue dlxQueue, DirectExchange dlxExchange) {
        return BindingBuilder.bind(dlxQueue).to(dlxExchange).with("");
    }

}
2、生产者发送消息,关联死信交换机
long expireTime = faultTimeToFault * 1000;

rabbitTemplate.convertAndSend("iot_fault_exchange", "iot_fault_routing_key", JSONUtil.parseObj(excuteFaultVO).toString(), message -> {
    message.getMessageProperties().setExpiration(String.valueOf(expireTime));
    return message;
});
3、消费者监听死信队列进行消费
@RabbitListener(queues = {"iot_fault_dlx_queue"})
    public void consumer01(Message message, Channel channel) throws IOException {

        try {
            // 处理消息
//            String msg = Arrays.toString(message.getBody());

            String msg = StrUtil.str(message.getBody(), "UTF-8");

            ExcuteFaultVO excuteFaultVO = JSONUtil.toBean(JSONUtil.parseObj(msg), ExcuteFaultVO.class);

            IotFault iotFault = new IotFault();
            iotFault.setEquipmentId(excuteFaultVO.getEquipmentId());
            iotFault.setFaultId(excuteFaultVO.getAttrId());
            iotFault.setFaultMsg(excuteFaultVO.getMsg());
            iotFault.setDeptId(excuteFaultVO.getDeptId());
            iotFault.setCreateTime(DateUtil.date());
            System.out.println(DateUtils.dateTimeNow());
            iotFaultMapper.insert(iotFault);
            System.out.println("消费者 -01- 接收消息:" + msg );

//            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);

        } catch (Exception e) {
            // 处理失败,拒绝消息
            channel.basicReject(message.getMessageProperties().getDeliveryTag(), false);
        }
    }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值