我有一个水平可扩展的应用程序。我的应用程序是带有2.1.1.RELEASE的spring框架版本的spring-boot服务。
每个工作程序都有一个队列(和它各自的侦听器),并绑定到类型为“ x-consistent-hash”的交换。我使用Rabbitmq版本3.7.7的Rabbitmq-consistent-hash-exchange插件。
根据消息的message_id(as described here)以一致的方式正确地对消息进行哈希处理,并且始终由与我的应用程序相同的工作队列使用这些消息:
我实现此目的的代码如下:
public static final String EXCHANGE = "e3";
private static final String EXCHANGE_TYPE = "x-consistent-hash";
@Bean
public Queue autoDeleteQueue1() {
return new AnonymousQueue();
}
@Qualifier("testlistenerAdapter")
@Bean
MessageListenerAdapter testlistenerAdapter(TestListener receiver) {
MessageListenerAdapter msgadapter = new MessageListenerAdapter(receiver, "testMessageReceived");
return msgadapter;
}
@Qualifier("testcontainer")
@Bean
SimpleMessageListenerContainer testcontainer(ConnectionFactory connectionFactory,
@Qualifier("testlistenerAdapter") MessageListenerAdapter listenerAdapter) throws IOException {
Connection conn = connectionFactory.createConnection();
Channel ch = conn.createChannel(true);
ch.queueDeclare(autoDeleteQueue1().getName(), true, true, true, null);
ch.queuePurge(autoDeleteQueue1().getName());
Map<String, Object> args = new HashMap<>();
args.put("hash-property", "message_id");
ch.exchangeDeclare(EXCHANGE, EXCHANGE_TYPE, false, false, args);
ch.queueBind(autoDeleteQueue1().getName(), EXCHANGE, "20");
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
container.setQueueNames(autoDeleteQueue1().getName());
container.setMessageListener(listenerAdapter);
return container;
}
我想做的是将所有具有相同message_id的消息路由到与以前相同的工人上,但在不同的队列侦听器上。在第一种情况下,事情很容易,因为一个工人只有一个队列。现在,一个工作人员有多个队列,我希望在同一工作人员中始终对消息进行哈希处理。
我试图通过在每条消息上添加不同的header / routing_key来实现此目的,但是没有成功。
例如,任何带有message_id:“ test”的消息总是路由到同一工作者(让我们说“ worker B”),并且取决于它具有的头文件/ routing_key(foo或bar),foo或bar将使用它。队列侦听器(请参见下图)。我的应用程序的业务逻辑是有状态的,因此我需要具有相同message_id的消息由同一工作人员提供服务。
我尝试了许多实现替代方案,但是似乎这并不是一件容易的事。恐怕我想做的事不可行,因为rabbitmq插件会对队列级别进行哈希处理。一种快速的解决方案是坚持第一种情况。仅保留一种类型的侦听器,然后在同一端点内进行业务逻辑分离。我有什么想法可以实现这种功能,而不必同时合并两个侦听器(foo和bar)的功能?
答案 0 :(得分:0)
这是行不通的。在rabbitmq中,不同的队列侦听器属于不同的队列。
由于每个工作人员都创建自己的队列,因此我只能保证消息始终在同一队列中,而不是在同一工作人员中。
一致的哈希是在队列级别而不是在工作程序级别进行的。
我通过每个工作人员仅维护一个侦听器队列来完成实现。通过这种方式,我可以确保消息始终在同一工作进程中路由。
如果有人有兴趣看看https://github.com/ubitech/generic-policy-engine-with-consistent-hashing
,我的示例项目就在这里