24

我有一个网络应用程序,当用户提交请求时,我们将 JMS 消息发送到远程服务,然后等待回复。(还有异步请求,我们为消息重放等设置了各种细节,所以我们更愿意坚持使用 JMS 而不是 HTTP)

我应该如何使用 JMS 实现请求响应?, ActiveMQ 似乎不鼓励每个请求使用临时队列或在 JMSCorrelationID 上使用选择器的临时消费者的想法,因为启动它们会产生开销。

但是,如果我使用池消费者进行回复,我如何从回复消费者分派回原始请求线程?

我当然可以编写自己的线程安全回调注册/调度,但我讨厌编写我怀疑已经由比我更了解的人编写的代码。

该 ActiveMQ 页面推荐Lingo,它自 2006 年以来就没有更新过,还有Camel Spring Remoting,我的团队因为它的许多陷阱错误而被地狱禁止。

是否有更好的解决方案,以实现此模式的库的形式,或以不同模式的形式来模拟 JMS 上的同步请求-回复?


相关的SO问题:

4

5 回答 5

4

在过去的项目中,我们遇到过类似的情况,同步 WS 请求是使用一对 Async req/res JMS 消息处理的。当时我们正在使用 Jboss JMS impl,而且临时destinations开销很大。

我们最终编写了一个线程安全的调度程序,让 WS 等待 JMS 响应到来。我们使用 CorrelationID 将响应映射回请求。

该解决方案都是本土开发的,但我遇到了一个很好的阻塞映射 impl,它解决了将响应与请求匹配的问题。

阻塞图

如果您的解决方案是集群的,您需要注意将响应消息分派到集群中的正确节点。我不知道 ActiveMQ,但我记得 JBoss 消息传递在其可集群目标的引擎盖下存在一些故障。

于 2012-08-01T10:21:34.200 回答
4

我仍然会考虑使用 Camel 并让它处理线程,也许没有弹簧远程处理,但只是原始的 ProducerTemplates。

Camel 有一些关于该主题的不错的文档,并且与 ActiveMQ 配合得很好。 http://camel.apache.org/jms#JMS-RequestreplyoverJMS

对于您关于启动基于选择器的消费者和开销的问题,ActiveMQ 文档实际上说明的是它需要往返于 ActiveMQ 代理,该代理可能位于地球的另一端或在高延迟网络上。在这种情况下,开销是到 AMQ 代理的 TCP/IP 往返时间。我会认为这是一种选择。已成功使用它多次。

于 2012-08-01T20:03:54.470 回答
3

一位同事提出了一个潜在的解决方案——每个 webapp 线程一个响应队列/消费者,我们可以将返回地址设置为该特定线程拥有的响应队列。由于这些线程通常是长期存在的(并且会被重新用于后续的 Web 请求),所以我们只需要在线程由池生成时承受开销。

也就是说,整个练习让我重新思考 JMS 与 HTTP ...... :)

于 2012-08-03T01:33:51.817 回答
0

我一直使用 CorrelationID 进行请求/响应,并且从未遇到任何性能问题。我无法想象为什么这会是一个性能问题,对于任何消息传递系统来说,它都应该是超快的,并且是一个非常重要的特性,并且实现得很好。

http://www.eaipatterns.com/RequestReplyJmsExample.html有两个使用replyToQueue 或correlationID 的主流解决方案。

于 2012-08-01T08:45:09.977 回答
0

这是一个旧的,但我已经登陆这里寻找其他东西并且实际上确实有一些见解(希望对某人有所帮助)。

我们已经实现了非常相似的用例,Hazelcast 作为我们集群节点间通信的底盘。本质是 2 个数据集:1 个用于响应的分布式地图,1 个响应等待者的“本地”列表(在集群中的每个节点上)。

  • 每个请求(从 Jetty 接收它自己的线程)在本地等待者的映射中创建一个条目;该条目显然具有相关 UID 和将用作信号量的对象
  • 然后请求被分派到远程(REST/JMS),原始线程开始等待信号量;UID 必须是请求的一部分
  • 远程返回响应并使用相关的 UID 将其写入响应映射
  • 正在听取响应地图;如果在本地等待者的映射中找到新响应的 UID,则通知其信号量,释放原始请求的线程,从响应映射中获取响应并将其返回给客户端

这是一个一般性描述,我可以通过一些优化来更新答案,以防有任何兴趣。

于 2017-08-11T07:22:53.087 回答