【问题标题】:Relationship between JMS connections, sessions, and producers/consumersJMS 连接、会话和生产者/消费者之间的关系
【发布时间】:2011-06-12 02:52:24
【问题描述】:

我想将一批 20k JMS 消息发送到同一个队列。我使用 10 个线程将任务拆分,因此每个线程将处理 2k 条消息。我不需要交易。

我想知道是否推荐使用一个连接、一个会话和 10 个生产者?

如果我有一个由所有线程共享的生产者呢?我的消息会损坏还是同步发送(没有性能提升)?

如果我总是连接到同一个队列,决定是否创建新连接或会话的一般准则是什么?

谢谢你,很抱歉一次问了很多。

(这是一个类似的问题,但它并没有完全回答我要找的东西。Long lived JMS sessions. Is Keeping JMS connections / JMS sessions allways open a bad pratice?

【问题讨论】:

    标签: java jms


    【解决方案1】:

    根据我对该主题的调查,一个会话意味着一个线程。这基于 JMS 规范。如果你想要多线程(多个生产者/消费者),需要创建多个会话,一个连接就可以了。

    【讨论】:

      【解决方案2】:
      I was wondering if having one connection, one session, and 10 producers
      is the recommended way to go or not? 
      

      当然,但需要注意的是,您仅使用单线程,即您在创建 Session 对象时创建的线程。所有 10 个生产者都绑定到此会话对象,因此绑定到同一个线程。

      How about if I had one producer shared by all the threads? Would my messages
      be corrupt or would it be sent out synchronized (giving no performance gain)?
      

      我会说非常糟糕的主意。 JMS 规范明确规定 Session 不应由多个线程共享。它不是线程安全的。

      What's the general guideline of deciding whether to create a new connection
      or session if I'm always connecting to the same queue?
      

      如果您的系统支持多线程,那么您可以从单个连接创建多个会话(每个会话对应一个线程)。每个会话可以有多个生产者/消费者,但所有这些都不能在线程之间共享。

      【讨论】:

        【解决方案3】:

        如果某些消息重复或丢失,是否可以?当 JMS 客户端通过网络连接到 JMS 代理时,任何 API 调用都分为三个阶段。

        1. API 调用(包括任何消息数据)通过线路传输到代理。
        2. API 调用由代理执行。
        3. 结果代码和任何消息数据都会传回客户端。

        考虑一下制作人。如果在第一步中连接中断,那么代理永远不会收到消息,应用程序需要再次发送它。如果在第三步中连接断开,则消息已成功发送,再次发送将产生重复消息。该应用程序无法分辨这些之间的区别,因此唯一安全的选择是在出错时重新发送消息。如果会话被处理,则在所有情况下都可以安全地重新发送消息,因为如果原始消息已发送到代理,它将被回滚。

        考虑消费者。如果在第三步中连接丢失,则消息将从队列中删除,但从未返回客户端。但是如果会话被处理,消息将在应用程序重新连接时重新传递。

        在事务之外,可能会丢失或重复消息。在事务内部存在相同的模糊窗口,但它在 COMMIT 调用而不是 PUT 或 GET 上。通过事务会话,可以两次发送或接收消息,但不会丢失一次。

        JMS 规范识别出这种不明确的窗口并提供以下指导:

        如果在之间发生故障 客户提交工作的时间 会话和提交方法 返回,客户无法确定 如果事务已提交或 回滚。存在同样的歧义 当之间发生故障时 持久性的非事务性发送 消息和返回 发送方式。

        由 JMS 应用程序来处理 带着这种模棱两可。在某些情况下, 这可能会导致客户产生 功能上重复的消息。

        由于以下原因重新发送的消息 会话恢复不被视为 重复消息。

        应始终处理 JMS 会话,但丢失消息确实可以的情况除外。如果会话被处理,那么由于 JMS 线程模型,您需要每个线程的会话和连接。

        任何有关性能影响的建议都将是特定于供应商的,但一般来说,同步点之外的持久消息会在 API 调用返回之前固化到磁盘。但是事务调用可以在持久消息写入磁盘之前返回只要消息在 COMMIT 返回之前保持。如果供应商基于此进行优化,那么将几条消息写入磁盘然后分批提交它们的性能要高得多。这允许代理通过磁盘块而不是每个消息来优化写入和磁盘刷新。放入事务中的消息数量随着消息的大小而减少,超过一定的消息大小会减少到一个。

        如果您的 20k 消息相对较小(以 k 而非 mb 为单位),那么您可能希望使用每个线程的事务处理会话并调整提交间隔。

        【讨论】:

          【解决方案4】:

          在大多数情况下,使用一个连接和多个会话就足够了,每个线程使用一个会话。在某些环境中,您可以通过使用多个连接来获得额外的性能:

          一些消息传递系统支持集群模式,在这种模式下,连接会被负载平衡到不同的节点。通过多个连接,您可以在此方案中使用多个节点的性能。 (当然,只有当瓶颈在消息代理方面时才有帮助)。

          最好的解决方案是给我们一个连接池,并为管理员提供一些选项来配置特定区域的行为。

          【讨论】:

            【解决方案5】:

            理论上连接是线程安全的,但其他所有连接都不是,因此您应该为每个线程创建一个会话。

            实际上,这取决于您使用的 JMS 实现。

            【讨论】:

              猜你喜欢
              • 2014-05-24
              • 2017-07-13
              • 1970-01-01
              • 2012-05-18
              • 2015-08-03
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2018-03-07
              相关资源
              最近更新 更多