【问题标题】:Controlling concurrency and consumption in MDB在 MDB 中控制并发和消耗
【发布时间】:2016-02-12 14:37:23
【问题描述】:

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

问题™

我们在双节点 JBoss 设置 (EAP 6.3) 上运行一些相对繁重的分析作业,并希望并行化作业以及对并发作业的数量施加上限,这样我们就不会淹没数据库服务器。作业从 Web 前端开始,只要有空闲的处理槽就应该开始 - 没有优先级或排序限制。我们使用消息队列(IBM WMQ,因为政治原因)将“开始分析”消息分发到节点。

目前进展

根据各种建议进行大量摆弄,结果证明是非工作资源适配器特定货物崇拜错误信息™:),我认为通过定义 EJB 池解决了问题为 MDB。这确实解决了并发问题,但不幸的是,似乎没有空闲 MDB 的节点仍然会拉取队列中的消息 - 这可能会使一个节点未充分利用,而另一个节点则满载积压。

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

那么,有没有:

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

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

【问题讨论】:

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


    【解决方案1】:

    MQ,实际上是 JMS,经过设计和优化,可以让消息尽可能快地传递到管道中。每条消息的状态由队列管理器跟踪,但并发要求将要求 QMgr 跟踪消息彼此之间的状态。 MQ 不这样做。

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

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

    无论是在 ESB 还是 JEE 代码中实现,您所描述的是来自 Enterprise Integration Patterns 书中的 Message Dispatcher Pattern,它是消息传递世界中 权威的架构参考之一。有几种写法,具体取决于仪器的偏好。

    标记化

    1. 应用程序实例在令牌队列和同步点下执行GET 并等待。
    2. 收到令牌消息后,应用程序PUTs 将同一消息返回令牌队列,再次在同步点下。
    3. 应用程序执行GET 并在同步点下的应用程序队列上等待。
    4. 收到应用消息后,应用会对其进行处理,然后酌情执行COMMITROLLBACK

    应用实例在处理应用消息之前竞争令牌消息。结果是应用程序消息通常在它们到达时被尽快处理,但在负载下,最大并发数等于令牌消息的数量。

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

    独立调度程序

    1. 调度程序应用程序在通告的目标队列上侦听消息,并在 ACK 队列上侦听确认消息。
    2. 计数器将未处理的消息与调度程序应用配置中设置的{max outstanding message limit} 进行比较。
    3. 如果未完成的消息
    4. 当业务应用程序GETs 一条消息时,它也会将一条消息放入调度程序的ACK 队列中,这两个操作都在同步点下。
    5. 当业务应用程序发出COMMIT 时,调度程序接收到 ACK 并递减未完成消息计数器。

    调度程序应用程序可以请求发送确认消息,但这些消息并不总是与业务应用程序成功处理交易相关。如果业务应用明确地将 ACK 消息与所使用的业务消息放在同一个工作单元中,则结果非常可靠。

    【讨论】:

    • 虽然“越远越好,越快越好”,但当您没有执行资源时,从队列中获取消息似乎不是一个好主意可用于处理。
    • 对,所以不要这样做。预读需要非持久消息。当应用程序架构师选择最多一次的服务类时,在内存中缓冲消息会在根据定义没有缺点的情况下产生显着的性能提升。您要求的是基于标准的解决方案,而不是基于 MQ 的解决方案。该行为符合规范,通常使用架构模式来解决,您选择了 Dispatcher 模式实现为令牌化,令牌存储在数据库中而不是队列中。在我看来,我们最终来到了完全相同的地方。
    【解决方案2】:

    我最终使用了我的“或者我可以 [...]”方法 - 将“开始分析”更改为广播消息,并使用 SQL 中的状态子句处理节点选择声明。

    这是一个简单的解决方案,不会增加太多额外的复杂性,而且在实践中效果很好 - 到目前为止,它已经在生产环境中运行了大约一年。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-04-09
      • 1970-01-01
      • 2014-01-10
      • 2014-11-17
      • 2014-09-06
      • 1970-01-01
      • 2020-04-04
      • 1970-01-01
      相关资源
      最近更新 更多