spring-amqp 具有不同routingKey的多个队列
spring-amqp Multiple queues with different routingKey
我最近开始学习 Spring 和 spring-amqp 所以这个问题可能看起来很基础所以请原谅。
我有多个队列,它们位于不同的主机上并且具有不同的 QueueName、RoutingKey、虚拟主机、用户、密码。我正在为这些队列编写发布逻辑,但无法决定我是否应该为每个队列配置 class,还是可以在 XML 中完成。
创建 class 以获取有关队列的所有信息(主机、虚拟主机、用户名等)的方法工作正常,如 this example 中所述。
我创建了一个@Configuration class 并为该队列定义了所有bean。但是我需要做
ApplicationContext context = new AnnotationConfigApplicationContext(MyQueueConfiguration.class);
AmqpTemplate amqpTemplate = context.getBean(AmqpTemplate.class);
amqpTemplate.convertAndSend("Hello World!!");
所以我的要求是:
- 由于我有很多队列需要在应用程序启动时实例化,一旦tomcat启动,connections/channels到queue/rabbit集群应该被建立。
- 然后,一旦有 POST 请求到达我的应用程序,我需要根据 POST 参数将消息发布到队列之一。
所以对于每个队列我总是需要做:
ApplicationContext context = new AnnotationConfigApplicationContext(HelloWorldConfiguration.class);
或者有没有办法 Spring 加载我所有的队列配置 classes 并且只使用像这样的对象:
// calling code when I get a POST request
MyQueueConfigurationClass.publishMessage(payload, queueName);
// The implementation code
public boolean publishMessage(String payload, String queueName){
// Get Bean for the **queueName** somehow
AmqpTemplate amqpTemplate = context.getBean(AmqpTemplate.class);
// Use the bean to send the message
amqpTemplate.convertAndSend(payload);
}
- 那么我怎样才能获得确切队列的 amqpTemplate 而不是每次都做
new AnnotationConfigApplicationContext()
?
- 每次请求到达我的服务时都执行新的 AnnotationConfigApplicationContext 有什么危害? [我猜测为每个请求创建一个新对象不是一个好主意]
你不应该每次都创建一个新的上下文;那太浪费了。
您可以将多个连接工厂(每个兔子主机一个)添加到根(或网络)上下文,然后将 Routing Connection Factory 与 sendConnectionFactorySelectorExpression
一起使用到 select正确的主机基于您发送的消息。
或者,您可以简单地为每台服务器连接不同的 RabbitTemplate
。
编辑:
要使用 SimpleRoutingConnectionFactory
,请执行类似...
try {
SimpleResourceHolder.bind(routingCF, keyForThisMessage);
rabbitTemplate.convertAndSend(message);
}
finally {
SimpleResourceHolder.unbind(routingCF);
}
(这将适用于未修改的 RabbitTemplate
)或...
<rabbit:template id="routingTemplate"
connection-factory="rcf"
send-connection-factory-selector-expression="messageProperties.headers['cfKey']" />
<bean id="rcf" class="org.springframework.amqp.rabbit.connection.SimpleRoutingConnectionFactory">
<property name="targetConnectionFactories">
<map>
<entry key="foo" value-ref="cf1"/>
<entry key="bar" value-ref="cf2"/>
</map>
</property>
<property name="defaultTargetConnectionFactory" ref="defaultCF"/>
</bean>
...然后...
this.routingTemplate.convertAndSend("exchange", "routingKey", "xyz", new MessagePostProcessor() {
@Override
public Message postProcessMessage(Message message) throws AmqpException {
message.getMessageProperties().setHeader("cfKey", "foo");
return message;
}
});
有一个完整的测试用例here。
我最近开始学习 Spring 和 spring-amqp 所以这个问题可能看起来很基础所以请原谅。
我有多个队列,它们位于不同的主机上并且具有不同的 QueueName、RoutingKey、虚拟主机、用户、密码。我正在为这些队列编写发布逻辑,但无法决定我是否应该为每个队列配置 class,还是可以在 XML 中完成。
创建 class 以获取有关队列的所有信息(主机、虚拟主机、用户名等)的方法工作正常,如 this example 中所述。 我创建了一个@Configuration class 并为该队列定义了所有bean。但是我需要做
ApplicationContext context = new AnnotationConfigApplicationContext(MyQueueConfiguration.class);
AmqpTemplate amqpTemplate = context.getBean(AmqpTemplate.class);
amqpTemplate.convertAndSend("Hello World!!");
所以我的要求是:
- 由于我有很多队列需要在应用程序启动时实例化,一旦tomcat启动,connections/channels到queue/rabbit集群应该被建立。
- 然后,一旦有 POST 请求到达我的应用程序,我需要根据 POST 参数将消息发布到队列之一。
所以对于每个队列我总是需要做:
ApplicationContext context = new AnnotationConfigApplicationContext(HelloWorldConfiguration.class);
或者有没有办法 Spring 加载我所有的队列配置 classes 并且只使用像这样的对象:
// calling code when I get a POST request
MyQueueConfigurationClass.publishMessage(payload, queueName);
// The implementation code
public boolean publishMessage(String payload, String queueName){
// Get Bean for the **queueName** somehow
AmqpTemplate amqpTemplate = context.getBean(AmqpTemplate.class);
// Use the bean to send the message
amqpTemplate.convertAndSend(payload);
}
- 那么我怎样才能获得确切队列的 amqpTemplate 而不是每次都做
new AnnotationConfigApplicationContext()
? - 每次请求到达我的服务时都执行新的 AnnotationConfigApplicationContext 有什么危害? [我猜测为每个请求创建一个新对象不是一个好主意]
你不应该每次都创建一个新的上下文;那太浪费了。
您可以将多个连接工厂(每个兔子主机一个)添加到根(或网络)上下文,然后将 Routing Connection Factory 与 sendConnectionFactorySelectorExpression
一起使用到 select正确的主机基于您发送的消息。
或者,您可以简单地为每台服务器连接不同的 RabbitTemplate
。
编辑:
要使用 SimpleRoutingConnectionFactory
,请执行类似...
try {
SimpleResourceHolder.bind(routingCF, keyForThisMessage);
rabbitTemplate.convertAndSend(message);
}
finally {
SimpleResourceHolder.unbind(routingCF);
}
(这将适用于未修改的 RabbitTemplate
)或...
<rabbit:template id="routingTemplate"
connection-factory="rcf"
send-connection-factory-selector-expression="messageProperties.headers['cfKey']" />
<bean id="rcf" class="org.springframework.amqp.rabbit.connection.SimpleRoutingConnectionFactory">
<property name="targetConnectionFactories">
<map>
<entry key="foo" value-ref="cf1"/>
<entry key="bar" value-ref="cf2"/>
</map>
</property>
<property name="defaultTargetConnectionFactory" ref="defaultCF"/>
</bean>
...然后...
this.routingTemplate.convertAndSend("exchange", "routingKey", "xyz", new MessagePostProcessor() {
@Override
public Message postProcessMessage(Message message) throws AmqpException {
message.getMessageProperties().setHeader("cfKey", "foo");
return message;
}
});
有一个完整的测试用例here。