跳到主要内容
版本:4.1.1

多 Broker(或集群)支持

Doubao 中英对照 Multiple Broker (or Cluster) Support

2.3 版本为单个应用程序与多个 broker 或 broker 集群之间的通信增加了更多便利。在消费者一侧,主要好处是基础设施可以自动将自动声明的队列关联到相应的 broker。

下面用一个例子最能说明这一点:

@SpringBootApplication(exclude = RabbitAutoConfiguration.class)
public class Application {

public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}

@Bean
CachingConnectionFactory cf1() {
return new CachingConnectionFactory("localhost");
}

@Bean
CachingConnectionFactory cf2() {
return new CachingConnectionFactory("otherHost");
}

@Bean
CachingConnectionFactory cf3() {
return new CachingConnectionFactory("thirdHost");
}

@Bean
SimpleRoutingConnectionFactory rcf(CachingConnectionFactory cf1,
CachingConnectionFactory cf2, CachingConnectionFactory cf3) {

SimpleRoutingConnectionFactory rcf = new SimpleRoutingConnectionFactory();
rcf.setDefaultTargetConnectionFactory(cf1);
rcf.setTargetConnectionFactories(Map.of("one", cf1, "two", cf2, "three", cf3));
return rcf;
}

@Bean("factory1-admin")
RabbitAdmin admin1(CachingConnectionFactory cf1) {
return new RabbitAdmin(cf1);
}

@Bean("factory2-admin")
RabbitAdmin admin2(CachingConnectionFactory cf2) {
return new RabbitAdmin(cf2);
}

@Bean("factory3-admin")
RabbitAdmin admin3(CachingConnectionFactory cf3) {
return new RabbitAdmin(cf3);
}

@Bean
public RabbitListenerEndpointRegistry rabbitListenerEndpointRegistry() {
return new RabbitListenerEndpointRegistry();
}

@Bean
public RabbitListenerAnnotationBeanPostProcessor postProcessor(RabbitListenerEndpointRegistry registry) {
MultiRabbitListenerAnnotationBeanPostProcessor postProcessor
= new MultiRabbitListenerAnnotationBeanPostProcessor();
postProcessor.setEndpointRegistry(registry);
postProcessor.setContainerFactoryBeanName("defaultContainerFactory");
return postProcessor;
}

@Bean
public SimpleRabbitListenerContainerFactory factory1(CachingConnectionFactory cf1) {
SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(cf1);
return factory;
}

@Bean
public SimpleRabbitListenerContainerFactory factory2(CachingConnectionFactory cf2) {
SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(cf2);
return factory;
}

@Bean
public SimpleRabbitListenerContainerFactory factory3(CachingConnectionFactory cf3) {
SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(cf3);
return factory;
}

@Bean
RabbitTemplate template(SimpleRoutingConnectionFactory rcf) {
return new RabbitTemplate(rcf);
}

@Bean
ConnectionFactoryContextWrapper wrapper(SimpleRoutingConnectionFactory rcf) {
return new ConnectionFactoryContextWrapper(rcf);
}

}

@Component
class Listeners {

@RabbitListener(queuesToDeclare = @Queue("q1"), containerFactory = "factory1")
public void listen1(String in) {

}

@RabbitListener(queuesToDeclare = @Queue("q2"), containerFactory = "factory2")
public void listen2(String in) {

}

@RabbitListener(queuesToDeclare = @Queue("q3"), containerFactory = "factory3")
public void listen3(String in) {

}

}

如你所见,我们声明了 3 套基础设施(连接工厂、admin、容器工厂)。如前所述,@RabbitListener 可以指定使用哪个容器工厂;本例中它们还使用了 queuesToDeclare,如果队列不存在,就会在 broker 上声明该队列。通过按 <容器工厂名>-admin 的约定命名 RabbitAdmin bean,基础设施就能确定应由哪个 admin 来声明队列。这对于 bindings = @QueueBinding(…​) 同样有效,届时交换机和绑定也会被声明。它不适用于 queues,因为 queues 要求队列已经存在。

在生产者一侧,提供了一个便捷的 ConnectionFactoryContextWrapper 类,使 RoutingConnectionFactory(参见路由连接工厂)的使用更加简单。

如你在上面所见,已经添加了一个 SimpleRoutingConnectionFactory bean,其路由键为 one、two 和 three。还有一个使用该工厂的 RabbitTemplate。下例展示了如何使用该模板配合包装器路由到其中一个 broker 集群。

@Bean
public ApplicationRunner runner(RabbitTemplate template, ConnectionFactoryContextWrapper wrapper) {
return args -> {
wrapper.run("one", () -> template.convertAndSend("q1", "toCluster1"));
wrapper.run("two", () -> template.convertAndSend("q2", "toCluster2"));
wrapper.run("three", () -> template.convertAndSend("q3", "toCluster3"));
};
}