我们在上面几篇文章中介绍了ActiveMQ的使用、消息的几种模型,以及消息的确认机制。在消息确认机制这里面其实有个问题没有说清楚,那就是自动应答,消息何时被确认的呢?

       当我们设置session为自动应答方式,而在消费端进行消费。有两种方式进行消费,第一就是使用consumer.receive()方法,这个方式是阻塞式的方法,也就是同步的方法。该方法将阻塞直到获得并返回一条消息。这种情况下,消息返回给方法调用者之后就自动被确认了。也就是说consumer会阻塞,直到producer发送给consumer一条消息,然后producer会自动确认发送了消息。

            还有一种异步的方式,也就是采用listener方式,重写onMessage方法,当这个方法处理完,会自动发出确认信息给producer

         当我们在onMessage方法中发生异常,那么这个消息就不会被确认。然后消息退回给broker重新分配consumer,当其他消费者也和这个消费者一样,得到异常。那么这个消息就会进入发送->异常->退回的死循环。

   我们前面文章说了,在ActiveMQ中默认设置了6次应答,那么6次之后,这个消息就会被扔到一个队列中,叫死信队列。

      ActiveMQ官方文档中介绍了,在以下情况下,会将消息写到死信队列中。

分布式消息队列ActiveMQ(六)死信队列_java

   ActiveMQ默认配置的死信队列是ActiveMQ.DQL,客户端可以调用ActiveMQConnection.getRedeliveryPolicy()方法来设置死信队列参数。如下所示:

分布式消息队列ActiveMQ(六)死信队列_java_02


也可以使用配置文件进行配置,一共有以下几种情况:

1)当不使用缺省的死信队列时,我们可以在Activemq.xml中为每一个消息队列进行配置一个死信队列。如下所示:


分布式消息队列ActiveMQ(六)死信队列_java_03


2)如果想配置过期消息不写入死信队列,可以如下配置:


分布式消息队列ActiveMQ(六)死信队列_java_04


3)配置将非持久化消息写入死信队列


分布式消息队列ActiveMQ(六)死信队列_java_05


4)设置持久化消息不写入死信队列

       对于过期的消息,可以通过processExpired属性来控制,对于redelivered的失败的消息,需要通过插件来实现如下:

分布式消息队列ActiveMQ(六)死信队列_java_06

总结:

       在ActiveMQ中,死信队列是一个很重要的问题。因为系统运行时间长了,很多没有被接收处理的消息进入死信队列中。会保证死信队列的内存暴增并且难于管理。我们可以通过配置策略进行配置,比如我们过期的消息(比如6次没有应答的消息,当然次数可以配置)不进入死信队列、持久化的消息不进入死信队列。当然,消息进入死信队列,也是通过监听死信可以读取处理的。