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

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

我想知道是否有一个连接,一个会话,10个生产者是否是推荐的方式?

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

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

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

(这里有一个类似的问题,但是它并没有完全回答我正在寻找的东西。 长时间的JMS会话。保持JMS连接/ JMS会话总是打开一个不好的实践? )

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

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

考虑一下制片人一分钟。 如果连接在第一步中断,那么代理从来没有收到消息,应用程序将需要再次发送。 如果连接在第三步中被破坏,则消息已成功发送,并再次发送会产生重复的消息。 该应用程序无法区分这些之间的差异,所以唯一的安全select是重新发送错误的消息。 如果会话被处理,消息可以在所有情况下被安全地重新发送,因为如果原始消息已经交给经纪人,它将被回滚。

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

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

JMS规范认识到这个模糊的窗口,并提供了以下指导:

如果在客户端在Session上提交其工作并且提交方法返回的时间之间发生故障,则客户端无法确定事务是提交还是回滚。 当PERSISTENT消息的非事务性发送和发送方法的返回之间发生故障时,存在相同的歧义。

这是由JMS应用程序来处理这种模糊性。 在某些情况下,这可能会导致客户端产生function重复的消息。

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

JMS会话应该总是被处理,除非那些确实可以丢失消息的情况除外。 如果会话被处理,那么由于JMS线程模型的原因,您将需要每个线程的会话和连接。

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

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

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

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

最好的解决办法是给我们一个连接池,给pipe理员一些选项来configuration特定区域的行为。

从我调查这个话题来看,一个会话意味着一个线程。 这是基于JMS规范的。 如果你想要multithreading(多个生产者/消费者),需要创build多个会话,一个连接就可以了。

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

当然,这里需要注意的是,您只使用单线程,即创buildSession对象时创build的线程。 所有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? 

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

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

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