WebSphere Application Server V8.x如何处理有害消息

IBM WebSphere Application Server版本8和更高版本(V8.x)支持基于Java™消息服务(JMS)版本1.1规范的异步消息传递。 使用缺省消息传递提供程序或IBM WebSphere MQ,可以编写在目标(消息队列或主题)上侦听的消息驱动Bean(MDB)。 当消息到达目的地时,将调用MDB并调用其onMessage()方法。 如果“毒性消息”传递到MDB,则应用程序可以选择拒绝它。

在这种情况下,消息发生了什么,应用程序服务器的行为如何?

什么是毒药讯息?

带毒消息只是接收MDB应用程序无法处理的消息。 可能是消息已损坏,格式异常或包含MDB业务逻辑无法处理的信息。 例如,假设您有一个处理预订单的MDB。 如果MDB收到不存在的书籍的订单,则该消息可能被视为有害消息。

如果有毒消息传递到MDB,则Bean可以执行以下三种操作之一:

  • 将消息回滚到它来自的目的地。

    如果MDB在事务中运行,并且可以确保消息不会丢失,则可以这样做。 将消息返回到其原始目的地将使MDB有机会再次处理该消息。 如果应用程序由于临时问题(例如数据库不可用)而无法处理该消息,则此功能很有用。 要回滚消息,MDB应该在与Bean关联的消息驱动的上下文上调用setRollbackOnly()方法。

  • 将邮件移到其他目的地。

    当MDB不在事务内部运行时,这特别有用,因为它可以防止有害消息丢失。 系统管理员可以在以后检查该消息,以找出无法处理该消息的原因,并有可能将其移回MDB监视的目标,以便可以对其进行重新处理。

  • 通过不执行任何操作来丢弃该消息。

    这意味着消息永远消失了。

MDB应用程序有责任确定它是否收到了有害消息,以及如何处理它。 JMS提供者或应用程序服务器无法确定消息是否已损坏或无法处理。

回滚毒消息

在事务内部运行的MDB可以选择回滚无法处理的消息。 在这种情况下,应用服务器会做什么? 答案取决于所使用的JMS提供程序。

使用默认的消息传递提供程序

配置为使用默认消息传递提供程序的MDB监视由服务集成总线托管的队列或主题空间。 当消息到达队列或在主题上发布时,它们将传递到MDB。 当MDB回滚消息时,应用程序服务器的行为取决于三个属性的值:

  • JMS消息属性“重新交付计数”指示将JMS消息传递给应用程序的次数。 如果MDB在传递后拒绝了该消息,则增加此属性。
  • JMS目标属性“ 最大失败传递数”指定在将目标消息移至为此目标定义的异常目标之前,将目标消息传递到MDB的次数。 该属性的默认值为5,这意味着如果将一条消息回滚五次,则应用程序服务器会将其移动到其他位置。 可以在WebSphere Application Server管理控制台中的目标的配置面板上更改此属性(图1)。
图1. TestDestination的最大失败交付数属性
WebSphere Application Server V8.x如何处理有害消息

JMS目标属性Exception destination告诉应用程序服务器如何处理已回退的有毒消息,该消息已在“最大失败传递数”属性中指定的次数。 异常目标属性可以具有以下三个值之一:

  • 系统:将消息路由到系统异常目标_SYSTEM.Exception.Destination。<消息引擎名称>
  • 无:将邮件保留在原始目的地。
  • 指定:将消息移至用户指定的异常目标。

此属性的默认值为System,因此所有回滚超过“最大失败传递次数”的邮件都将移至为承载目标的消息传递引擎定义的系统异常目标。 像“最大失败交付数”属性一样,可以通过WebSphere管理控制台中目标的配置面板来更改Exception目标(图2)。

图2. TestDestination的异常目标设置为“ System”
WebSphere Application Server V8.x如何处理有害消息

如果“异常目标”属性设置为“无”,则默认情况下,应用程序服务器将查看消息传递引擎属性“ 默认阻止的目标重试间隔”的值,以确定将有毒消息重新传递到MDB之前要等待的时间。 此属性的默认值为5000毫秒,相当于5秒。

图3.默认阻止的目标重试间隔
WebSphere Application Server V8.x如何处理有害消息

