我正在尝试利用.NET Kaazing客户端通过Web套接字与JMS后端进行交互。我正在努力理解会话的正确用法。最初,我有一个跨所有线程共享的会话,但我注意到这不受支持:
会话对象是用于生成和使用消息的单线程上下文。尽管它可以在 Java 虚拟机 (JVM) 外部分配提供程序资源,但它被视为轻量级 JMS 对象。
我只有一个会话的原因只是因为我认为这会产生更好的性能。由于文档声称会话是轻量级的,因此我毫不犹豫地将代码切换为每个"操作"使用会话。通过"操作",我的意思是发送一条消息,或者订阅一个队列/主题。在前一种情况下,会话的生存期很短,并在发送消息后立即关闭。在后一种情况下,只要订阅处于活动状态,会话就需要存在。
当我尝试创建多个会话时,出现错误:
System.NotSupportedException: Only one non-transacted session can be active at a time
谷歌搜索这个错误是徒劳的,所以我尝试切换到事务处理会话。但是在尝试创建消费者时,我收到一个不同的错误:
System.NotSupportedException: This operation is not supported in transacted sessions
所以看起来我被困在岩石和坚硬的地方之间。我看到的唯一可能选项是跨线程共享我的会话,或者使用单个非事务处理会话来创建使用者,并为其他所有内容使用多个事务处理会话。这两种方法对我来说似乎都有点违背。
任何人都可以阐明我在客户端中处理会话的正确方法吗?
有几种方法可以向应用程序添加并发性。 您可以使用多个连接,但由于网络开销增加,这可能不可取。 更好的方法是实现一个简单的机制,通过调度任务或通过 ConcurrentQueues 传递消息来处理消息侦听器中的并发性。 以下是实施策略的一些选择:
-
基于任务的方法将使用任务计划程序。 在消息侦听器中,将计划一个任务来处理工作并立即返回。 例如,您可以为每条消息安排一个新任务。 此时,MessageListener 将返回,并且下一条消息将立即可用。 这种方法对于低吞吐量应用程序(例如每秒几条消息)很好,但需要并发性的地方可能是因为某些消息可能需要很长时间来处理。
-
另一种方法是使用消息的数据结构来处理待处理的工作(ConcurrentQueue)。 当调用 MessageListener 时,每条消息都会被添加到 ConcurrentQueue 中并立即返回。然后,一组单独的线程/任务可以使用适用于您的应用程序的策略从该 ConcurrectQueue 中提取消息。 这将适用于更高性能的应用程序。
-
此方法的变体是为每个处理入站消息的线程提供一个 ConcurrentQueue。 在这里,MessageListener 不会管理自己的 ConcurrentQueue,而是将消息传递到与每个线程关联的 ConcurrentQueue。 例如,如果您有表示股票源和新闻源的入站消息,则一个线程(或一组线程)可以处理股票源消息,另一个线程可以单独处理入站新闻项。
请注意,如果您使用的是 JMS 队列,那么当 MessageListener 返回时,将隐式确认每条消息。 这可能是也可能不是应用程序所需的行为。
对于更高性能的应用程序,应考虑方法 2 和 3。