JMS消息性能:大量主题/队列 vs.广泛过滤(消息选择器)

24

我正在开发一个项目,将大量使用JBoss Messaging (JMS)。我的任务是构建一个易于使用的消息包装器来方便其他开发人员使用,并考虑使用JMS的消息选择器来提供过滤技术,以最小化不必要的消息发送。我很好奇是否有人在性能方面有相关经验?我的担忧是,JMS提供程序可能会因为消息选择器而变得缓慢,从而完全打败整个目的。但与为每种消息类型创建长列表的主题/队列相比,这会更加方便。

最终,我无疑会使用两者的组合,但无论我倾向于哪一种方式,都会关心其对性能的影响。

5个回答

20
正如马丁所提到的,大多数JMS实现默认会在客户端处理消息选择器,除非它们是持久订阅的一部分,当有大量消息未通过选择器时,大多数JMS实现也会在服务器上处理它们,以避免太多消息被持久化。有些系统(比如SonicMQ)允许您指定消息选择器应在服务器上处理,这是一个不错的选项,适用于消息代理具有多余CPU但消费者没有的情况。
请注意,虽然基于主题的选择通常更快,但它可能非常繁琐,因为如果您想监听5个不同的东西,则必须有5个不同的MessageConsumer。而每个 Naive 驱动器实现中的消息接收者都是一个不同的线程,这可能会开始累积。出于这个原因,通常很有用从发布支持两个,以便某些客户端只能监听他们想要的主题,而其他客户端可以使用消息选择器(或基于代码的选择器)监听他们想要的主题层次结构(例如 foo.#) 。
但是,您应始终针对您的应用程序和代理进行测试。每个代理程序都以不同的方式处理情况,并且每个应用程序的功能也不同。您不能只是说“始终使用技术X”,因为针对客户端导向的消息处理的每种技术都具有不同的权衡。进行基准测试,进行基准测试,进行基准测试。
需要注意的一件事是,消息选择器不能动态更改,因此您有可能丢失消息或必须手动管理一个复杂的切换场景。想象以下用例:
  1. 您正在侦听形式为(Ticker in ('CSCO'、'MSFT')的消息选择器
  2. 用户想要开始侦听AAPL
  3. 您必须关闭旧的MessageConsumer,并启动一个新的以 (Ticker in ('CSCO, 'MSFT', 'AAPL')) 形式的消息选择器
  4. 在切换过程中,您可能会丢失消息(因为在启动新的MessageConsumer之前关闭了旧的MessageConsumer),或者您必须手动删除重复项(因为在旧的MessageConsumer关闭之前已经启动了新的MessageConsumer)

1
感谢您为消息选择器这个黑暗的艺术带来了一点光明。 - Stephen Harmon

7

我的建议:

我曾经对ActiveMQ提出了完全相同的问题。

  • 首先,我没有使用选择器并创建了很多主题。性能非常差,因为代理无法处理数百个主题而不需要大量资源。
  • 然后我使用了主题/选择器的组合。现在我只有少量的主题,选择工作得很好。但负载不是很重,不超过10个msg/s

我开发了一个抽象层,使开发人员可以编写代码而不需要问问题,并且我们通过切换实现进行了测试。


非常有用的信息。这证实了我一直担心的问题,即仅创建无尽的JMS目标。感谢您的输入! - James

3
不同的实现方式,但我会分享我与BEA JMS产品的高级架构师进行的一次对话。我提到了使用选择器,他评论了一些类似于“好吧,如果你不想让它执行”的话。
我们的应用程序每秒处理10条消息。他可能习惯于处理每秒100到1000条的复杂问题。除非您处于这些更高范围内或硬件非常慢,否则多个队列/主题或选择器可能都能正常工作。
在唐的观点中,JMS易于使用...我们选择了一个包装器来抽象东西。一旦涉及到强大的重新连接和正确处理多线程/异步侦听器等问题,编写代码的错误方式很多。对我们来说,将细节包装起来,使客户端可以保持对大部分细节的无知是非常值得的。

John,谢谢你的留言。这在某种程度上是我担心的问题,尽管我真的很想知道JBoss的新消息实现是否做得很好。我完全同意使用包装器来抽象事物,但不幸的是,我们每秒将处理数百条消息 :( - James
3
如果JBossMQ不能支持每秒数百条消息的消息选择器,请使用新的消息队列实现。我已经在其他系统中每秒运行了数万条消息。 - Kirk Wylie
@KirkWylie,您能否建议其他哪些MQ在选择器方面提供如此高的性能? - Riyafa Abdul Hameed

3
从我使用JBoss MQ实现的经验来看,消息选择器被客户端用于过滤消息。显然,这意味着主题中的每条消息仍会发送给每个接收者,即使他们忽略它。另一方面,服务器上不同的队列和主题将影响服务器性能。
我认为选择器的增多会影响客户端和网络负载,而主题和队列的增多则会影响服务器负载。显然,网络负载、消息消费者负载和消息生产者负载都有不同的扩展方式。
除了简单情况外,包装器变得棘手;我建议您将错误处理和JMS API包装成一个简单的消息传递API,在概念上结构化以满足您特定的需求。然后,在底层,您可以轻松地更改到上述任何不同的设计。

2
我只能谈谈我使用 JBoss MQ 的经验。嗅探流量时,确实看到消息在被 JMS 实现的客户端过滤之前到达客户端。 - Martin
2
詹姆斯 - 我不认为JMS规范说明选择器过滤需要发生在哪里。这是实现质量的问题。你可能希望它发生在服务器端,但我没有规范可以指出其他错误的地方。 - John M

2

嗯,我有些怀疑。JMS非常易于使用。我见过有人尝试过其他更易于使用的解决方案,但最终效果不佳且存在漏洞。


我通常会同意,但是由于需要发送的消息数量较大,需要做一些工作来确保不必要的消息被最小化。此外,我们有许多开发人员对Java的了解很少,坦率地说,这让他们感到害怕。 :) - James
用某种服务包装它怎么样?我遇到过这样的情况很合适。你得判断它是否适合你。 - Don Branson
这基本上就是我正在做的事情。然而,这些服务涉及到上述的性能问题。 - James
我使用了消息选择器方法,遵循了修改后的竞争消费者模式。性能对于我们的应用程序来说足够好,每天处理大约150万个事务,使用4或6个Sun盒子。 - Don Branson
使用Spring JmsTemplate怎么样?你不需要使用Spring的其他部分,它作为一个通用的JMS包装层非常好。 - Kirk Wylie
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接