用来保存处理失败或者过期的消息。 

出现下面情况时,消息会被重发: 

  1. 事务会话被回滚。
  2. 事务会话在提交之前关闭。
  3. 会话使用CLIENT_ACKNOWLEDGE模式,并且Session.recover()被调用。 
  4. 自动应答失败

当一个消息被重发超过最大重发次数(缺省为6次,消费者端可以修改)时,会给broker发送一个"有毒标记“,这个消息被认为是有问题,这时broker将这个消息发送到死信队列,以便后续处理。 

在配置文件(activemq.xml)来调整死信发送策略。

消息中间件 - ActiveMQ高级特性和用法-死信队列(九)_发送消息

<destinationPolicy>
<policyMap>
<policyEntries>
<policyEntry queue=">" >
<deadLetterStrategy>
<individualDeadLetterStrategy queuePrefix="DLQ." useQueueForQueueMessages="true" />
</deadLetterStrategy>
<!-- The constantPendingMessageLimitStrategy is used to prevent
slow topic consumers to block producers and affect other consumers
by limiting the number of messages that are retained
For more information, see:

http://activemq.apache.org/slow-consumer-handling.html

-->
<pendingMessageLimitStrategy>
<constantPendingMessageLimitStrategy limit="1000"/>
</pendingMessageLimitStrategy>
</policyEntry>
</policyEntries>
</policyMap>
</destinationPolicy>

可以单独使用死信消费者处理这些死信。参见代码

生产者:

public class DlqProducer {

//默认连接用户名
private static final String USERNAME
= ActiveMQConnection.DEFAULT_USER;
//默认连接密码
private static final String PASSWORD
= ActiveMQConnection.DEFAULT_PASSWORD;
//默认连接地址
private static final String BROKEURL
= ActiveMQConnection.DEFAULT_BROKER_URL;
//发送的消息数量
private static final int SENDNUM = 1;

public static void main(String[] args) {
ActiveMQConnectionFactory connectionFactory;
ActiveMQConnection connection = null;
Session session;
ActiveMQDestination destination;
MessageProducer messageProducer;

connectionFactory
= new ActiveMQConnectionFactory(USERNAME,PASSWORD,BROKEURL);

try {
connection = (ActiveMQConnection) connectionFactory.createConnection();
connection.start();

session = connection.createSession(true,Session.AUTO_ACKNOWLEDGE);

destination = (ActiveMQDestination) session.createQueue("TestDlq2");
messageProducer = session.createProducer(destination);
for(int i=0;i<SENDNUM;i++){
String msg = "发送消息"+i+" "+System.currentTimeMillis();
TextMessage message = session.createTextMessage(msg);

System.out.println("发送消息:"+msg);
messageProducer.send(message);
}
session.commit();


} catch (JMSException e) {
e.printStackTrace();
}finally {
if(connection!=null){
try {
connection.close();
} catch (JMSException e) {
e.printStackTrace();
}
}
}


}


}

消费者:

public class DlqConsumer {

private static final String USERNAME
= ActiveMQConnection.DEFAULT_USER;//默认连接用户名
private static final String PASSWORD
= ActiveMQConnection.DEFAULT_PASSWORD;//默认连接密码
private static final String BROKEURL
= ActiveMQConnection.DEFAULT_BROKER_URL;//默认连接地址

public static void main(String[] args) {
ActiveMQConnectionFactory connectionFactory;
ActiveMQConnection connection = null;
Session session;
ActiveMQDestination destination;

MessageConsumer messageConsumer;//消息的消费者

//实例化连接工厂
connectionFactory
= new ActiveMQConnectionFactory(USERNAME,PASSWORD,BROKEURL);
//限制了重发次数策略
RedeliveryPolicy redeliveryPolicy = new RedeliveryPolicy();
redeliveryPolicy.setMaximumRedeliveries(1);

try {
//通过连接工厂获取连接
connection = (ActiveMQConnection) connectionFactory.createConnection();
//启动连接
connection.start();
// 拿到消费者端重复策略map
RedeliveryPolicyMap redeliveryPolicyMap
= connection.getRedeliveryPolicyMap();
//创建session
session
= connection.createSession(false,
Session.AUTO_ACKNOWLEDGE);
destination = (ActiveMQDestination) session.createQueue("TestDlq2");
// 将消费者端重发策略配置给消费者
redeliveryPolicyMap.put(destination,redeliveryPolicy);
//创建消息消费者
messageConsumer = session.createConsumer(destination);
messageConsumer.setMessageListener(new MessageListener() {
public void onMessage(Message message) {
try {
System.out.println("Accept msg : "
+((TextMessage)message).getText());
} catch (JMSException e) {
e.printStackTrace();
}
throw new RuntimeException("test");
}
});
} catch (JMSException e) {
e.printStackTrace();
}

}
}

消费死信队列

public class ProcessDlqConsumer {

private static final String USERNAME
= ActiveMQConnection.DEFAULT_USER;//默认连接用户名
private static final String PASSWORD
= ActiveMQConnection.DEFAULT_PASSWORD;//默认连接密码
private static final String BROKEURL
= ActiveMQConnection.DEFAULT_BROKER_URL;//默认连接地址

public static void main(String[] args) {
ConnectionFactory connectionFactory;//连接工厂
Connection connection = null;//连接

Session session;//会话 接受或者发送消息的线程
Destination destination;//消息的目的地

MessageConsumer messageConsumer;//消息的消费者

//实例化连接工厂
connectionFactory = new ActiveMQConnectionFactory(ProcessDlqConsumer.USERNAME,
ProcessDlqConsumer.PASSWORD, ProcessDlqConsumer.BROKEURL);

try {
//通过连接工厂获取连接
connection = connectionFactory.createConnection();
//启动连接
connection.start();
//创建session
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
//创建一个连接HelloWorld的消息队列
//destination = session.createTopic("TestDlq");
destination = session.createQueue("DLQ.>");

//创建消息消费者
messageConsumer = session.createConsumer(destination);
messageConsumer.setMessageListener(new MessageListener() {
public void onMessage(Message message) {
try {
System.out.println("Accept DEAD msg : "
+((TextMessage)message).getText());
} catch (JMSException e) {
e.printStackTrace();
}
}
});
} catch (JMSException e) {
e.printStackTrace();
}

}
}

注意,该代码中展示了如何配置重发策略。同时,重试策略属于ActiveMQ的部分,所以有部分connectionFactory,connection的声明等等不能使用接口,必须使用ActiveMQ的实现。

消息中间件 - ActiveMQ高级特性和用法-死信队列(九)_发送消息_02