您可以通过设置两个JMS目标属性来为单个JMS目标覆盖此时间段:

  • 您可以选择覆盖消息传递引擎阻止重试超时默认值
  • 您可以将“ 阻止的重试超时”(以毫秒单位)设置为0或更大的值。 此属性的默认值为-1 当您将该属性设置为该值并选择“ 覆盖消息传递引擎阻止的重试超时默认值”时,“默认阻止的目标重试间隔”(消息传递引擎属性)的值用于确定将消息重新传递到MDB之前要等待的时间。
图4. TestDestination的阻塞重试超时(以毫秒为单位)设置为10000毫秒(或10秒)
WebSphere Application Server V8.x如何处理有害消息

回滚邮件时,其“重新投递”计数会增加,并与邮件最初来自的目标的“最大失败传递数”的值进行比较。

如果“重新交付”计数小于“最大失败传递数”,则邮件将返回到目的地,以便可以对其进行重新处理。

如果重新交付计数等于或大于最大失败传递次数,则消息传递引擎将消息移至指定的Exception目标,或者等待sib.processor.blockedRetryTimeout指定的时间段再尝试再次传递它,如果例外目标设置为无。 此行为如图5所示。

图5.默认消息传递提供程序如何处理有害消息
WebSphere Application Server V8.x如何处理有害消息

默认行为

默认情况下,“最大失败交付数”属性的值为5,“例外”目标设置为“系统”。 如果使用这些默认值,当有毒消息到达目标然后传递到MDB时会发生什么?

  1. 由于MDB无法处理该消息,因此它将回滚,这导致重新交付计数增加到1。消息传递引擎将消息返回到目标,因为重新交付计数小于目标的最大失败传递数。
  2. MDB再次接收到该消息,但是仍然无法处理它,因此MDB像以前一样执行回滚。 现在,邮件的重新交付计数设置为2,这仍小于目标的最大失败传递次数,因此邮件传递引擎将邮件放回其原始位置。
  3. 重复此模式,直到消息回滚5次为止。
  4. 现在,“重新交付”计数的值与目标的“最大失败交付数”相同。 消息传递引擎没有将消息返回到其原始目标,而是将消息移动到目标的Exception目标,该目标指定为_SYSTEM.Exception.Destination.<messaging engine name>

使用WebSphere MQ消息传递提供程序

使用WebSphere MQ消息传递提供程序的MDB可以使用**规范或侦听器端口来监视WebSphere MQ托管的队列或主题。 将消息放入队列或在特定主题上发布时,**规范或侦听器端口会检测到该消息并将其传递到MDB。

当MDB回滚消息时,应用程序服务器的行为会有所不同,具体取决于MDB是绑定到**规范还是侦听器端口。

**规范

