【问题标题】:JMS Message Ordering and Transaction RollbackJMS 消息排序和事务回滚
【发布时间】:2015-11-27 21:54:56
【问题描述】:

我们正在构建一个系统,该系统将通过 JMS 将消息从一个应用程序发送到另一个应用程序(如果需要,使用 Websphere MQ)。这些消息的形式为“创建 x”或“删除 x”。 (这样做的最终结果是需要通知第三方系统 Create 和 Delete 消息,因此 JMS 队列的 Read 端将与第三方系统通信,而 JMS 的 Write 端队列只是广播消息以进行处理)

我们在这里担心的问题是如果其中一条消息失败。这里最初的想法只是将故障回滚到 JMS 队列中,并让正常的重试机制来处理它。这一直有效,直到你得到一个删除,然后是一个相同标识符的创建,例如

  • 删除 123 - 失败,回滚到队列中
  • 创建 123 - 成功
  • 删除 123 - 从之前的失败中重试

这样做的最终结果是第三方被告知创建 123,然后立即删除 123,而不是相反。

虽然并不理想,但从我一直在阅读的内容来看,Message Affinity 似乎在这里会有所帮助,这样我们就可以保证以正确的顺序处理消息。但是,我不确定当消息被处理并失败返回队列时消息关联将如何工作? (Message Affinity 通常被认为是一个坏主意,但这里的负载不会很大,并且中毒消息的风险非常低。只是我们正在与之交互的第三方有一个简短的风险我们担心的中断)

如果做不到这一点,关于如何做到这一点,有没有更好的想法?

编辑 - 进一步复杂化。我们正在构建的与第三方集成的系统是为了替换他们直到最近才使用的来自不同供应商的系统。因此,第三方已经有大量数据,但实际上很难将其取出。 (第三方甚至不发回成功/失败消息,只是确认收到!),所以我们实际上并不知道系统的初始状态。

【问题讨论】:

    标签: java jms ibm-mq


    【解决方案1】:

    避免上述情况的一种方法是对消息故障进行不同分类;请记住,您的消息应按顺序处理。(消息亲和性)

    考虑场景:-

    如果应用程序收到之前没有收到 Create x 的 Delete X, 然后将此错误场景分类为“Business Error”,因为发生此错误是因为 消息的生产者发送了错误的消息。或者我们可以说消息的生产者以错误的顺序发送消息。

    一旦你将此错误归类为“Business Error”,就不应调用回滚;而不是将此消息插入数据库,并以“业务错误”作为标识。

    因此,通过这种方式,您从队列中提交了此消息并降低了回滚风险,并进一步降低了应用程序行为不一致的风险。

    现在考虑另一个场景:-

    如果您的应用程序本身有问题(例如,数据库或 Web 服务器出现故障或任何此类技术错误),那么在这种情况下使用 JMS 队列的回滚机制并将此错误视为“Technical Error”。

    因此,如果发生任何“Technical Error”,JMS 队列将重试消息,直到您的应用程序能够接受并处理这些消息。

    一旦您的应用程序在此“Technical Error”之后启动并尝试按顺序处理消息,此处应用相同的规则,即如果发生“业务错误”,则该消息将不再重试。

    注意:“业务错误”分类应得到各方同意,即如果您将任何消息标记为“Business Error”,则表示该消息不再有用并且您的 Producer应该为任何有效的“创建 x”发送一个新的“删除 x”。

    您可以考虑的一些“业务错误”是--

    1. 在“创建 x”之前收到“删除 x”

    2. 在“创建 x”之后收到“创建 x”

    3. 在有效“删除 x”后收到“删除 x”

    【讨论】:

      【解决方案2】:

      解决此问题的最终方法是在消息中包含一个序列,以使较早的消息不能覆盖后面的消息。

      曾几何时,您在银行的交易是按照它们到达的顺序处理的。然而,正是这个确切的问题导致了这种情况的改变。人们意识到他们的账户余额可能会受到交易处理顺序的正面或负面影响。当它被偶然发现时,它偶尔会成为人们的问题,但一般不会察觉到恶意。

      后来,银行开始在白天记录交易,然后在处理它们之前将它们排序成对银行最有利的顺序。例如,如果最大的支票首先被清算并且账户中的钱用完了,那么几张较小的支票可能会被退回,从而为银行产生多次退回费用。一旦发现这已成为普遍做法,它就被更改为始终以对帐户持有人最有利的顺序应用交易。 (至少在美国。)

      这是一个常见问题,已经解决了很多次,第一次是几十年前。企业级应用程序真的没有任何借口了

      1. 使用无法保证按设计交付顺序的异步消息传递,并且
      2. 包含对交付订单的固有依赖性,以确保交易和数据的完整性。

      当作为传输问题处理时,消息关联性的提及暗示了此问题的解决方案。为保证消息顺序传递,需要满足以下条件:

      • 只有一个消息发件人
      • 一个也是唯一一个从中发送消息的节点。
      • 消息的发送者和接收者之间只有一个路径。
      • 接收消息的队列只有一个。
      • 在同步点下处理的所有消息。
      • 存在孤立事务时挂起处理任何消息的能力(连接异常处理)。
      • 输入队列上没有回退队列。
      • 如果消息通过通道,则没有 DLQ。
      • 沿路径的任何队列均不使用优先传送。
      • 只有一个消息接收者。
      • 除了将 CPU 和内存添加到托管 QMgr 的节点之外,无法扩展应用程序。

      或者可以在应用程序设计中使用备忘录发布、补偿事务或任何其他通常用于消除序列依赖性的技术来解决问题。

      (旁注:如果有问题的应用程序是现成的供应商软件包,这在我看来会造成可信度问题。如果像退出这样司空见惯的事情,没有应用程序可以声称是健壮的消息可能会破坏数据完整性。)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-11-18
        • 2016-10-28
        • 2015-12-21
        • 1970-01-01
        • 2016-11-18
        • 2015-02-25
        • 1970-01-01
        • 2012-06-21
        相关资源
        最近更新 更多