【问题标题】:Consume JMS Topic only once仅使用一次 JMS 主题
【发布时间】:2013-09-12 10:52:38
【问题描述】:

我有一个 JMS 主题,它会产生独特的消息。

我在 n 台机器(clients)上部署了一个简单的 webapp,它所做的只是将使用的 msg 放入另一个系统(目标系统)。

注意:

  • 我确实可以控制 JMS。
  • 确实可以控制客户端。
  • 我确实可以控制将由客户端接收消息的目标系统。

我的问题是:

如何确保消息被其中一个客户端写入一次(到目标系统),并且永远不会被另一个客户端再次写入(好像 JMS 是队列而不是主题),知道每个 msg 都有一个 uniqueId 吗?

我正在考虑两种解决方案:

  1. 创建另一个使用该主题的 JMS 队列,并且该队列将由 n 个客户端之一为每个 msg 使用一次。

  2. 有某种共享位置(memcache),其中包含已使用 msgs 的消息 ID,并且在客户端将已使用 msg 发送到目标系统之前,我必须检查共享存储(memcache)是否具有此 id之前,如果没有,则发送到目标系统。

你怎么看?

更新

最终得到消息的系统不是 RDBMS,甚至不在我的控制之下。我只是将一些味精从一个系统传送到另一个系统。 (其实是 Apache Flume 不受我控制)

【问题讨论】:

    标签: database jms message-queue jms-topic


    【解决方案1】:
    • 使用另一个队列可能会导致另一个问题:您的 n 台机器中的一个必须监听该主题。如果您必须确保没有消息丢失,您必须以某种方式同步订阅者。添加单独的订阅者会增加系统复杂性。

    • 添加另一个存储(共享内存集群、memcache 等)会增加系统复杂性(并且您已经拥有一个公共存储)。

    所以最好的办法是使用队列而不是主题。您无法更改此设置,因此我建议使用此选项:

    • 所有 JMS 消息都有唯一的消息 ID。您可以将此 ID 与该列上的唯一索引一起存储在数据库中。所以你可以插入(并忽略一个唯一的约束违规错误)。不是很好,但它可以在集群中工作,并且不会增加系统复杂性。一个变体是在数据库中已经存在消息之前检查。

    【讨论】:

    • 对于#1,第二个 JMS 服务将是一个队列(与主题相比),因此只有一个会消耗 msg,即使没有侦听器,队列也会保留 msg,直到一位听众来了。
    • 顺便说一句,我已经通过问题进行了编辑,表明我最终在不受我控制的其他系统中推送消息(它实际上不是 DB)
    【解决方案2】:

    如果可能,我不会部署 n 个客户端监听该主题。因为客户端所做的工作是每次发布消息时仅将单个消息副本转发到另一个组件或数据库。相反,我会创建一个持久订阅,并且只有一个客户端监听该订阅。该客户端会将消息转发到数据库。如果客户端未运行,消息将由消息传递提供程序持有并在客户端再次运行时传递。

    【讨论】:

    • creating one durable subscription 是什么意思?
    • 持久订阅是即使消费者离线也能继续接收发布的订阅。只有一个这样的订阅就足以消费发布并将它们推送到下一个组件。
    • 啊哈,所以 JMS 队列是持久订阅。
    猜你喜欢
    • 2011-03-31
    • 2014-09-15
    • 2014-11-13
    • 2018-10-28
    • 2016-02-03
    • 2013-04-01
    • 1970-01-01
    • 2012-12-15
    • 2011-06-02
    相关资源
    最近更新 更多