简体   繁体   English

与JMS / ActiveMQ并发同步请求 - 模式 - 模式/库?

[英]Concurrent Synchronous Request-Reply with JMS/ActiveMQ - Patterns/Libraries?

I have a web-app where when the user submits a request, we send a JMS message to a remote service and then wait for the reply. 我有一个web-app,当用户提交请求时,我们将JMS消息发送到远程服务,然后等待回复。 (There are also async requests, and we have various niceties set up for message replay, etc, so we'd prefer to stick with JMS instead of, say, HTTP) (还有异步请求,我们为消息重放设置了各种各样的细节,所以我们更喜欢坚持使用JMS而不是HTTP)

In How should I implement request response with JMS? 如何使用JMS实现请求响应? , ActiveMQ seems to discourage the idea of either temporary queues per request or temporary consumers with selectors on the JMSCorrelationID, due to the overhead involved in spinning them up. ,ActiveMQ似乎不鼓励每个请求的临时队列或JMSCorrelationID上具有选择器的临时消费者的想法,因为旋转它们涉及的开销。

However, if I use pooled consumers for the replies, how do I dispatch from the reply consumer back to the original requesting thread? 但是,如果我使用池化消费者进行回复,我如何从回复消费者发送回原始请求线程?

I could certainly write my own thread-safe callback-registration/dispatch, but I hate writing code I suspect has has already been written by someone who knows better than I do. 我当然可以编写自己的线程安全回调 - 注册/调度,但我讨厌编写我怀疑已经由比我知道的更好的人编写的代码。

That ActiveMQ page recommends Lingo , which hasn't been updated since 2006, and Camel Spring Remoting , which has been hellbanned by my team for its many gotcha bugs. 那个ActiveMQ页面推荐自2006年以来一直没有更新过的LingoCamel Spring Remoting ,我的团队已经因为它的许多漏洞而被hellbanned。

Is there a better solution, in the form of a library implementing this pattern, or in the form of a different pattern for simulating synchronous request-reply over JMS? 是否有更好的解决方案,以实现此模式的库的形式,或以不同模式的形式模拟JMS上的同步请求 - 回复?


Related SO question: 相关问题:

In a past project we had a similar situation, where a sync WS request was handled with a pair of Async req/res JMS Messages. 在过去的项目中,我们遇到了类似的情况,其中使用一对Async req / res JMS消息处理同步WS请求。 We were using the Jboss JMS impl at that time and temporary destinations where a big overhead. 我们当时正在使用Jboss JMS impl和临时destinations ,这是一个很大的开销。

We ended up writing a thread-safe dispatcher, leaving the WS waiting until the JMS response came in. We used the CorrelationID to map the response back to the request. 我们最终编写了一个线程安全的调度程序,让WS等待JMS响应进入。我们使用CorrelationID将响应映射回请求。

That solution was all home grown, but I've come across a nice blocking map impl that solves the problem of matching a response to a request. 这个解决方案都是本土的,但我遇到了一个很好的阻塞映射impl,解决了匹配请求响应的问题。

BlockingMap BlockingMap

If your solution is clustered, you need to take care that response messages are dispatched to the right node in the cluster. 如果您的解决方案是群集的,则需要注意将响应消息分派到群集中的正确节点。 I don't know ActiveMQ, but I remember JBoss messaging to have some glitches under the hood for their clusterable destinations. 我不知道ActiveMQ,但是我记得JBoss的消息传递在他们的可集群目的地下面有一些故障。

I would still think about using Camel and let it handle the threading, perhaps without spring-remoting but just raw ProducerTemplates. 我仍然会考虑使用Camel并让它处理线程,可能没有spring-remoting但只是原始的ProducerTemplates。

Camel has some nice documentation about the topic and works very well with ActiveMQ. Camel有一些关于这个主题的很好的文档,并且与ActiveMQ非常兼容。 http://camel.apache.org/jms#JMS-RequestreplyoverJMS http://camel.apache.org/jms#JMS-RequestreplyoverJMS

For your question about spinning up a selector based consumer and the overhead, what the ActiveMQ docs actually states is that it requires a roundtrip to the ActiveMQ broker, which might be on the other side of the globe or on a high delay network. 对于关于启动基于选择器的消费者和开销的问题,ActiveMQ文档实际指出的是它需要往返于全球另一端或高延迟网络的ActiveMQ代理的往返。 The overhead in this case is the TCP/IP round trip time to the AMQ broker. 这种情况下的开销是到AMQ代理的TCP / IP往返时间。 I would consider this as an option. 我认为这是一个选择。 Have used it muliple times with success. 多次使用它成功。

A colleague suggested a potential solution-- one response queue/consumer per webapp thread, and we can set the return-address to the response queue owned by that particular thread. 一位同事建议了一个潜在的解决方案 - 每个webapp线程一个响应队列/消费者,我们可以将返回地址设置为该特定线程拥有的响应队列。 Since these threads are typically long-lived (and are re-used for subsequent web requests), we only have to suffer the overhead at the time the thread is spawned by the pool. 由于这些线程通常是长期存在的(并且被重新用于后续Web请求),因此我们只需要在池生成线程时承受开销。

That said, this whole exercise is making me rethink JMS vs HTTP... :) 也就是说,整个练习让我重新思考JMS与HTTP ...... :)

