Java 如何从JMS读取和收集响应消息,并使它们可用于正确的servlet线程?

Java 如何从JMS读取和收集响应消息,并使它们可用于正确的servlet线程?,java,multithreading,servlets,jms,sonicmq,Java,Multithreading,Servlets,Jms,Sonicmq,我们为异步JMS消息传递系统提供了一个同步HTTP请求-响应前端 每个HTTPRequest的HTTP查询servlet在查询队列中创建相应的JMS消息。此查询由后端处理,并为此查询创建两条响应消息。在JMS中组织响应消息的接收,并确保它们到达适当的servlet线程,以便它能够制定HTTPResponse的好方法是什么 查询和响应是非事务性的,不需要持久化。其中大多数是读取查询。如果在45秒内没有读取响应,servlet将生成超时响应。然而,吞吐量很重要。我们需要处理越来越多的查询。这个系统已

我们为异步JMS消息传递系统提供了一个同步HTTP请求-响应前端

每个HTTPRequest的HTTP查询servlet在查询队列中创建相应的JMS消息。此查询由后端处理,并为此查询创建两条响应消息。在JMS中组织响应消息的接收,并确保它们到达适当的servlet线程,以便它能够制定HTTPResponse的好方法是什么

查询和响应是非事务性的,不需要持久化。其中大多数是读取查询。如果在45秒内没有读取响应,servlet将生成超时响应。然而,吞吐量很重要。我们需要处理越来越多的查询。这个系统已经有十年的历史了,还得再运行两年左右

我们正在使用SonicMQ。我们为所有响应创建了一个队列。servlet容器有一个到代理的连接,用于读写。我们为每个登录用户生成一个侦听器线程(大约并发1500个)。该线程有一个带有消息选择器的接收器,该选择器仅为该特定用户选择响应消息。一旦servlet线程发送了查询消息,它将等待用户的侦听器线程通知它已读取响应

我们曾经有一个由所有发送者和接收者共享的队列会话。这实际上是有效的(!),尽管会话官方上不是线程安全的。每个线程创建一个QueueSession(servlet线程和侦听器线程)在一定程度上提高了性能,但是事情仍然不太稳定,我们希望更好地组织事情

我尝试过为每个用户会话创建一个临时队列,而不是一个带有消息选择器的队列,但这大大降低了速度


有什么更好的/正确的方法来组织这篇文章呢?

我一开始是这样评论的,但它有点扩大了

根据您的描述,听起来每个请求至少需要两个线程,甚至可能更多。如果您已经有1500个并发用户,并且您的查询已经足够多,您需要将它们分发到其他节点,那么我认为您已经进入了危险的领域,因为在没有大量CPU/内存分配和一些严重的设置调整的情况下,有多少活动线程将在JVM中有效运行

我对删除JMS的评论是因为在应用程序的servlet端,您只是在做大量额外的工作,使JMS成为一个同步请求/响应机制,而简单的线程池也可以用来运行多个并发查询来响应HTTP请求。不过,听起来JMS是后端接收工作请求的一种不错的方式,因此可能不值得进行大规模重写

我认为更好的组织方式是每个tomcat实例一组消费者,而不是每个请求线程一个消费者。每个webhead都可以有自己的响应队列,或者在单个队列上使用MessageSelector。然后,当一个请求传入时,发送一个请求JMS消息,并为使用者留下一种方法,让其回调调用线程,就像调用者正在等待的调用线程一样。如果您必须等待多条消息才能为单个请求提供服务,那么可以将a与a结合起来,在接收到所有响应时向请求线程发送信号。这样,您就可以拥有一个相对较小的线程池,负责在消息传入时接收消息。我觉得应该有一些东西可以帮助你解决这个问题,但我不能马上想到任何东西


之后,如果您发现性能仍然存在问题,您可以通过添加tomcat实例或查看HTTP请求处理的非阻塞IO进行扩展,将相同的策略应用到前门和后门:使用一个小线程池来处理大请求量,其中等待是在每个请求的线程模型中占用大量线程。

从等式中删除JMS是一种选项,还是这是您必须与此后端系统交互的“方式”?@RyanStewart后端当前由从查询队列读取、执行查询、,并将响应消息发布到客户端队列。这确实有一定的优势,它有点像一辆迷你巴士。该系统需要再运行2年左右。因此,极端的改头换面是不可能的。将查询执行移到tomcat(servlet容器)中是我们已经讨论过的事情,但我们对此并不十分自信。你认为我们应该吗?我们的系统操作报告服务器没有太忙。将工作分配给线程是有偏差的,它们会挨饿。如果绝对必要的话,我想我们可以得到第二台服务器,但是如果我们可以重新组织线程,那就更好了。因此,我们确实遇到了调整。我同意,每个用户一个线程是愚蠢和浪费的,这需要减少。我注意到每个sonic a连接都有一个发送者和监听者线程,所以也许我可以为单个tomcat实例建立连接?不确定我是否完全理解你对sonic线程的看法,但我肯定会使用我所有的JMS内容,这使得以有效的方式使用JMS非常简单,例如缓存生产者和消费者的连接和会话,以及在具有专用线程池的队列上运行多个并发消费者。当Spring可以在十几行XML中完成这些工作时,手动完成这些工作就太多了。我看到每个sonicmq连接在sonicmq内部由一个线程管理。感谢您提供有关SpringJMS的提示!