时间:2011-01-19 22:49:04

标签: java jms

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

我想知道是否建议使用一个连接,一个会话和10个生产者?

如果我有一个生产者共享所有线程怎么样?我的邮件是否会损坏或是否会同步发送(不会带来任何性能提升)?

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

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

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

5 个答案:

答案 0 :(得分:28)

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

  1. API调用(包括任何消息数据)通过网络传输到代理。
  2. API调用由代理执行。
  3. 结果代码和任何消息数据都会传回客户端。
  4. 考虑制片人一分钟。如果连接在第一步中断,则代理从未收到消息,应用程序将需要再次发送。如果在第三步中连接断开,则消息已成功发送,再次发送将产生重复消息。应用程序无法区分这些,因此唯一安全的选择是重新发送错误消息。如果会话被处理,则可以在所有情况下安全地重新发送消息,因为如果原始消息已经发送给代理,则它将被回滚。

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

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

    JMS规范识别出这种模糊性窗口并提供以下指导:

      

    如果发生故障   客户承诺工作的时间   会话和提交方法   返回,客户端无法确定   如果交易已经提交或   回滚。存在同样的歧义   当发生故障时   非事务性发送PERSISTENT   消息和从中返回   发送方法。

         

    由JMS应用程序来处理   这种含糊不清。在某些情况下,   这可能会导致客户生产   功能上重复的消息。

         

    由于重新传递而重新传递的消息   会话恢复不被视为a   重复的消息。

    除了可以丢失消息的情况外,应始终对JMS会话进行处理。如果会话是事务处理,那么由于JMS线程模型,您需要每个线程的会话和连接。

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

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

答案 1 :(得分:9)

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

某些邮件系统支持群集模式,其中连接负载均衡到不同的节点。通过多个连接,您可以在此方案中使用多个节点的性能。 (当瓶颈位于消息代理的一侧时,这当然只有帮助。)

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

答案 2 :(得分:4)

I was wondering if having one connection, one session, and 10 producers
is the recommended way to go or not? 

当然,但请注意,您只使用单线程,即创建Session对象时创建的线程。所有10个生成器都绑定到此Session对象,因此绑定到同一个线程。

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 :(得分:4)

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

答案 4 :(得分:1)

理论上,Connections是线程安全的,但其他所有都不是,所以你应该为每个线程创建一个会话。

实际上,它取决于您正在使用的JMS实现。