Java JMS连接、会话和生产者/消费者之间的关系

Java JMS连接、会话和生产者/消费者之间的关系,java,jms,Java,Jms,我想向同一队列发送一批20k JMS消息。我使用10个线程将任务拆分,因此每个线程将处理2k条消息。我不需要交易 我想知道是否建议使用一个连接、一个会话和10个制作人 如果我有一个制作人被所有线程共享呢?我的消息是否已损坏,或者是否已同步发送(不会带来性能提升) 如果我总是连接到同一队列,那么决定是否创建新连接或会话的一般原则是什么 谢谢你,很抱歉一下子问了很多问题 (这里有一个类似的问题,但它并没有完全回答我所寻找的问题。)理论上,连接是线程安全的,但所有其他连接都不是,因此您应该为每个线程创

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

我想知道是否建议使用一个连接、一个会话和10个制作人

如果我有一个制作人被所有线程共享呢?我的消息是否已损坏,或者是否已同步发送(不会带来性能提升)

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

谢谢你,很抱歉一下子问了很多问题


(这里有一个类似的问题,但它并没有完全回答我所寻找的问题。)

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


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

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

一些消息传递系统支持群集模式,在这种模式下,连接可以与不同的节点进行负载平衡。对于多个连接,您可以在此场景中使用多个节点的性能。(当然,只有当瓶颈位于MessageBroker一侧时,这才有帮助)


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

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

  • API调用(包括任何消息数据)通过电线传输到代理
  • API调用由代理执行
  • 结果代码和任何消息数据都会传输回客户端
  • 考虑一下制作人。如果连接在第一步中断,那么代理永远不会收到消息,应用程序将需要再次发送消息。如果在第三步中连接中断,则消息已成功发送,再次发送将产生重复消息。应用程序无法区分这两者之间的区别,因此唯一安全的选择是在出现错误时重新发送消息。如果会话是事务性的,则在所有情况下都可以安全地重新发送消息,因为如果原始消息已发送到代理,则消息将回滚

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

    在交易之外,可能会丢失或重复消息。在事务内部存在相同的模糊窗口,但它位于提交调用上,而不是PUT或GET上。使用事务处理会话,可以发送或接收两次消息,但不会丢失一条消息

    JMS规范识别了这一模棱两可的窗口,并提供了以下指导:

    如果故障发生在 客户提交其工作的时间 会话和提交方法 返回,客户端无法确定 如果事务已提交,或 向后滚。同样的歧义也存在 当两个系统之间发生故障时 持久性的非事务性发送 消息和来自 发送方法

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

    由于以下原因重新传递的消息: 会话恢复不被认为是一个重要问题 重复消息

    JMS会话应该始终进行事务处理,除非确实可以丢失消息。如果会话是事务性的,那么由于JMS线程模型,每个线程都需要会话和连接

    关于性能影响的任何建议都是特定于供应商的,但通常在API调用返回之前,syncpoint之外的持久消息会被硬化到磁盘。但是,只要消息在提交返回之前被持久化,事务处理调用就可以在持久消息写入磁盘之前返回。如果供应商基于此进行优化,那么将多条消息写入磁盘,然后成批提交,性能会更好。这允许代理按磁盘块而不是按消息优化写入和磁盘刷新。要放入事务中的消息数量随着消息的大小而减少,超过某个消息大小后,将减少到一个

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

    I was wondering if having one connection, one session, and 10 producers
    is the recommended way to go or not? 
    
    当然,但这里需要注意的是,您只使用单线程,即在创建会话对象时创建的线程。所有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规范明确规定会话不应由多个线程共享。它不是线程安全的

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

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

    根据我对本主题的研究,一个会话意味着一个线程。这是基于JMS规范的。如果需要多线程(多个生产者/消费者),则需要创建多个会话,一个连接即可