ActiveMQ 单线程到多线程……什么是最好的设计方法?
ActiveMQ single to multiple threads...what's the best design approach?
我对 ActiveMQ 的可行设计模式有疑问。我有一个基于 ActiveMQ 的单线程数据库客户端 - 调用者创建一个临时响应队列,JMS“发送”一个 SQL 查询到正确的队列,并等待临时队列上的响应。问题是,运行 的复杂查询慢慢意味着单线程消费者陷入困境……如果一个查询需要五分钟,则在第一个查询完成之前,不会对该数据库进行其他查询。查询本身是原子的,我们不在 JMS 级别使用任何方式的事务处理。我正在考虑的解决方案是对使用者进行多线程处理,但我想确保我不会 运行 违反任何 ActiveMQ 或 JMS 限制。
我知道我可以从队列切换到主题,然后我可以 运行 我今天拥有的跨多个线程。它可能会变成这样,但就目前而言,队列结构构成了一个以多种方式使用的“API”,因此它不容易更改为基于主题的东西。
相反,我设想一个主线程在从总线获取消息方面就像当前的消费者一样,除了不是内联处理消息(就像我们现在所做的那样),消息将排队到一个单独的线。子线程将执行数据库工作,然后将结果发送回其临时队列中的原始请求者。
如果我正确理解规范,我可以使用跨线程共享的单个“连接”。只有一个消费者,所以它会继续处于消息接收循环中,就像今天一样。在新的子线程中,我们将在现有连接上启动一个单独的 JMS 会话(会话不能共享),等待工作,处理查询,最后将任何结果发送到请求者的临时队列,以便他得到他的输出。我不认为我们需要大量的并行性,所以我想只预分配一些子线程并等待工作。
问题如下:
- 我能否从子线程之一发送到请求者的临时队列?
- 我可以在我的每个子线程中创建一个会话并反复使用它吗?
- 我预计在什么情况下单个连接会不堪重负?
- 代理上是否有我必须调整的配置设置来处理我可能有很多倍会话的事实?
- 如果有多个处理器内核、足够的数据库连接等等,在 JMS 级别是否有任何“陷阱”会阻止我的方法真正并行?
- 是否有更好的方法来为慢速事务实现更好的吞吐量?
这听起来像是工作模型,队列是一个不错的选择。如果您希望 相同 查询请求由多个系统处理,主题会很好。
是的。临时队列的唯一限制是,一旦不再有消息或生产者或消费者附加,它就会消失。另一种方法是使用真正的队列并使用 ActiveMQ 的垃圾收集器 'gc' 来自动清理它们。此处的优势在于,您可以更容易地了解正在使用的队列以及是否有掉队者。
会话可以在生产者和消费者之间共享。 JMS 对象层次结构类似于 JDBC 对象层次结构。你有彼此的子对象。在低负载和低连接数(例如,每个 CPU 核心少于 8 个连接)下,为每个线程设置专用的连接会话消费者对象并没有真正的危害——尤其是如果您打开池。它使错误处理和回滚更容易。
延迟 and/or 网络 I/O。如果您每秒处理的消息少于 512 条,消息大小为 4k 或更小,则一个连接不是问题。
取决于连接总数和每分钟消息数以及消息大小。
错误处理。如果您执行 JMS 本地事务(推荐!),您的错误处理是在会话级别进行回滚。
不,你很好!多线程消费者是解决缓慢消费者模式的首选方法。
建议--
- 为 ActiveMQ 连接配置池连接工厂
- 在 try {} catch {} finally {} 块中实现标准创建连接、会话、消费者、接收循环并在每条消息后关闭所有资源
- 让这里的代码多线程--^
连接池防止代理连接抖动。这种模式对于错误处理和避免导致消息丢失的资源泄漏是最可靠的。
我对 ActiveMQ 的可行设计模式有疑问。我有一个基于 ActiveMQ 的单线程数据库客户端 - 调用者创建一个临时响应队列,JMS“发送”一个 SQL 查询到正确的队列,并等待临时队列上的响应。问题是,运行 的复杂查询慢慢意味着单线程消费者陷入困境……如果一个查询需要五分钟,则在第一个查询完成之前,不会对该数据库进行其他查询。查询本身是原子的,我们不在 JMS 级别使用任何方式的事务处理。我正在考虑的解决方案是对使用者进行多线程处理,但我想确保我不会 运行 违反任何 ActiveMQ 或 JMS 限制。
我知道我可以从队列切换到主题,然后我可以 运行 我今天拥有的跨多个线程。它可能会变成这样,但就目前而言,队列结构构成了一个以多种方式使用的“API”,因此它不容易更改为基于主题的东西。
相反,我设想一个主线程在从总线获取消息方面就像当前的消费者一样,除了不是内联处理消息(就像我们现在所做的那样),消息将排队到一个单独的线。子线程将执行数据库工作,然后将结果发送回其临时队列中的原始请求者。
如果我正确理解规范,我可以使用跨线程共享的单个“连接”。只有一个消费者,所以它会继续处于消息接收循环中,就像今天一样。在新的子线程中,我们将在现有连接上启动一个单独的 JMS 会话(会话不能共享),等待工作,处理查询,最后将任何结果发送到请求者的临时队列,以便他得到他的输出。我不认为我们需要大量的并行性,所以我想只预分配一些子线程并等待工作。
问题如下:
- 我能否从子线程之一发送到请求者的临时队列?
- 我可以在我的每个子线程中创建一个会话并反复使用它吗?
- 我预计在什么情况下单个连接会不堪重负?
- 代理上是否有我必须调整的配置设置来处理我可能有很多倍会话的事实?
- 如果有多个处理器内核、足够的数据库连接等等,在 JMS 级别是否有任何“陷阱”会阻止我的方法真正并行?
- 是否有更好的方法来为慢速事务实现更好的吞吐量?
这听起来像是工作模型,队列是一个不错的选择。如果您希望 相同 查询请求由多个系统处理,主题会很好。
是的。临时队列的唯一限制是,一旦不再有消息或生产者或消费者附加,它就会消失。另一种方法是使用真正的队列并使用 ActiveMQ 的垃圾收集器 'gc' 来自动清理它们。此处的优势在于,您可以更容易地了解正在使用的队列以及是否有掉队者。
会话可以在生产者和消费者之间共享。 JMS 对象层次结构类似于 JDBC 对象层次结构。你有彼此的子对象。在低负载和低连接数(例如,每个 CPU 核心少于 8 个连接)下,为每个线程设置专用的连接会话消费者对象并没有真正的危害——尤其是如果您打开池。它使错误处理和回滚更容易。
延迟 and/or 网络 I/O。如果您每秒处理的消息少于 512 条,消息大小为 4k 或更小,则一个连接不是问题。
取决于连接总数和每分钟消息数以及消息大小。
错误处理。如果您执行 JMS 本地事务(推荐!),您的错误处理是在会话级别进行回滚。
不,你很好!多线程消费者是解决缓慢消费者模式的首选方法。
建议--
- 为 ActiveMQ 连接配置池连接工厂
- 在 try {} catch {} finally {} 块中实现标准创建连接、会话、消费者、接收循环并在每条消息后关闭所有资源
- 让这里的代码多线程--^
连接池防止代理连接抖动。这种模式对于错误处理和避免导致消息丢失的资源泄漏是最可靠的。