【问题标题】:Handling Failed calls on the Consumer end (in a Producer/Consumer Model)在消费者端处理失败的调用(在生产者/消费者模型中)
【发布时间】:2013-02-12 18:56:17
【问题描述】:

让我试着解释一下情况:

我们将要合并一个消息传递系统,它可以是队列或主题(JMS 术语)。

1)生产者/发布者:有一个服务A。A产生消息并写入队列/主题

2)消费者/订阅者:有一个服务B。B从Queue/Topic异步读取消息。 B 然后调用 Web 服务并将消息传递给它。 Web 服务需要花费大量时间来处理消息。 (这个动作不需要实时处理。)

消息代理是 Tibco

我的意图是:不要错过处理来自 A 的任何消息。在稍后的时间点重新处理它,以防第一次处理失败(可能是批处理)。

问题

我正在考虑在进行网络服务调用之前将消息写入数据库。如果调用成功,我会将消息标记为已处理。否则失败。后来,在一个 cron 作业中,我会处理所有最初失败的请求。

写入数据库是执行此操作的典型方式吗?

【问题讨论】:

  • 通话失败是否有回拨?
  • 是的,如果调用返回“失败”响应,我会收到响应。如果调用本身失败(网络、I/O 问题等),我也能够捕获异常

标签: java asynchronous jms publish-subscribe tibco


【解决方案1】:

由于您有一个失败的回调,您可以将您的Message 重新排队并让您的Consumer/Subscriber 将其取回并重试。如果由于 Web 服务中的某些问题而失败,并且您想在重试之前等待 X 时间,那么您可以为该特定 Message 安排稍后调用 Web 服务的计划(查看 ScheduledExecutorService ) 或按照您的描述进行操作,并使用带有一些数据库条目的 cron 作业。

如果您只希望它在每条消息中重试一次,则使用Message 或在Map<Message, Integer> 中保留一个内部计数器作为每个Message 的计数器。

【讨论】:

    【解决方案2】:

    粗略地说,这就是技术,尽管您可以使用开箱即用的解决方案。典型的 ESB 解决方案支持可靠的消息传递。也可以看看MuleESBApache ActiveMQ

    【讨论】:

    • 如果出现异常和错误,我无法“提交” --> 我能够在大多数 JMS 实现中找到这一点。但是,如果我想稍后重试,比如一个小时左右,该怎么办?
    【解决方案3】:

    利用您已有的 EMS 平台(示例 1)而不是构建自定义解决方案(示例 2)可能会很有趣。

    但这一切都取决于实现语言:

    示例 1 - EMS 是“守护者”:如果我要使用 TIBCO BusinessWorks 解决此类问题,我会使用 BW 的“JMS 事务”功能。通过将 EMS 读取和 WS 调用包含在同一个“组”中,您要求它们都被应用,或者根本不应用。如果由于某种原因呼叫失败,消息将返回给 EMS。 此解决方案有两个问题:您可能没有 BW,并且第一个失败的操作会阻塞批处理的所有其余部分(这可能是所需的行为)。 仅供参考,我知道可以在“纯 java”中使用此类功能,但我从未尝试过:http://www.javaworld.com/javaworld/jw-02-2002/jw-0315-jms.html

    示例 2 - 数据库是“守护者”:如果您使用“数据库”方法,您的队列/主题客户会不断地将插入数据放入数据库中,并且所有记录都代表要执行的任务。这感觉很像每个集成中间件旨在简化的简单“映射引擎”问题。您可以使用任何东西来解决这个问题,从自定义 Java 代码和多个线程(DB 插入器、WS 作业处理程序等)到 EAI 中间件(如 BW)甚至 BPM 引擎(TIBCO 有很多解决方案) 当然,还有其他厂商……EMS是JMS的标准实现,你知道的。

    【讨论】:

      【解决方案4】:

      我建议使用内置的 EMS (& JMS) 功能,因为“保证交付”是它的目的;) - 根本不需要 db...

      您需要注意,第一个决定将是:

      • 需要按顺序发货吗? (那么只应使用 1 个 JMS Session 和 Client Ack 模式)
      • 您希望重试的频率和重复次数? (不让该网络服务无法处理的消息无限循环)。

      无论您使用哪种客户端(TIBCO BW 或例如 MDB 中的 Java onMessage()),这都是独立的。

      对于“按顺序”交付:使舒尔只有 1 个 JMS 会话处理消息,并且它使用客户端确认模式。成功处理消息后,您需要通过调用 JMS API“acknowledge()”方法或在 TIBCO BW 中通过执行“commit”活动来确认消息。

      如果发生错误,您不执行该方法的确认,因此消息将被放回队列中以进行重新传递(您可以在 JMS 标头中看到它被重新传递了多少次)。

      EMS 的 Explicit Client Acknolwedge 模式也使您能够在顺序不重要并且您需要一些客户端线程来处理消息时执行相同操作。

      用于控制消息处理的频率:

      • EMS 队列的 ma​​x redelivery 属性(例如,您可以将消息置于死区 重新投递后的信件队列,以免耽误其他消息)
      • 重新交付延迟在重新交付之间设置一个“暂停”。这在以下情况下很有用 Web Service 需要在崩溃后恢复,而不是通过重新传递而在高间隔内一次又一次地受到相同消息的冲击。

      希望有帮助

      干杯 赛博

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-10-12
        • 2021-04-30
        • 2018-11-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多