rabbimq xml 配置延迟对列

关于 RabbitMQ 的 Dead-Letters-Queue “死信队列”

 
来自一个队列的消息可以被当做‘死信’,即被重新发布到另外一个“exchange”去,这样的情况有:
  • 消息被拒绝 (basic.reject or basic.nack) 且带 requeue=false 参数
  • 消息的TTL-存活时间已经过期
  • 队列长度限制被超越(队列满)
 
Dead letter exchanges (DLXs) are normal exchanges.
 
For any given queue, a DLX can be defined by clients using the queue's arguments, or in the server using policies.
 
Dead Letter Pattern
     “死信”模式指的是,当消费者不能处理接收到的消息时,将这个消息重新发布到另外一个队列中,等待重试或者人工干预。
这个过程中的exchange和queue就是所谓的"Dead Letter Exchange 和 Queue"。
     关键是如何区分“消费失败”和“处理失败”?消费失败需要送到死信队列,而处理失败不需要。大部分情况都属于“处理失败”。
 
Dead-Letter-Exchange, routing-key, queue 都可以从 rabbitmq 的管理后台配置。
 
如果用 Spring-rabbitmq 来使用 Dead-Letter-Exchange 和 Queue 需要对。
     从 3.9 Exception Handling 可以知道,设置 defaultRequeueRejected = false 会丢弃消息或者重新发布到死信队列中。
     如果是 Convert 出现异常,那么会直接 "reject-dont-requeue".
 
< rabbit:listener-container  defaultRequeueRejected="false"   connection-factory = "connectionFactory" >
   < rabbit:listener  ref = "listener"  method = "listen"  queue-names = "async_request_queue"  />
</rabbit: listener-container>
 
     也可以在 handler 中抛出 "AmqpRejectAndDontRequeueException" 来告诉spring容器,不要重新requeue这条消息。
 
     然后配置 Dead Letter Exchange 并绑定 Dead Letter Queue.
 
<rabbit:queue name="q.with.dlx">
    <rabbit:queue-arguments> 
        <entry key="x-dead-letter-exchange" value="dlx"/>
        <entry key="x-message-ttl" value="10000" value-type="java.lang.Long"/>
    </rabbit:queue-arguments>
</rabbit:queue>

<rabbit:queue name="dlq"/>

<rabbit:direct-exchange name="dlx">
    <rabbit:bindings>
        <rabbit:binding key="q.with.dlx" queue="dlq"/>
    </rabbit:bindings>
</rabbit:direct-exchange>
     如果 exchange 或者 queue 是 镜像/持久的,那么需要先删除再启动 spring-amqp 程序,这样 xml 中的 exchange 和 queue 配置才能生效,
否则服务器端配置不会修改,启动生成者时抛异常,启动失败。
     对于部署,可以考虑使用新队列来避免需要先删除已有队列的问题。


<?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:context="http://www.springframework.org/schema/context"
       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 http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/rabbit http://www.springframework.org/schema/rabbit/spring-rabbit.xsd">

    <description>Spring公共配置 </description>

    <!--配置connection-factory,指定连接rabbit server参数 -->
    <rabbit:connection-factory id="connectionFactory"
                               host="192.168.87.108" port="5672" username="admin"
                               password="admin" virtual-host="/"/>

    <!--通过指定下面的admin信息,当前producer中的exchange和queue会在rabbitmq服务器上自动生成 -->
    <rabbit:admin connection-factory="connectionFactory" />
    <rabbit:template id="amqpTemplate" connection-factory="connectionFactory" />

    <rabbit:queue name="delayQueue" durable="true" auto-delete="false" exclusive="false" />
    <rabbit:direct-exchange name="dlx">
        <rabbit:bindings>
            <rabbit:binding key="q.with.dlx" queue="delayQueue"/>
        </rabbit:bindings>
    </rabbit:direct-exchange>


    <!--定义queue  说明:durable:是否持久化 exclusive: 仅创建者可以使用的私有队列,断开后自动删除 auto_delete: 当所有消费客户端连接断开后,是否自动删除队列-->
    <rabbit:queue name="initQueue">
       <rabbit:queue-arguments>
           <entry key="x-dead-letter-exchange" value="dlx"/>
           <entry key="x-dead-letter-routing-key" value="q.with.dlx"/>
           <entry key="x-message-ttl" value="10000" value-type="java.lang.Long"/>
       </rabbit:queue-arguments>
    </rabbit:queue>

    <rabbit:direct-exchange name="initEx">
        <rabbit:bindings>
            <rabbit:binding key="test" queue="initQueue"/>
        </rabbit:bindings>
    </rabbit:direct-exchange>




<!--    <rabbit:queue name="${rabbit.queue.event.delay}" durable="true" auto-delete="false" exclusive="false"/>-->

    <!-- 消息接收者 -->

    <!--<bean id="initConsumer" class="com.honglu.upgrade.mq.handlers.InitConsumer">-->
        <!--<property name="exchange" value="${rabbit.exchange.event}"/>-->
        <!--<property name="dlxRoute" value="${rabbit.route.dlx}"/>-->
    <!--</bean>-->
    <!--<bean id="delayConsumer" class="com.honglu.upgrade.mq.handlers.DelayConsumer">-->
        <!--<property name="exchange" value="${rabbit.exchange.event}"/>-->
        <!--<property name="dlxRoute" value="${rabbit.route.dlx}"/>-->
    <!--</bean>-->
    <!-- queue litener 观察 监听模式 当有消息到达时会通知监听在对应的队列上的监听对象 -->
    <!--<rabbit:listener-container connection-factory="connectionFactory" acknowledge="manual" concurrency="2">-->
        <!--<rabbit:listener  queues="${rabbit.queue.event.init}"  ref="initConsumer"/>-->
    <!--</rabbit:listener-container>-->

    <!--<rabbit:listener-container connection-factory="connectionFactory" acknowledge="manual" concurrency="2">-->
        <!--<rabbit:listener  queues="${rabbit.queue.event.delay}"  ref="delayConsumer"/>-->
    <!--</rabbit:listener-container>-->


</beans>

 
常见问题:
     原因:queue已经存在,但是启动 consumer 时试图设定一个 x-dead-letter-exchange 参数,这和服务器上的定义不一样,server 不允许所以报错。如果删除 queue 重新 declare 则不会有问题。或者通过 policy 来设置这个参数也可以不用删除队列。
     参考 blog
 
参考:

猜你喜欢

转载自blog.csdn.net/m0_37542889/article/details/80405404