ActiveMQ Queue vs Topic vs VirtualTopic
之前写过一篇文章讨论VirtualTopic,但觉得不够透彻,这里再根据实验结果进行一次横向对比破除模糊和选择困难症。
文章中核心对比要素是:消息副本和负载均衡
Queue的特点和优势
ActiveMQ中Queue适用于“一对一”场景,单条消息无副本,只会被一个消费者消费。如果单个队列同时有多个消费者连接,则消息会按照一定的顺序依次发送给不同消费者消费,例如10条消息发送给5个消费者,那么消费者(1,2,3,4,5)分别获得(2,1,3,2,2)条消息,这就实现了负载均衡。
所以Queue的特点是:无副本,可负载
Topic的特点和优势
ActiveMQ中Topic适用于“一对多”场景,单条消息有副本,同时被多个消费者消费,如果单个Topic同时有多个消费者连接,则消息按照副本形式全量发送给不同消费者,例如10条消息发送给5个消费者,那么消费者(1,2,3,4,5)分别获得(10,10,10,10,10)条消息,显然无法实现负载均衡。
所以Topic的特点是:有副本,不可负载
VirtualTopic的特点和优势
Queue是无副本,可负载, Topic是有副本,不可负载, 那么还有一种场景需要有副本,可负载,为了满足这种需求,VirtualTopic机制被加入了进来,VirtualTopic使用生产者发送的Topic实现了有副本, 使用消费者消费的Queue实现了可负载,所以VirtualTopic的特点是:有副本,可负载
这里补充一下VirtualTopic的使用说明:
VirtualTopic是一种内嵌机制,默认开启无需配置,使用者通过使用特殊命名的Topic和Queue来使用VirtualTopic机制,默认的命名方式是:
Topic: VirtualTopic.>
Queue: Consumer.*.VirtualTopic.>
# * 和 > 表示通配符
# 例如如果Topic命名为: VirtualTopic.Test,那么Queue就要命名为Consumer.A.VirtualTopic.Test 才能收到来自Topic分发的消息
当然我们可以自己配置相应的命名方式:
vim activemq.xml
<destinationInterceptors>
<virtualDestinationInterceptor>
<virtualDestinations>
<virtualTopic name="NewVirtualTopic.>" prefix="VirtualTopicConsumers.*."/>
</virtualDestinations>
</virtualDestinationInterceptor>
</destinationInterceptors>
# <virtualTopic name="NewVirtualTopic.>" prefix="VirtualTopicConsumers.*."/> 中 name表示 Topic的命名方式,prefix表示 Queue相对于Topic的前缀
# 例如Topic 需要命名为 NewVirtualTopic.Test , Queue需要命名为 VirtualTopicConsumers.A.NewVirtualTopic.Test
# * 和 > 都是通配符,可以混用
总结
到这里,我们可以按照 消息副本和负载均衡两个关键点来对三者进行区分:
无副本,可负载 使用 Queue
有副本,不可负载 使用 Topic
有副本,可负载 使用VirtualTopic
这两个区分点可以说是这三种机制的核心特点,并且不论是否持久化都成立。我们可以具此匹配不同的业务场景酌情使用,至于剩下的那种情况应该是没有需求的。