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

2022-08-31 22:35:17

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

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

如果我有一个生产者由所有线程共享怎么样?我的邮件是损坏了,还是会同步发送出去(没有性能提升)?

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

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

(这是一个类似的问题,但它并没有完全回答我正在寻找的东西。长期存在的 JMS 会话。保持 JMS 连接/JMS 会话是否开启了一个糟糕的做法? )


答案 1

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

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

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

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

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

JMS 规范可识别此多义窗口,并提供以下指导:

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

由 JMS 应用程序来处理这种多义性。在某些情况下,这可能会导致客户端生成功能上重复的消息。

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

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

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

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


答案 2

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

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

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


推荐