请考虑以下情形:
可以说有4个微服务,每个微服务应该有自己的队列。让我们使用以下方案
现在所有上述微服务都应该将消息发送到主队列,让我们调用queue.master。当微服务A要向微服务B发送消息时,它打算将其发送到主队列,主队列将其路由到微服务B,依此类推。换句话说,没有微服务队列知道彼此的队列,它只知道主队列,并且主队列将相应地“路由”消息。
现在问题出在上述方案的配置中。对于基于XML的应用程序,它将非常简单明了。我将定义<destinationInterceptors>
标签以及<compositeQueue>
和<forwardOnly>
标签,如下所示:
<destinationInterceptors>
<virtualDestinationInterceptor>
<virtualDestinations>
<compositeQueue name="queue.master" forwardOnly="false">
<forwardTo>
<queue physicalName="queue.A" />
<queue physicalName="queue.B" />
<queue physicalName="queue.C" />
</forwardTo>
</compositeQueue>
</virtualDestinations>
</virtualDestinationInterceptor>
</destinationInterceptors>
[另外,我将在标签中使用选择器,以便它可以“过滤”出消息并相应地发送它们。上述基于XML的方案按预期工作。但我希望在程序执行期间也可以使用上述配置。基本上我想做的是:
经纪人将要启动
微服务A启动,将向代理发送消息或Web请求,说“嗨,我起来了,为我创建一个队列并将其与主队列绑定”。
微服务B启动并执行相同的操作。
到目前为止,我所做的是通过java API调用创建代理,并通过java方法和类似的类配置了virtualdestination和复合队列:
VirtualDestinationInterceptor virtualDestinationInterceptor = new VirtualDestinationInterceptor();
CompositeQueue compositeQueue = new CompositeQueue();
Queue queue = new ActiveMQQueue("queue.A"); // create the child queue of microservice
compositeQueue.setName("master.queue"); // the master queue .
compositeQueue.setForwardTo(Arrays.asList(queue));
virtualDestinationInterceptor.setVirtualDestinations(new VirtualDestination[]{compositeQueue});
DestinationInterceptor[] destinationInterceptors = new DestinationInterceptor[]{virtualDestinationInterceptor};
brokerService.setDestinationInterceptors(destinationInterceptors);
上面的代码驻留在@Configuration类内部的BrokerService
bean中。当springboot应用程序(代理)启动时,它创建了上面的child.queue并将其与master.queue绑定(一切都很好,完美),但是即使设置了代理,我也想要做以上的事情。
为此,我创建了一个小型服务类和一个控制器类,并将上面的代码片段放入称为createQueue(String queueName)
的方法中,并将其用于我的控制器中。当访问该端点时,什么也没有发生。没有错误,没有警告,代码被执行但是它没有反映在代理中。我看不到新创建的队列,并且将消息发送到主队列也无法将其转发到子队列。
这种情况甚至可能吗?在运行时配置和制作CompositeQueues?
事实证明他们的在线文档不一致。在此问题(https://activemq.apache.org/what-is-the-difference-between-a-virtual-topic-and-a-composite-destination)中,它明确声明以下语句:
虚拟主题与复合主题之间的主要区别取消定意是使用Composite Destination的消费者列表目的地是静态且硬连线]]。而虚拟主题位于运行时可以动态创建并添加新的使用者或队列订阅,而不必重新配置代理。
但是!在此页面上,存在版本5.9的发行说明(https://activemq.apache.org/runtime-configuration),它指出某些标记是可在运行时配置的。整个文档应保持一致。
p.s是为了防止有人想这样做:您必须在代理配置中添加<runtimeConfigurationPlugin checkPeriod="1000" />
,并在主代理标签中使用此属性start="false"
。