I have always used CorrelationID for request / response and never suffered any performance issues. 我一直使用CorrelationID进行请求/响应,并且从未遇到任何性能问题。 I can't imagine why that would be a performance issue at all, it should be super fast for any messaging system to implement and quite an important feature to implement well. 我无法想象为什么这将是一个性能问题,它应该是任何消息传递系统实现的超快速,并且实现良好的非常重要的特性。

http://www.eaipatterns.com/RequestReplyJmsExample.html has the tow main stream solutions using replyToQueue or correlationID. http://www.eaipatterns.com/RequestReplyJmsExample.html使用replyToQueue或correlationID提供两个主流解决方案。

It's an old one, but I've landed here searching for something else and actually do have some insights (hopefully will be helpful to someone). 这是一个旧的,但我已经到了这里寻找其他东西,实际上有一些见解(希望对某人有帮助)。

We have implemented very similar use-case with Hazelcast being our chassis for cluster's internode comminication. 我们已经实现了非常类似的用例,Hazelcast是我们用于集群节点间通信的机箱。 The essense is 2 datasets: 1 distributed map for responses, 1 'local' list of response awaiters (on each node in cluster). 本质是2个数据集:1个响应的分布式映射,1个“本地”响应等待者列表(在集群中的每个节点上)。

  • each request (receiving it's own thread from Jetty) creates an entry in the map of local awaiters; 每个请求(从Jetty接收它自己的线程)在本地等待者的地图中创建一个条目; the entry has obviously the correlation UID and an object that will serve as a semaphore 该条目显然具有相关性UID和将用作信号量的对象
  • then the request is being dispatched to the remote (REST/JMS) and the original thread starts waiting on the semaphore; 然后将请求分派到远程(REST / JMS),原始线程开始等待信号量; UID must be part of the request UID必须是请求的一部分
  • remote returns the response and writes it into the responses map with the correlated UID remote返回响应并使用相关的UID将其写入响应映射
  • responses map is being listened; 正在听取回应地图; if the UID of the newly coming response is found in the map of the local awaiters, it's semaphore is being notified, original request's thread is being released, picking up the response from the responses map and returning it to the client 如果在本地等待者的地图中找到新来的响应的UID,则会通知其信号量,正在发布原始请求的线程,从响应映射中获取响应并将其返回给客户端

This is a general description, I can update an answer with a few optimizations we have, in case there will be any interest. 这是一般性的描述,我可以通过一些优化来更新答案,以防有任何兴趣。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM