如何在取消部署之前停止消息处理?

时间:2011-04-26 14:41:24

标签: java-ee deployment jboss jmx message-driven-bean

假设:

  • JMS消息队列。
  • 定时服务,定期(从数据库)将消息放入该队列。
  • 从队列中读取的JEE6消息驱动bean。
  • 计时器服务和消息驱动的bean是不同部署单元的一部分。

问题:

只要消息正在进行中,就不能在不中断工作流状态的情况下取消部署消息驱动的bean。因此,我们首先停止计时器服务,然后等待所有消息完成。

有没有办法自动化这种行为?或者,如果计时器服务仍在运行,是否可以防止取消部署?我们目前正在使用JBoss 4.2.3。

非解决方案:

  • 重构部署单元,因为它涉及多个部门。
  • 我知道不会涉及系统崩溃,并且防弹解决方案应包含恢复策略。

1 个答案:

答案 0 :(得分:2)

每个部署的MDB都有一个JMX管理接口MBean。此MBean的ObjectName因部署而异(并且JBoss版本之间也可能不同)。我使用的是JBoss 4.3,ObjectName格式是:

Domain Name:    jboss.j2ee
service:    EJB3
name:   <MDB Name>
ear:    <EAR Name>  (if applicable)
jar:    <JAR Name>

如果您的计时器服务是JBoss ServiceMBean,您可以使用JBoss @Depends(“计时器服务ObjectName”使计时器上的MDB 依赖 “)注释。这将强制计时器服务在MDB启动之前启动(因此最好使计时器服务具有一些启动后延迟)但更重要的是,我相信在取消部署时将发生相反的情况并且计时器服务应该首先停止,然后停止MDB。

如果可行,它会负责排序,但我不认为您可以在计时器运行时强制MDB不取消部署。您的应用程序的详细信息可能不支持这一点,但您可以考虑解决此问题的一种方法是使用JBoss Quartz JCA Inflow Adapter,它将计时器和消息处理器绑定为一个(它就像一个MDB,但它接收计时器事件而不是消息),摆脱你必须与两个组件之间的依赖关系搏斗。

================================ 尝试#2  ================================

好的,所以你想要防止MDB在进给队列的深度大于零时停止。这种方法应该对你有用,尽管它对JBoss非常具体。

  1. 实现监听MDB Delegate MBean状态更改的JMX NotificationListener
  2. 您还可以实施JMX NotificationFilter来缩小要收听的特定事件的范围。
  3. 您要查找的状态更改位于属性状态,您要查找的转换为 3 - &gt; 1 开始 - &gt;停止
  4. [此版本] JBoss中的JMX通知是同步发出的,并将阻塞,直到通知侦听器返回。当您的侦听器收到此通知时,在MDB的提供队列MBean上启动一个轮询循环(没有询问您是否使用JBoss Messaging但我会假设您是)。虽然 MessageCount 是&gt; 0,你继续投票。当队列的消息计数为零时,侦听器返回,MDB将停止。
  5. 确保在轮询循环中添加一个简短的睡眠,以及轮询超时(如果事情变得糟糕)。
  6. 对于至少 n 轮询循环的消息计数为0,您可能还会考虑不返回,以防在传输过程中出现一些可能未显示在消息计数中的未提交消息。
  7. 最重要的是,在调用属性更改侦听器时,将继续处理消息。当属性更改侦听器返回时,MDB停止将继续。

    如果您的JMS实现是本地in-VM JBoss Messaging,则队列消息计数将在队列的管理MBean中可用。对于任何其他设置,您可能需要进行专有的JMS API调用以获取队列的消息计数,或者,使用更强力的方法,您只需请求JMS QueueBrowser并计算消息数。 / p>