RabbitMQ(九)死信队列AND延迟队列

RabbitMQ(九)死信队列AND延迟队列

死信队列

  • DLX(Dead Letter Exchanges)死信交换机/死信邮箱,当消息在队列中由于某些原因没有被及时消费而变成死信(dead message)后,这些消息就会被分发到DLX交换机中,而绑定DLX交换机的队列,称之为:“死信队列”
  • 消息没有被及时消费的原因:
    • 消息被拒绝(basic.reject/ basic.nack)并且不再重新投递 requeue=false
    • 消息超时未消费
    • 达到最大队列长度

在这里插入图片描述

spring-rabbitmq-producer-dlx.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:rabbit="http://www.springframework.org/schema/rabbit"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/tx
        https://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/rabbit
        https://www.springframework.org/schema/rabbit/spring-rabbit.xsd">

    <!--配置RabbitMQ连接-->
    <!--publisher-confirms="true" : 开启生产者确认机制-->
    <rabbit:connection-factory id="connectionFactory" host="106.75.245.83" port="5672" username="admin" password="admin"
                               virtual-host="/szx"></rabbit:connection-factory>

    <!--配置RabbitMQAdmin,主要用于在Java代码中对队列的管理,用来创建,绑定,删除队列与交换机,发送消息等操作-->
    <rabbit:admin connection-factory="connectionFactory"></rabbit:admin>

    <!--配置RabbitMQ的模板-->
    <!--confirm-callback="messsageConfirm" : 添加确认回调处理类-->
    <rabbit:template id="rabbitTemplate" connection-factory="connectionFactory" exchange="my_exchange"></rabbit:template>

    <!--配置确认机制的处理类-->
    <bean id="messsageConfirm" class="com.szx.confirm.MesssageConfirm"></bean>

    <!--##############################################################################################################################-->

    <!--配置死信队列-->
    <rabbit:queue name="dlx_queue"></rabbit:queue>

    <!--定义定向死信交换机-->
    <rabbit:direct-exchange name="dlx_exchange">
        <rabbit:bindings>
            <rabbit:binding key="dlx_ttl" queue="dlx_queue"></rabbit:binding>
            <rabbit:binding key="dlx_max" queue="dlx_queue"></rabbit:binding>
        </rabbit:bindings>
    </rabbit:direct-exchange>

    <!--定义测试过期消息队列-->
    <rabbit:queue name="test_ttl_queue">
        <rabbit:queue-arguments>
            <!--设置队列的过期时间-->
            <entry key="x-message-ttl" value-type="long" value="6000"></entry>
            <!--消息超时 将消息投递给死信交换机(路由)-->
            <entry key="x-dead-letter-exchange" value="dlx_exchange"></entry>
        </rabbit:queue-arguments>
    </rabbit:queue>

    <!--定义超出长度消息队列-->
    <rabbit:queue name="test_max_queue">
        <rabbit:queue-arguments>
            <!--设置队列的额定长度(本队列最多装 2 个消息)-->
            <entry key="x-max-length" value-type="long" value="2"></entry>
            <!--消息超出长度 将消息投递给死信交换机(路由)-->
            <entry key="x-dead-letter-exchange" value="dlx_exchange"></entry>
        </rabbit:queue-arguments>
    </rabbit:queue>

    <!--定义定向的测试消息的交换机-->
    <rabbit:direct-exchange name="my_exchange">
        <rabbit:bindings>
            <rabbit:binding key="dlx_ttl" queue="test_ttl_queue"></rabbit:binding>
            <rabbit:binding key="dlx_max" queue="test_max_queue"></rabbit:binding>
        </rabbit:bindings>
    </rabbit:direct-exchange>

</beans>
public class SenderDLX {

    public static void main(String[] args) {
        //获取spring的配置文件
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring/spring-rabbitmq-producer-dlx.xml");
        //与容器中获取RabbitMQ模板类
        RabbitTemplate rabbitTemplate = context.getBean(RabbitTemplate.class);
        /**
         * String routingKey: 指定路由键
         * Object object: 发送的数据
         */
        rabbitTemplate.convertAndSend("dlx_ttl", "测试超时".getBytes());
        System.out.println("消息已发送!");
        context.close();
    }

}
public class SenderDLX {

    public static void main(String[] args) {
        //获取spring的配置文件
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring/spring-rabbitmq-producer-dlx.xml");
        //与容器中获取RabbitMQ模板类
        RabbitTemplate rabbitTemplate = context.getBean(RabbitTemplate.class);
        /**
         * String routingKey: 指定路由键
         * Object object: 发送的数据
         */
        rabbitTemplate.convertAndSend("dlx_max", "测试长度 1".getBytes());
        rabbitTemplate.convertAndSend("dlx_max", "测试长度 2".getBytes());
        rabbitTemplate.convertAndSend("dlx_max", "测试长度 3".getBytes());
        System.out.println("消息已发送!");
        context.close();
    }

}

测试长度 1 被放入死信队列

延迟队列

  • 延迟队列:TTL + 死信队列的合体
  • 死信队列只是一种特殊的队列,里面的消息仍然可以消费
  • 在电商开发部分中,都会涉及到延时关闭订单,此时延迟队列正好可以解决这个问题

生产者

沿用上面死信队列案例的超时测试,超时时间改为订单关闭时间即可

消费者

spring-rabbitmq-consumer.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:rabbit="http://www.springframework.org/schema/rabbit"
       xmlns:rab="http://www.springframework.org/schema/rabbit"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/tx
        https://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/rabbit
        https://www.springframework.org/schema/rabbit/spring-rabbit.xsd">

    <!--配置RabbitMQ连接-->
    <rabbit:connection-factory id="connectionFactory" host="106.75.245.83" port="5672" username="admin" password="admin" virtual-host="/szx"></rabbit:connection-factory>

    <!--配置RabbitMQAdmin,主要用于在Java代码中对队列的管理,用来创建,绑定,删除队列与交换机,发送消息等操作-->
    <rabbit:admin connection-factory="connectionFactory"></rabbit:admin>

    <!--配置扫描包-->
    <context:component-scan base-package="com.szx.listener"></context:component-scan>

    <!--配置监听-->
    <!--
        限流
            acknowledge="manual":手动确认
            prefetch="3":一次性消费的数量。会告诉 RabbitMQ 不要同时给一个消费者推送多于 N 个消息还没有 ack ,则该 consumer 将阻塞,到消息被 ack 确认
    -->
    <rabbit:listener-container connection-factory="connectionFactory" prefetch="3" acknowledge="manual">
        <!--应用注入到容器中的监听类-->
        <rabbit:listener ref="consumerListener" queue-names="dlx_queue"></rabbit:listener>
    </rabbit:listener-container>



</beans>
@Component
public class ConsumerListener /*implements MessageListener*/ extends AbstractAdaptableMessageListener {

    //jackson提供序列化和反序列化中使用最多的类,用来转换json
    private static final ObjectMapper MAPPER = new ObjectMapper();

    @Override
    public void onMessage(Message message, Channel channel) throws Exception {
        //获取传递消息
        String string = new String(message.getBody());
        System.out.println("string = " + string);
    }

}
public class TestRunner {
    public static void main(String[] args) {
        //获取spring容器
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring/spring-rabbitmq-consumer.xml");
        try {
            //程序一直运行不停止
            System.in.read();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值