如果配置为使用**规范的MDB回滚消息,则应用程序服务器的行为取决于五个属性:

  • 前两个:
    • 如果消息传递失败则停止端点,并且
    • 挂起端点之前顺序传递失败的次数

    是**规范的高级属性,它们一起确定在回滚消息后是否应该停止**规范。

    如果消息传递失败,停止端点属性是一个复选框。 选中后,**规范将保留使用它的MDB执行的回滚数量的计数。 回滚消息时,回滚计数器增加一。 当消息由MDB成功处理时,回滚计数器将重置为零。

    如果回滚计数器达到挂起端点属性之前“顺序传递失败次数 ”所指定的值,则**规范将停止。

    默认情况下,选中“ 如果消息传递失败 ,则停止端点”复选框,并且“ 挂起端点之前顺序传递失败次数”属性的值为0。这意味着,一旦MDB回滚消息,**规范就会停止。 可以在WebSphere管理控制台中的**规范的“高级属性”面板上更改这些属性(请参见图6)。

    图6.如果消息传递失败,则停止端点;在挂起TestActivationSpec的端点属性之前,顺序传递失败的次数
    WebSphere Application Server V8.x如何处理有害消息
  • JMS消息属性“重新交付计数”指示将JMS消息传递给应用程序的次数。 如果MDB在传递后拒绝了该消息,则增加此属性。
  • WebSphere MQ队列属性回退阈值 (BOTHRESH)指定消息在移至其他位置之前可以放入队列的最大次数。 此属性的默认值为0,这意味着**规范将永远不会尝试重新排队已由MDB回滚的消息。 可以使用WebSphere MQ命令行实用程序runmqsc或WebSphere MQ Explorer中的Queue Properties面板(图7)来设置Backout阈值
    图7.测试队列的回退阈值属性
    WebSphere Application Server V8.x如何处理有害消息
  • WebSphere MQ队列属性“回退重新排队队列” (BOQNAME)是在将消息回滚到队列上(在“回退阈值”属性中指定的次数)后,消息被移动到的队列位置。 回退重新排队队列没有默认值,这意味着应用程序服务器会将超过回退阈值的所有消息移至SYSTEM.DEAD.LETTER.QUEUE。 可以使用WebSphere MQ实用程序runmqsc或WebSphere MQ Explorer来设置Backout重新排队队列属性。 队列属性面板如图8所示。
    图8.测试队列的Backout requeue queue属性设置为SYSTEM.DEAD.LETTER.QUEUE
    WebSphere Application Server V8.x如何处理有害消息

    当**规范在JMS目标上检测到消息时,它要做的第一件事就是将消息的“重新交付”计数的值与队列的“退出”阈值的值进行比较。 如果“重新交付计数”小于“回退”阈值,则将邮件传递到MDB进行处理。 但是,如果“重新交付”计数等于“退出”阈值,那么WebSphere MQ消息传递提供程序会将消息移至“退出”重新排队队列。 如果未定义“回退”重新排队队列,则消息将移至SYSTEM.DEAD.LETTER.QUEUE。

    如果消息传递到MDB,然后回滚,则**规范会将消息放回消息源所在的JMS目标,并增加“重新交付计数”的值。

    然后,**规范检查是否选中了“如果消息传递失败,停止端点”复选框。 如果是,则**规范会递增其内部回滚计数器,并将该计数器的值与挂起端点属性之前的“顺序传递失败数”的值进行比较。 如果两个值相等,则**规范将停止。

    此行为如图9所示。

    图9.使用WebSphere MQ JMS Provider时,应用程序服务器如何处理有害消息
    WebSphere Application Server V8.x如何处理有害消息

默认行为

默认情况下,选中“ 如果消息传递失败 ,则停止端点”复选框,“ 在挂起端点之前顺序传递失败次数”属性的值为0,并且“退出阈值”和“退出重排队队列”属性均没有值。 因此,当有毒消息传递到使用**规范来监视由WebSphere MQ托管的JMS目标的MDB时,默认行为是什么?

MDB回滚该消息,这意味着该消息的“重新交付”计数将增加到1。**规范现在检查“ 如果消息传递失败,停止端点”复选框并找到已选中的消息,因此它将增加回滚计数器。

然后,**规范在挂起端点属性之前检查“ 顺序传递失败数”的值,并将其与回滚计数器的值进行比较。 由于回滚计数器大于挂起端点之前的顺序传递失败数 ,因此将停止**规范。

重新****规范后,它将再次检测有害消息,并将消息的重新发送计数与队列的“退出阈值”属性的值进行比较。 此属性没有值,因此消息将传递到MDB。 如果MDB仍然无法处理它,则消息将被回滚到队列中,并且其“重新传递”计数将增加为2。再次,**规范将检查“ 如果消息传递失败 ,则停止端点”复选框,发现它是选择并增加回滚计数器。 现在,回滚计数器的值为2,该值大于挂起端点之前的顺序传递失败数值,因此**规范将再次停止。

下次重新启动**规范时,它将检测到该消息,并将重复整个周期。

由于此行为,有可能最终导致有毒消息阻止队列中其他消息的处理的情况。

回滚消息后,它将返回到队列中的原始位置。 **规范始终从队列顶部开始处理消息,因此,如果队列上的第一条消息是有害消息,则**规范将对其进行检测,并将其传递到MDB。 由于无法处理该消息,因此MDB会将其回滚,这将使其再次回到队列的顶部。 然后将关闭**规范。 重新启动时,**规范将再次检测该有害消息,并将其重新传递到MDB。 MDB将其回滚,再次导致**规范停止。

更改默认行为

如您所见,默认行为将继续,直到系统管理员从队列中删除有害消息为止。

为防止这种情况发生,您需要:

  • 确保由**规范监视的队列同时定义了回退阈值和回退重排队队列。
  • 要么:
    • 取消选择“如果消息传递失败 ,则停止端点”复选框,或者
    • 保留“ 如果邮件传递失败时停止端点”复选框,并将“ 挂起端点之前顺序传递失败次数”属性设置为大于“回退阈值”的值。

