级别: 初级 Paul Titheridge (PAULT@uk.ibm.com)IBM WebSphere and Java Messaging Support
2004 年 7 月 01 日 本文描述 WebSphere Application Server V5 提供的嵌入式 JMS Server 如何处理有害消息、如何修改缺省行为以及如果使用 WebSphere MQ 作为消息服务提供程序,则行为如何改变。
引言
WebSphere Application Server V5.x 提供基于 Java™ Messaging Service(JMS)规范的异步消息传递支持。通过使用消息侦听器服务和嵌入式 JMS 服务器或外部消息提供程序(比如 WebSphere MQ),应用程序开发人员可以编写消息驱动 Bean(MDB),它们在 JMS 目的地(一个消息队列,或者一个主题)上侦听,并且在消息到达那个特定的目的地时被调用。如果消息侦听器服务将一个“有害”消息传递给 MDB 应用程序,则该应用程序可以选择拒绝此消息。此时,应用程序服务器怎样处理此消息?
本文假定您具备 JMS 基础知识。
什么是有害消息?
有害消息就是接收该消息的 MDB 应用程序无法处理的消息。该消息可能是已损坏的或是以非预期格式表示的消息。例如,假设您有一个处理 TextMessage 类型 JMS 消息的 MDB。如果消息侦听器服务传递了一个具有不同消息类型的消息,则该消息被认为是有害消息。
遇到有害消息
如果 MDB 发现一个有害消息,它可以做以下三件事之一:
-
将消息回滚到它来自的队列。如果该 MDB 在一个事务中运行,并且确保该消息未丢失,则可以完成此操作。为此,MDB 必须在与它相关的消息驱动上下文中调用 setRollbackOnly() 方法。
-
将消息移动到不同的队列。该方法对于 MDB 没有在一个事务中运行时特别有用,因为该方法能防止有害消息丢失。
-
无需做任何事,丢弃该消息。这表示该消息永远消失。
请牢记 MDB 应用程序的职责是确定它是否收到一个有害消息。JMS 提供程序或消息侦听器服务无法检测一个消息是否已损坏或是否应用程序所期望的 JMS 消息类型。
回滚有害消息
如果在一个事务中运行,则 MDB 可以回滚有害消息。这将导致消息被返回到它来源的队列。JMS 服务器在这种情况下的缺省行为是关闭与 MDB 相关的侦听器端口,主要为防止可能出现的失控状态。
如果侦听器端口没有被关闭,则消息侦听器服务将检测消息到达的受监控的目的地,并且将再次把消息发送给 MDB。然而,该消息仍然是有害消息,所以 MDB 将第二次回滚该消息。
有害消息第一次被回滚时关闭侦听器端口,这会强制应用程序开发人员仔细考虑应用程序和 JMS 服务器应如何处理它们。
更改缺省行为
JMS 服务器的确切行为依赖于三个属性:
- 侦听器端口属性
Maximum retries。
该属性定义了在侦听器端口被停止之前消息侦听器服务向 MDB 尝试发送消息的次数。该属性的缺省值是 0,这表示当第一次出现某个消息无法发送或应用程序拒绝了有害消息时,侦听器端口将自关闭。在 WebSphere 管理控制台中的 Listener Port Settings 面板中可以更改 Maximum retries 属性。
图 1 显示了样本 MDB 应用程序使用的 SamplePtoPListenerPort 的 Listener Port Settings 面板。该端口将 Maximum retries 属性设置为 10。
图 1. 侦听器端口设置
- JMS 消息属性
Redelivery count。
Redelivery count 属性说明消息已被尝试提交给应用程序的次数。在提交消息后,如果消息无法提交或应用程序拒绝该消息(例如,通过回滚事务),则该属性加 1。
- JMS 目的地属性
Backout threshold。
作为 WebSphere Application Server 一部分安装的 JMS 服务器允许用户定义自己的 JMS 目的地。每个以这种方式定义的目的地的 Backout threshold 属性值都固定为 5。当一个消息传送失败的次数等于 Backout threshold 属性值,则 JMS 服务器将把消息移动到缺省队列 SYSTEM.DEAD.LETTER.QUEUE(此队列是无法传送消息的仓库,而不考虑失败原因)。
嵌入式 JMS 服务器首先把消息返回到它源自的目的地。此时,服务器将比较消息 Redelivery count 和为目的地而定义的 Backout threshold 属性值。
如果 Redelivery count 少于 Backout threshold,则把消息留在队列中。然而,如果 Redelivery count 等于 Backout threshold,则把消息移出队列并置于队列 SYSTEM.DEAD.LETTER.QUEUE 中。
何时设置侦听器端口的 Maximum retries 属性?如上所述,该属性指定了在侦听器端口被停止之前消息侦听器服务向 MDB 尝试发送一个消息的次数。该属性的缺省值是 0,这表示当第一次出现某个消息无法发送时,侦听器端口被关闭,并且消息被返回到队列。此时,该消息的 Redelivery count 属性值加 1。
当侦听器端口被重启,它将再次尝试传送消息到 MDB。如果传送失败或消息被再次回滚,则该消息的 Redelivery count 加 1(将该属性设置为 2),然后将关闭侦听器端口。
此行为将持续到消息传送失败或回滚五次,此时该消息被置于 SYSTEM.DEAD.LETTER.QUEUE。这样做的原因是该消息的 Redelivery count 等于队列的 Backout threshold。
如果 Maximum retries 属性值被设置为 6 或更多,则当侦听器端口无法传送一个消息到 MDB 时,它将永远不会自关闭。当侦听器端口第五次发送同一个消息失败时,嵌入式 JMS 服务器将把消息置于 SYSTEM.DEAD.LETTER.QUEUE,而不是消息的原始队列,这是因为 Redelivery count 等于该队列的 Backout threshold 值。
当 JMS 的提供程序是 WebSphere MQ
缺省地,WebSphere MQ 创建的队列将 Backout threshold 属性(在 WebSphere MQ 用术语 BOTHRESH 表示)设置为 0。因此,WebSphere MQ 的缺省行为是从不收回有害消息。这意味着什么?
当 MDB 将有害消息回滚时,该消息被返回到它源自的队列。因为该队列未定义 Backout threshold,有害消息将被留在那里。然而,因为它现在存在于队列中,消息侦听器服务会检测到它并重新发送回 MDB。但这是一个有害消息,所以 MDB 将拒绝该消息,导致它被回滚被返回队列!
这一系列事件将持续直到有害消息被回滚的次数等于侦听器端口的 Maximum retries 属性值。此时,侦听器端口将自关闭。防止这种事情发生的方法是将队列的 Backout threshold 属性值设置为大于 0 而小于侦听器端口的 Maximum retries 属性值。这将确保在侦听器关闭之前回滚并删除任何有害消息。
退回的消息去了哪里?
在使用 WebSphere MQ 时,您可以通过修改队列的 Backout Requeue Name 属性(在 WebSphere MQ 术语中是 BOQNAME)来指定退回消息的目的地。缺省未设置该属性,这表示任何已被回滚的次数等于队列 Backout threshold 属性值的消息将丢失。需要培养的好习惯是将此属性值设置为系统的死信(dead letter)队列(缺省死信队列是 SYSTEM.DEAD.LETTER.QUEUE),因为有害消息实际上是“死信”。
可以使用 WebSphere MQ 提供的命令程序来设置 Backout threshold 和 Backout Requeue Name 属性。
图 2 来自 WebSphere MQ Explorer 实用程序,运行于 Windows® 平台。在此,将称为 CSINPUT_QUEUE 的队列的 Backout threshold 属性值设置为 1,并把 Backout Requeue Name 属性设置为 SYSTEM.DEAD.LETTER.QUEUE。当有害消息第一次被 MDB 检测到并回滚,MDB 将把该消息从 CSINPUT_QUEUE 移至队列 SYSTEM.DEAD.LETTER.QUEUE。
图 2. WebSphere MQ 队列属性
当然,您应该周期性地监控死信队列以检查应用程序接收了多少有害消息。如果死信队列包含了大量的消息,您应该调查这些消息出现的原因。
结束语
本文描述了 WebSphere Application Server V5 中的嵌入式 JMS 服务器提供程序当遇到有害消息时的缺省行为,如何通过修改侦听器端口的属性来更改此行为,以及相同情况下使用 WebSphere MQ 作为 JMS 提供程序时所产生的行为。
参考资料
关于作者  | |  |
Paul Titheridge1995 年 9 月从 Exeter 大学毕业后加入 IBM。在 Voice and Business Integration 部门工作一段时间后,Paul 现在是 WebSphere 和 Java 消息传递支持组的成员,致力于解决那些使用 WebSphere MQ 和 WebSphere Application Server 的顾客的问题。
|
对本文的评价
|