消息再传递及未传递的消息
消息有可能传递失败(比如相关的事务发生回滚)。失败的消息将退回到队列中准备重新传递。这样就会出现
一种情况,就是同一个消息会被反复的传递而总不成功,以至于使系统处于忙的状态。
对于这样的消息我们有两种处理方法:
延迟再传递
这种方法是让消息再次传递时有一定的时间延迟,这样客户端就有机会从故障中恢复,同时网络连接和CPU资源
也不致于被过度占用。
死信(Dead Letter)地址
这种方法是规定一个死信地址,如果消息再被反复传递达到一定次数时,就会从原有队列中删除,转到这个
死信地址中。这样消息就不会永远地重复传递了。
以上两种方法可以合理搭配使用,使解决方案更加灵活。
延迟再传递
延迟再传递对于时常出现故障或回滚的客户端十分有用。如果没有延迟,整个系统可能会处于一种”疯狂“的状态。
就是消息被传递、回滚、再传递,这样反复不间断地进行着,将宝贵的CPU和网络资源占用。
延迟再传递的配置
延迟再传递的配置在地址设定内(address-setting):
<!-- delay redelivery of messages for 5s -->
<address-setting match="jms.queue.exampleQueue">
<redelivery-delay>5000</redelivery-delay>
</address-setting>
如果定义了redelivery-delay,ActiveMQ在再传递之前等待所定义的时间。
默认是没有延时的(即redelivery-delay的值是0)。
可以使用通配符为一组地址定义再传递的延迟(参见)。
例子
参见 。这是一个JMS应用中配置延迟再传递的例子。
死信地址
通过定义一个死信地址也可以防止同一个消息被无休止地传递:
当一个消息被重复传递一定次数后,就会从队列中删除并传递到定义好的死信地址中。
这些死信中的消息之后可以转发到某个队列中,以供系统管理员分析处理。
每个ActiveMQ的地址可以有一个死信地址。当一个消息被反复传递达一定次数时,它就会被从队列中删除并送到
死信地址。这些死信消息可以被接收进行分析处理。
配置死信地址
死信地址定义在地址设定中(address-setting):
<!-- undelivered messages in exampleQueue will be sent to the dead letter address
deadLetterQueue after 3 unsuccessful delivery attempts
-->
<address-setting match="jms.queue.exampleQueue">
<dead-letter-address>jms.queue.deadLetterQueue</dead-letter-address>
<max-delivery-attempts>3</max-delivery-attempts>
</address-setting>
如果没有定义dead-letter-address,消息在经过
max-delivery-attempts次重复传递后被删除。
默认的重复传递次数为10。将max-delivery-attempts设定为-1
表示无限次重复传递。
例如,对一组地址设置了一个通用的死信地址后,再将其中某个地址的max-delivery-attempts
设定为-1时,那么只有这个地址的再传递次数是无限的。
可以使用通配符对一组地址设定死信地址(参见)。
死信的属性
从死信地址接收到的消息有以下属性:
_HQ_ORIG_ADDRESS
这是一个字符串属性,它是该死信消息的原始地址。
例子
参见。这个例子给出了在JMS应用中死信的配置与使用。
传递计数的持久化
通常情况下ActiveMQ在一个消息被回滚之前并不更新持久的传递计数(即在消息传递到接收者之前不会更新传递计数)。
大多数情况下消息被接收、通知、然后被忘掉。这样对每一个消息的传递都要更新一次持久的
传递计数,会显著降低系统的性能。
介是如果在消息传递之前不进行持久传递计数的更新,服务器一旦发生故障而崩溃,就会造成消息可能被传递出去而传递
计数却没有正确反映出传递的結果。在恢复阶段,服务器将错误地将该消息的redelivered设为
false而不是true。
这样是不符合严格的JMS要求的。因此ActiveMQ允许在消息传递前更新传递计数。但是默认不这样做,目的是优先考虑
了它对性能的影响。
要想打开传递计数更新功能,将activemq-configuration.xml文件中的
persist-delivery-count-before-delivery设为true即可:
<persist-delivery-count-before-delivery>true</persist-delivery-count-before-delivery>