控制MDB中的并发和消耗

时间:2015-11-11 13:33:37

标签: java-ee jboss ibm-mq message-driven-bean

在MDB中是否有控制并发和消耗的标准方法?我能够找到的每个建议似乎都是应用服务器或资源适配器特定的(例如 maxSession @ActivationConfigProperty)。

The Problem™

我们在双节点JBoss设置(EAP 6.3)上运行一些相对繁重的分析工作,并希望并行化作业以及对并发作业数施加上限,因此我们不会淹没数据库服务器。作业是从Web前端启动的,应该在有免费处理槽时启动 - 没有优先级或排序约束。我们使用消息队列(IBM WMQ,因为政治)将“开始分析”消息分发给节点。

当前进度

经过大量的调整后,根据各种建议,结果证明是非工作资源 - 适配器特定的Cargo-Cult Misinformation™:),我这个问题通过定义EJB池解决了对于MDB。这确实解决了并发问题,但不幸的是,似乎没有空闲MDB的节点仍然会拉取队列的消息 - 这可能会使一个节点未得到充分利用而另一个节点完全加载了积压。

如果我正确理解IBM documentation,则应使用 readAheadAllowed 配置选项控制此行为,但这似乎不会影响我的结果。

那么,是吗:

  • 控制消息消耗的Java EE标准方法?
  • A(工作)IBM WQ特定配置选项?
  • JBoss特定的修复方法吗?
  • 其他一些我没有想过的智能解决方案?

或者我可能会重新设计架构以使用主题队列,并让每个节点尝试UPDATE Projects SET Status='inprogress' WHERE Id=42 AND Status='inqueue';行 - 但是如果我不需要,我宁愿不去那里,主要是因为获取队列所需的变更请求的更改:)

2 个答案:

答案 0 :(得分:1)

MQ,实际上是JMS,经过精心设计和优化,可以尽可能快地将消息尽可能地传递给管道。队列管理器跟踪每个消息的状态,但并发要求将要求QMgr跟踪彼此相关的消息状态。 MQ不这样做。

调整Activation Spec连接池和事务范围中的一些连接池有一些粒度,但这些粒度旨在影响服务器的动态行为,而不是精确指定它。

跨多个消息管理应用程序状态正是IBM Integration Broker等ESB产品的设计目标。虽然MQ是仅查看消息头以执行路由和传递的传输,但ESB会查看消息关系和内容。除非JMS规范定义了并发管理API,否则这种责任分工与MQ进行传输和ESB进行处理的可能性不大。

无论是在ESB代码还是JEE代码中实现,您所描述的内容都是来自Message Dispatcher Pattern本书的Enterprise Integration Patterns,其中一个是 权威消息中的权威架构引用世界。根据仪器的偏好,有几种方法可以写这个。

标记化

  1. 应用程序实例在令牌队列和同步点下执行GET等待。
  2. 收到令牌消息后,应用PUT在令牌队列上再次显示相同的消息,同样在同步点下。
  3. 应用程序在同步点下的应用程序队列上执行GET等待。
  4. 收到应用程序消息后,应用程序会对其进行处理,然后根据需要执行COMMITROLLBACK
  5. 在处理应用消息之前,应用实例会竞争令牌消息。结果是,app消息通常在到达时处理得很快,但在加载时,max concurrency等于令牌消息的数量。

    通常,令牌消息是信息性的,例如包含随每次迭代递增的计数器以及可能用于写入令牌消息的最后一个应用的实例信息。这提供了一些关于正在发生的事情的诊断见解。在某些情况下,监控应用程序还会侦听令牌队列以对该信息进行采样并写入仪表板。在这种情况下,会向队列中添加额外的令牌消息,以说明监控应用程序的活动。

    独立调度程序

    1. 调度程序应用程序在广告的目标队列上侦听消息,并在ACK队列上侦听确认消息。
    2. 计数器将未完成的消息与调度程序应用程序配置中设置的{max outstanding message limit}进行比较。
    3. 如果未完成的消息<限制,消息被移动到应用程序的输入队列,未完成的消息计数器递增。
    4. 当业务应用程序GET成为消息时,它还会向调度程序的ACK队列发送一条消息,这两个操作都在同步点下。
    5. 当业务应用程序发出COMMIT时,调度程序收到ACK并减少未完成的消息计数器。
    6. 调度程序应用程序可以请求确认传递消息,但这些消息并不总是与成功处理事务的业务应用程序相关联。如果业务应用程序明确地将ACK消息放在与消耗的业务消息相同的工作单元中,那么结果就是坚实的。

答案 1 :(得分:1)

我最终使用了我的" 或者我可以[...] "方法 - 改变"开始分析"到广播消息,并使用SQL语句中的status子句处理节点选择。

这是一个简单的解决方案,它不会增加额外的复杂性,并且在实践中已经发挥得非常好 - 它已经在生产中运行了大约一年。