例如,假设您有一个定义为TestActivationSpecification的**规范,该规范正在监视WebSphere MQ队列测试中的消息。 **规范具有选中“ 如果消息传递失败 ,则停止端点”复选框,并且“ 挂起端点之前顺序传递失败次数”属性设置为值5。队列测试的回退阈值为1,回退重排队队列为SYSTEM.DEAD。信队列。

消息到达队列测试,由**规范检测到,并传递到您的MDB。 现在,假设您的MDB无法处理此消息并将其回滚。 邮件的重新交付计数现在设置为1。

WebSphere MQ消息传递提供程序选中**规范的消息传递失败时停止端点复选框,并发现该规范已被选中,因此增加了回滚计数器。

然后,它将回滚计数器的值与挂起端点属性之前的顺序传递失败数(Number of)的值进行比较,该值的值为5。该值大于回滚计数器的值,因此**规范继续运行。

下次**规范检测到消息时,WebSphere MQ消息传递提供程序检查消息的Redelivery计数并发现其值为1。它现在查看队列测试的Backout阈值,该阈值也为1。因此, WebSphere MQ消息传递提供程序决定退回消息。

WebSphere MQ消息传递提供程序查询队列的Backout重新排队队列属性。 它设置为SYSTEM.DEAD.LETTER.QUEUE,因此WebSphere MQ消息传递提供程序从测试队列中除去消息,并将其放入该消息队列中。

然后,**规范返回到监视队列测试以了解更多消息到达。

最大服务器会话数属性如何影响有害消息

**规范的高级属性“最大服务器会话数”定义可以同时处理的最大消息数。 如果此属性的值为10,并且**规范正在监视目标上的10条消息,则与**规范关联的内部服务器会话将同时处理所有10条消息。

重要的是要注意,如果为**规范选择了“如果消息传递失败 ,则停止端点”复选框,并且“ 在挂起端点之前顺序传递失败次数”属性设置为大于零的值,则**将维护回滚计数器规范适用于所有服务器会话。

这意味着,如果不同的毒害消息同时通过不同的服务器会话回滚,则**规范可能会停止,而不会尝试将毒害消息移至回退队列。

除此之外,一旦服务器会话成功处理了**规范检测到的消息,则**规范的回滚计数器将重置为零。

例如,假设我们的**规范testActivationSpecification具有:

  • 如果选择了邮件传递失败,则停止端点
  • 挂起端点属性之前的顺序传递失败数设置为3。
  • “最大服务器会话数”属性设置为5。

**规范配置为监视名为test的队列,该队列的Backout threshold属性设置为5,Backout队列名称设置为SYSTEM.DEAD.LETTER.QUEUE。

当**规范启动时,队列上有十条毒消息。 怎么了? 好问题。

**规范检测到前五个消息,并将它们传递到五个服务器会话中进行处理。

第一个服务器会话将第一条有害消息传递给MDB。 MDB尝试对其进行处理,发现它无法进行处理,并将其回滚到队列中。 现在将消息的重新交付计数设置为1,并将与**规范关联的回滚计数器设置为1。

并行地,第二个服务器会话将第二个有害消息提供给同一MDB的另一个实例。 此MDB实例尝试处理该消息,但无法进行处理,因此将其回滚到队列中。 现在,此消息的重新交付计数设置为1。**规范的内部回滚计数器设置为2。

在进行所有这些处理的同时,第三个服务器会话将第三个有害消息传递给另一个MDB实例。 此MDB实例还回滚该消息,因为它无法处理它。 第三个有害消息的重新交付计数设置为1,更重要的是,**规范的回滚计数器设置为3。

此时,WebSphere MQ消息传递提供程序检测到回滚计数器等于挂起**规范的端点之前的顺序传递失败数。 结果,WebSphere MQ消息传递提供程序停止了**规范。

毒消息4和5仍将分别由服务器会话4和5处理,因为该消息是在**规范停止之前提供给服务器会话的。

也有可能在停止**规范之前也处理了毒气消息6和7。 这是因为一旦这些服务器会话回退了毒害消息1和2,它们将被传递到第一和第二服务器会话。

为了更改此行为,并确保**规范始终尝试将有害消息移至指定的退出队列而不是停止,请确保选中“ 如果消息传递失败 ,则停止端点”复选框。

