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

发布于 2024-11-03 04:15:38 字数 446 浏览 6 评论 0原文

给定:

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

问题

只要消息正在处理中,就无法在不破坏工作流状态的情况下取消部署消息驱动 Bean。因此,我们首先停止计时器服务并等待所有消息完成。

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

非解决方案

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

Given:

  • A JMS message queue.
  • A timer service which puts messages to that queue periodically (from a database).
  • A JEE6 message-driven bean which reads from the queue.
  • The timer service and the message-driven bean are part of different deployment units.

Problem:

The message-driven bean cannot be undeployed, without breaking the workflow state, as long as messages are work in process. Because of that, we stop the timer service first and wait until all messages are finished.

Is there a way to automate that behavior? Or is it possible to prevent undeployment if the timer service is still running? We are currently using JBoss 4.2.3.

Non-Solutions:

  • Refactoring the deployment units, because it would involve several departments.
  • I know that a system crash won't be covered and that a bulletproof solution should include a recovery strategy.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

巴黎盛开的樱花 2024-11-10 04:15:38

每个部署的 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 让您的 MDB 依赖 于计时器@Depends("定时器服务ObjectName")注释。这将强制计时器服务在 MDB 启动之前启动(因此最好让计时器服务有一些启动后延迟),但更重要的是,我相信在取消部署时会发生相反的情况,并且计时器服务应该首先停止,然后是 MDB。

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

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

好的,所以您想防止 MDB 在馈送队列有深度时停止大于零。这种方法应该适合您,尽管它是针对 JBoss 的。

  1. 实现一个 JMX NotificationListener 来侦听状态更改MDB 委托 MBean。
  2. 您还可以实现 JMX NotificationFilter 来缩小范围您想收听的特定事件。
  3. 您要查找的状态更改位于属性 State 上,您要查找的转换是 3 --> 1已启动 --> 正在停止
  4. [此版本] JBoss 中的 JMX 通知是同步发出的,并且会阻塞,直到通知侦听器返回。当您的侦听器收到此通知时,在 MDB 的馈送队列 MBean 上启动轮询循环(没有询问您是否正在使用 JBoss Messaging,但我假设您正在使用)。而 MessageCount 为 > 0,你继续轮询。当队列的消息计数为零时,侦听器返回并且 MDB 将停止。
  5. 确保在轮询循环中添加短暂的睡眠,以及轮询超时(以防事情变得异常)。
  6. 您还可以考虑在至少 n 个轮询循环中消息计数为 0 之前不返回,以防传输中存在一些未提交的消息,这些消息可能不会显示在消息计数中。

最重要的是,当您的属性更改侦听器被调用时,消息将继续被处理。当属性更改侦听器返回时,MDB 停止将继续。

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

Each deployed MDB has a JMX management interface MBean. The ObjectName of this MBean varies according to deployment (and might also be different between versions of JBoss). I am using JBoss 4.3 and the ObjectName format is:

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

If your timer service is a JBoss ServiceMBean, you can make your MDB depend on the timer by using the JBoss @Depends("the timer service ObjectName") annotation. This will force the timer service to start before the MDB starts (so preferably, make the timer service have some post start delay) but more importantly, I believe the reverse will occur on undeploy and the timer service should stop first, then the MDB.

If that works, it takes care of ordering, but I don't think you can force the MDB not undeploy while the timer is running. The details of your application might not support this, but one way you might consider resolving this issue is to use the JBoss Quartz JCA Inflow Adapter which will essentially bind the timer and message processor into one (it's like an MDB, but it receives timer events rather than messages), ridding you of having to wrestle with dependencies between two components.

================================
Attempt #2
================================

Ok, so you want to prevent the MDB from stopping while the feeding queue has a depth of more than zero. This approach should work for you, although it is highly specific to JBoss.

  1. Implement a JMX NotificationListener that listens on state changes of the MDB Delegate MBean.
  2. You can also implement a JMX NotificationFilter to narrow down the specific events you want to listen on.
  3. The state change you're looking for is on the attribute State and the transition you're looking for is 3 --> 1 (Started --> Stopping)
  4. JMX notifications in [this version of] JBoss are issued synchronously and will block until the notification listener returns. When your listener receives this notification, start a polling loop on the MDB's feeding queue MBean (did not ask if you were using JBoss Messaging but I will assume you are). While the MessageCount is > 0, you keep polling. When the queue's message count is zero, the listener returns and the MDB will stop.
  5. Make sure to add a brief sleep in your polling loop, as well as a polling timeout (in case things get whacky).
  6. You might also consider not returning until the message count is 0 for at least n polling loops in case there is some uncommited message in transit which might not show up in the message count.

The bottom line is that while your attribute change listener is being called, message will continue to be processed. When the attribute change listener returns, the MDB stop will continue.

If your JMS implementation is the local in-VM JBoss Messaging, the queue message count will be available in the queue's management MBean. For any other setup, you may need to make a proprietary JMS API call to get the queue's message count, or, using a more brute force approach, you can simply request a JMS QueueBrowser and count the number of messages.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文