使用Apache Camel路由和ActiveMQ

时间:2016-05-20 12:43:24

标签: apache-camel activemq netty spring-jms

请帮助我使用Apache Camel和ActiveMQ完成异步交付支持的架构,下面我已经逐点解释了我的需求。

  1. 我让Jetty Server接收传入消息,而ActiveMQ使用Kaha DB将其存储在磁盘中。

  2. Active MQ在将kaha DB存储回客户端后发送ack。

  3. 我有Spring AbstractPollingMessageListenerContainer JMS Message侦听器,它每1秒从activemq队列中获取一条消息,然后发送到Camel HTTP端点,最后发送到实际的远程接收器。 一旦Dispatcher线程从远程接收器获得响应,它就会从ActiveMQ中删除消息。

  4. 假设我有很多慢速远程接收器,在这种情况下,由 AbstractPollingMessageListenerContainer 创建的Dispatcher线程仍然被阻塞,直到我从远程接收器获得响应。这导致创建新的Dispatcher线程,因为已经创建了Dispatcher线程无法从ActiveMQ队列分派新消息。 现在,创建许多Dispatcher线程会导致更多的CPU使用率,从而影响整体性能。

  5. 现在我的要求是我只希望Dispatcher线程将消息从ActiveMQ队列调度到HTTP端点并忘记并且也不做确认,以便消息仍然在队列中。 此外,我不会让Dispatcher线程等到我得到响应,所以我想使用单独的线程处理响应,同一个线程只会从ActiveMQ队列中删除消息。

  6. 所以我目前的架构如下:

    Camel Jetty Server ----> ActiveMQ队列----> Dispatcher Thread ---> Camel Direct端点----> Camel HTTP端点--->远程接收器发回响应--->回应---> Dispatcher Thread(发送ack以从ActiveMQ队列中删除消息)----> ActiveMQ队列。

    我觉得因为我们正在使用同步的Direct端点,所以Dispatcher线程保持活动状态直到它得到响应,因此同一个调度程序线程无法处理来自ActiveMQ队列的更多新消息。

    请建议我是否可以使用其他方法来避免直接端点。

    我使用了SEDA端点,但缺点是它使用1个线程处理1条消息,并且在被接收方响应之前也会被阻塞。 在这种方法中,先前Dispatcher线程被阻塞,但现在Seda消费者线程被阻塞,无法从SEDA的内存队列向远程接收器发送新消息。

  7. 我觉得某种设计可以帮助我继续向远程接收器发送消息,并且只有当响应返回时,一些daemeon线程才会得到通知,它将处理对activeMQ的确认。另外我想使用像Camel netty / netty4-http组件这样的NIO框架实现,但是找不到确切的用法以及如何使它适合当前的架构。

  8. 修改后的架构应如下所示: Camel Jetty Server ----> ActiveMQ队列----> Dispatcher Thread ---> Unknown Stuff ----> Camel HTTP端点--->发送响应的远程接收器---> Unknown Stuff(发送ack以从ActiveMQ队列中删除消息)----> ActiveMQ队列

  9. 请帮我确定未知的东西,并在做足够的R& S之后发布我的查询d。

    也欢迎新的想法,请给我一个限制的想法,我必须坚持消息并在获得远程接收器的成功响应后才删除它。此外,我必须使用Apache Camel路由设计架构。 路线定义: 1.调度员路线: 从(fromUri)至(toUris); fromUri: [ActiveMQueue.http1270018081testEndpoint1:queue:ActiveMQueue?maxConcurrentConsumers = 15& concurrentConsumers = 3& maxMessagesPerTask = 10& messageListenerContainerFactoryRef = AbstractPollingMessageListenerContainer] ToUris: [ActiveMQ.DLQ:queue:ActiveMQ.DLQ,direct:http1270018081testEndpoint1]

    2.远程接收器代理路由: fromUri:直接:http1270018081testEndpoint1 从(fromUri)。为了(toUri).process(responseProcessor) toUri:http://127.0.0.1:8081/testEndpoint1?bridgeEndpoint=true responseProcessor:处理远程接收器收到的响应。

    总体路线如下所示: 调度员路线--->远程接收器路由--->远程服务器

1 个答案:

答案 0 :(得分:0)

JMS消息确认在封面下完成,因此您真正“将确认发送回队列”的唯一方法是使用JMS事务(不需要是XA)

这听起来像LLR风格的交易会很有用,并且会大大简化您的工作。如果使用JMS本地事务从队列中使用消息,并且只有另一个端点,则只有在完成http发送时才会确认消息并将其从队列中删除 - 即使HTTP不支持事务。然后,您可以让多个并发使用者并行运行,并结合限制来帮助进行速率限制。

{{1}}