В RabbitMQ RPC через несколько экземпляров в RabbitMQ
у меня есть три клиента, каждый со своими экземплярами RabbitMQ, и у меня есть приложение (назовем его appA), которое имеет свой собственный экземпляр RabbitMQ, три клиентских приложения (app1, app2, app3) хотят использовать службу на appA.
служба на appA требует связи RPC, app1, app2 и app3 каждый имеет бронирование.запрос очереди и бронирование.очередь ответов.
С помощью плагина shovel я могу переслать все бронирование.запрос сообщения из app1-3 в appA:
Shovel1
virtualHost=appA,
name=booking-request-shovel,
sourceURI=amqp://userForApp1:password@app1-server/vhostForApp1
queue=booking.request
destinationURI=amqp://userForAppA:password@appA-server/vhostForAppA
queue=booking.request
setup another shovel to get booking requests from app2 and app3 to appA in the same way as above.
теперь appA ответит на запрос о бронировании.очередь ответов, мне нужно сообщение ответа бронирования на rabbitMQ-appA, чтобы вернуться к правильному бронированию.очередь ответов на app1, app2 или app3, но не на все из них - как настроить лопату / федеративную очередь на rabbitMQ-appA, которая будет пересылать ответ обратно на правильный rabbitMQ (app1, app2, app3), который ожидает ответа в своем собственном бронировании.ответ очередь?
все эти приложения используют spring-amqp (в случае, если это актуально) Кроме того, я мог бы настроить шаблон rabbitMQ весной, который слушает несколько очередей rabbitMQ и потребляет из каждого из них.
из документации, это то, что типичный потребитель выглядит так:
<rabbit:listener-container connection-factory="rabbitConnectionFactory">
<rabbit:listener queues="some.queue" ref="somePojo" method="handle"/>
</rabbit:listener-container>
можно ли указать несколько фабрик соединений, чтобы сделать это, даже если фабрики соединений находятся в одном экземпляре RabbitMQ, но просто разные vhosts:
обновление:
основываясь на ответе Джоша, у меня было бы несколько фабрик соединений:
<rabbit:connection-factory
id="connectionFactory1"
port="${rabbit.port1}"
virtual-host="${rabbit.virtual1}"
host="${rabbit.host1}"
username="${rabbit.username1}"
password="${rabbit.password1}"
connection-factory="nativeConnectionFactory" />
<rabbit:connection-factory
id="connectionFactory2"
port="${rabbit.port2}"
virtual-host="${rabbit.virtual2}"
host="${rabbit.host2}"
username="${rabbit.username2}"
password="${rabbit.password2}"
connection-factory="nativeConnectionFactory" />
тогда я бы использовал SimpleRoutingConnectionFactory, чтобы обернуть оба соединения-фабрики:
<bean id="connectionFactory" class="org.springframework.amqp.rabbit.connection.SimpleRoutingConnectionFactory">
<property name="targetConnectionFactories">
<map>
<entry key="#{connectionFactory1.virtualHost}" ref="connectionFactory1"/>
<entry key="#{connectionFactory2.virtualHost}" ref="connectionFactory2"/>
</map>
</property>
</bean>
теперь, когда я объявляю свой шаблон rabbitMQ, я бы указал его на SimpleRoutingConnectionFactory вместо отдельных фабрик соединений:
<rabbit:template id="template" connection-factory="connectionFactory" />
... а затем использовать шаблон как я обычно использую его ...
<rabbit:listener-container
connection-factory="connectionFactory"
channel-transacted="true"
requeue-rejected="true"
concurrency="${rabbit.consumers}">
<rabbit:listener queues="${queue.booking}" ref="TransactionMessageListener" method="handle" />
</rabbit:listener-container>
/ / и сообщения потребляются из обоих экземпляров rabbitMQ
... и...
@Autowired
private AmqpTemplate template;
template.send(getExchange(), getQueue(), new Message(gson.toJson(message).getBytes(), properties));
/ / и сообщение публикуется в обе очереди
Я прав?
2 ответов
взгляните на org.springframework.протокол AMQP.кролик.соединение.AbstractRoutingConnectionFactory. Это позволит вам создать несколько фабрик подключения к различным vhosts или различным экземплярам rabbitmq. Мы используем его для приложения multi tenant rabbitmq.
прошло некоторое время, но если вы используете Spring, вы можете создать столько фабрик соединений, сколько хотите, со своими собственными конфигурациями (хост, пользователь/pass, vhost и т. д.), так же, как и вы:
@Bean
@Primary
public ConnectionFactory amqpConnectionFactory1() {
final CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
connectionFactory.setAddresses("...");
connectionFactory.setUsername("...");
connectionFactory.setPassword("...");
connectionFactory.setVirtualHost("...");
return connectionFactory;
}
@Bean
public ConnectionFactory amqpConnectionFactory2() {
final CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
// ...
return connectionFactory;
}
и ваш кролик администратор / шаблон, как вы идете:
@Bean
@Primary
public RabbitAdmin rabbitAdmin1() {
return new RabbitAdmin(amqpConnectionFactory1());
}
@Bean
public RabbitAdmin rabbitAdmin2() {
return new RabbitAdmin(amqpConnectionFactory2());
}
// ...
@Bean
@Primary
public RabbitTemplate rabbitTemplate1() {
RabbitTemplate rabbitTemplate = new RabbitTemplate(amqpConnectionFactory1());
// ...
return rabbitTemplate;
}
@Bean
public RabbitTemplate rabbitTemplate2() {
RabbitTemplate rabbitTemplate = new RabbitTemplate(amqpConnectionFactory2());
// ...
return rabbitTemplate;
}
обратите внимание, что вы должны предоставить @Primary
тег, чтобы включить один основной боб, как только весна не знает, какой из них выбрать, когда вы не сообщите name
явно.
С этим в руках, просто впрысните их нормально вдоль ваших компонентов:
@Autowired
private RabbitTemplate template;
// ...
@Autowired
@Qualifier("rabbitTemplate2") // Needed when want to use the non-primary bean
private RabbitTemplate template;
надеюсь, что это помогает! :)