spring activeMQ 死信队列

1:死信队列简介

DLQ-死信队列(Dead Letter Queue)用来保存处理失败或者过期的消息。
出现以下情况时,消息会被redelivered
 A transacted session is used and rollback() is called.
 A transacted session is closed before commit is called.
 A session is using CLIENT_ACKNOWLEDGE and Session.recover() is called.
当一个消息被redelivered超过maximumRedeliveries(缺省为6次,具体设置请参考后面的链接)次数时,会给broker发送一个"Poison ack",这个消息被认为是a poison pill,这时broker会将这个消息发送到DLQ,以便后续处理。
缺省的死信队列是ActiveMQ.DLQ,如果没有特别指定,死信都会被发送到这个队列。
缺省持久消息过期,会被送到DLQ,非持久消息不会送到DLQ
可以通过配置文件(activemq.xml)来调整死信发送策略。

注:本次测试使用的是第三种,使用自行确认接收并且在失败时session.recover()进行恢复.

2:activemq.xml配置

死信队列配置

 <destinationPolicy>
            <policyMap>
              <policyEntries>
                  <policyEntry queue=">">
                     <deadLetterStrategy>
                         <individualDeadLetterStrategy queuePrefix="DLQ."
                          useQueueForQueueMessages="true" />
                     </deadLetterStrategy>
                  </policyEntry>
        
                  <policyEntry topic=">" >                 
                    <pendingMessageLimitStrategy>
                       <constantPendingMessageLimitStrategy limit="1000"/>
                    </pendingMessageLimitStrategy>
                  </policyEntry>
              </policyEntries>
            </policyMap>
</destinationPolicy>

持久化配置(mysql)

<persistenceFactory>  
   <journalPersistenceAdapterFactory journalLogFiles="5" dataDirectory="${activemq.data}/activemq-data" dataSource="#mysql-ds" createTablesOnStartup="true"/>  
</persistenceFactory>  
<bean id="mysql-ds" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <property name="url" value="jdbc:mysql://localhost:3306/activemq?relaxAutoCommit=true" />
        <property name="username" value="root" />
        <property name="password" value="root" />      
        <property name="poolPreparedStatements" value="true"/>
</bean>

3:RedeliveryPolicy重发策略设置

<!-- 真正可以产生Connection的ConnectionFactory,由对应的 JMS服务厂商提供 -->
<bean id="activeMQConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
    <property name="brokerURL" value="tcp://localhost:61636"></property>
    <property name="useAsyncSend" value="true"></property>
    <property name="redeliveryPolicy">
        <bean id="redeliveryPolicy" class="org.apache.activemq.RedeliveryPolicy">
            <!--是否在每次尝试重新发送失败后,增长这个等待时间-->
            <property name="useExponentialBackOff" value="true"></property>
            <!--重发次数,默认为6次-->
            <property name="maximumRedeliveries" value="5"></property>
            <!--重发时间间隔,默认为1秒-->
            <property name="initialRedeliveryDelay" value="1000"></property>
            <!--第一次失败后重新发送之前等待500毫秒,第二次失败再等待500 * 2毫秒,这里的2就是value-->
            <property name="backOffMultiplier" value="2"></property>
            <!--最大传送延迟,只在useExponentialBackOff为true时有效(V5.5),假设首次重连间隔为10ms,倍数为2,那么第 二次重连时间间隔为 20ms,第三次重连时间间隔为40ms,当重连时间间隔大的最大重连时间间隔时,以后每次重连时间间隔都为最大重连时间间隔。-->
            <property name="maximumRedeliveryDelay" value="1000"></property>
        </bean>
    </property>
</bean>

4:send测试类

import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsTemplate;

/**
 * 类描述:sender测试类
 *
 * @author fengyong
 * @version 1.0
 * @since 1.0
 * Created by fengyong on 16/8/3 下午7:45.
 */
public class ActiveMqSender extends BaseTest {
    @Autowired
    private JmsTemplate senderJmsTemplate;

    @Test
    public void activeMq(){
        for(int i = 1;i<=10;i++){
            senderJmsTemplate.convertAndSend("FirstQueue","我是第"+i+"个");
        }
        System.out.print("全部执行完毕!!!");
    }
}

5:receiver测试类

import com.system.freemwork.amq.SimpleJmsTemplate;
import org.apache.activemq.command.ActiveMQQueue;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsTemplate;

import javax.jms.JMSException;
import javax.jms.TextMessage;

/**
 * 类描述:receiver测试类
 *
 * @author fengyong
 * @version 1.0
 * @since 1.0
 * Created by fengyong on 16/8/8 下午5:28.
 */
public class ActiveMqReceiver extends BaseTest {
    @Autowired
    private SimpleJmsTemplate receiverJmsTemplate;
    @Autowired
    private ActiveMQQueue activeMQQueue;

    /**
     * 如果session事物设置为true,receiver直接将sessioin进行commit,
     * <p>
     * 如果设置为false,receiver方法会直接判断进行消息确认,无法做到手动的消息确认,所以一旦发生异常,这条消息不会回到消息队列中
     * <p>
     * session的提交可以认为是消息确认收到
     *
     * @throws JMSException
     */
    @Test
    public void recerver() throws JMSException {
        int i = 1;
        int j = 0;
        String eq = null;
        while (true) {
            i++;
            TextMessage message = (TextMessage) receiverJmsTemplate.receive(activeMQQueue);
            if (null != message) {
                String messageText = message.getText();
                eq = messageText;

                System.out.println("收到消息==================" + messageText);
                if (messageText.equals("我是第2个")) {
                    try {
                        throw new RuntimeException("Exception");
                    } catch (Exception e) {
                        System.out.println("第" + j + "次接收");
                        j++;
                        receiverJmsTemplate.getSessionToUse().recover();
                    }
                }
                receiverJmsTemplate.msgAckAndcloseSession(message);
            } else {
                System.out.print("超时10秒");
                break;
            }
        }
    }
}

6:测试结果

收到消息==================我是第1个
收到消息==================我是第2个
第0次接收
收到消息==================我是第2个
第1次接收
收到消息==================我是第2个
第2次接收
收到消息==================我是第2个
第3次接收
收到消息==================我是第2个
第4次接收
收到消息==================我是第2个
第5次接收
收到消息==================我是第3个
收到消息==================我是第4个
收到消息==================我是第5个
收到消息==================我是第6个
收到消息==================我是第7个
收到消息==================我是第8个
收到消息==================我是第9个
收到消息==================我是第10个

注:这里第一次是默认的,后五次是配置的重新发送,当五次重新发送之后还是失败,那么将会进入死信队列,看下一步

7:死信队列结果





  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值