侦听器端口

自WebSphere Application Server V5起,侦听器端口已可用,并且为MDB提供了一种替代机制,以监视消息的JMS目标。 自WebSphere Application Server V6.1以来,侦听器端口的行为未更改,并且自WebSphere Application Server V7起已稳定,这意味着一段时间以来没有向其添加任何新功能。

这意味着,developerWorks文章WebSphere Application Server V6如何处理有害消息中的侦听器端口上的信息对于WebSphere Application Server V8和更高版本仍然有效。

WebSphere MQ安全性注意事项

一个经常出现的问题是:

为了撤消消息,我的WebSphere Application Server系统需要什么WebSphere MQ授权?

为了使WebSphere Application Server可以回退消息,在其下运​​行应用程序服务器的用户标识必须对回退重排队队列具有以下许可权:

  • 得到
  • 查询
  • 传递所有上下文
  • 设置所有上下文

如果应用程序服务器没有这些权限,则应用程序服务器会将消息移至为队列管理器定义的死信队列。

在z / OS上使用WebSphere MQ提供程序

在z /OS®上使用WebSphere MQ JMS提供程序时,处理有毒消息的方式与上述相同,只有一点点差异。

z / OS上的WebSphere MQ使用消息的内存中副本。 侦听器端口首次检测到消息时,WebSphere MQ在将消息的副本传递到应用程序服务器之前将其副本存储在内存中。 如果成功处理了该消息,则将删除内存中的副本,并从存储中删除实际的消息。

在MDB回滚消息的情况下,WebSphere MQ将增加内存中副本的Redelivery计数。 然后,应用程序服务器在副本上查看此属性的值,以确定是否将实际消息移至“回退”重新排队队列,以及是否应停止侦听器端口。 如果内存中副本的“重新交付”计数的值大于“退出”阈值,则将实际消息移至“退出”重新排队队列,然后删除内存中副本。

如果在撤消消息之前停止WebSphere MQ系统,则可能产生影响。

假设您定义了一个**规范,称为TestActivationSpec2。 **规范配置为监视WebSphere MQ队列test2中的消息,并在10次连续传递失败后停止。 该队列由运行在z / OS上的WebSphere MQ队列管理器托管,并且Backout threshold属性设置为5:

一条消息到达队列,并被TestActivationSpecfication2检测到。 消息的副本已制作,然后传递到MDB。 但是,该消息无法处理,因此MDB将其回滚。 邮件的内存副本的重新交付计数增加,现在值为1。

**规范再次检测到该消息,然后再次将其传递到MDB,然后在第二次回滚。 邮件的内存副本现在的重新交付计数为2。

假设此时z / OS队列管理器已关闭。 由于应用程序服务器仅在处理消息的内存副本,因此队列上存储的实际消息的“重新交付”计数仍设置为0。重新启动队列管理器时,**规范将再次检测到消息。 将创建该邮件的新内存副本,其“重新交付”计数为0。当MDB回滚该消息时,该副本的“重新交付计数”的值将增加为1。

这种行为一直持续到MDB将消息回滚5次为止。 此时,应用程序服务器确定消息的内存中副本的重新交付计数等于队列的Backout阈值,然后将实际消息移至Backout重新排队队列属性指定的队列。

在这种情况下,有毒消息实际上已经被处理了七次,然后被撤消,这超过了为队列定义的“撤消”阈值。

此行为是不理想的。

为了防止这种情况的发生,需要将z / OS上的WebSphere MQ配置为在发生回滚时更新存储中实际消息以及内存中副本的重新交付计数。 这意味着重新交付计数值将保持不变,因此可以在队列管理器重新启动后幸免。 为此,需要将MDB监视的队列的HardenGetBackout(HNDBKTCNT)属性设置为YES。

结论

本文描述了什么是毒害消息,并解释了JMS应用程序遇到它们时可以做什么。 您还了解了缺省消息传递提供程序和WebSphere MQ JMS提供程序如何处理MDB回滚有害消息的情况,如何更改缺省行为以及使用WebSphere时某些侦听器端口属性如何影响应用程序服务器的行为。 MQ JMS提供程序。


翻译自: https://www.ibm.com/developerworks/websphere/techjournal/1407_titheridge/1407_titheridge.html