Spring 如何同时使用兔子连接缓存模式和自动声明功能?
报告说: 从1.3版开始,可以将Spring 如何同时使用兔子连接缓存模式和自动声明功能?,spring,spring-amqp,spring-rabbit,Spring,Spring Amqp,Spring Rabbit,报告说: 从1.3版开始,可以将CachingConnectionFactory配置为缓存连接以及通道。在这种情况下,每次调用createConnection()都会创建一个新连接(或从缓存中检索一个空闲连接)。关闭连接会将其返回到缓存(如果尚未达到缓存大小)。在这样的连接上创建的通道也被缓存。在某些环境中,使用单独的连接可能很有用,例如使用HA集群中的数据,结合负载平衡器,连接到不同的集群成员。将cacheMode设置为cacheMode.CONNECTION 我在负载平衡器后面有一个HA集群
CachingConnectionFactory
配置为缓存连接以及通道。在这种情况下,每次调用createConnection()
都会创建一个新连接(或从缓存中检索一个空闲连接)。关闭连接会将其返回到缓存(如果尚未达到缓存大小)。在这样的连接上创建的通道也被缓存。在某些环境中,使用单独的连接可能很有用,例如使用HA集群中的数据,结合负载平衡器,连接到不同的集群成员。将cacheMode
设置为cacheMode.CONNECTION
我在负载平衡器后面有一个HA集群,当我使用CacheMode.CHANEL
时,我可以清楚地看到我的所有通道都来自一个连接,它们都位于同一个主机上
当我切换到CacheMode.CONNECTION
时,我确实看到通道中存在差异,即并非所有通道都位于同一个连接中,因此我看到使用的集群中有不同的主机
所以我认为在这种特殊情况下,第二种配置对我来说很有意义。然而,这些文件还说:
当缓存模式为连接时,不支持自动声明队列等
显然,这也是一个重要的特性,因为我不想手动应用配置中的任何更改
所以,我的问题是,有没有一种方法可以同时使用这两种东西?有两个连接工厂有意义吗,一个用于
RabbitAdmin
,另一个用于rabbitmplate
、侦听器等?问题是我们不知道在哪个连接上声明元素;我们最终会为每一个新创建的连接重新定义一切
如果您同意的话,您可以将自己的连接侦听器添加到连接工厂,并在rabbitAdmin
bean上调用rabbitAdmin.initialize()
(如果缓存模式为channel,则这是Admin中的所有默认侦听器所做的)
或者您可以将RabbitAdmin
子类化,并重写afterPropertieSet()
我想您可以添加更多的逻辑来确定是否确实需要进行声明-请参见RabbitAdmin.afterPropertiesSet()
/**
* If {@link #setAutoStartup(boolean) autoStartup} is set to true, registers a callback on the
* {@link ConnectionFactory} to declare all exchanges and queues in the enclosing application context. If the
* callback fails then it may cause other clients of the connection factory to fail, but since only exchanges,
* queues and bindings are declared failure is not expected.
*
* @see InitializingBean#afterPropertiesSet()
* @see #initialize()
*/
@Override
public void afterPropertiesSet() {
synchronized (this.lifecycleMonitor) {
if (this.running || !this.autoStartup) {
return;
}
if (this.connectionFactory instanceof CachingConnectionFactory &&
((CachingConnectionFactory) this.connectionFactory).getCacheMode() == CacheMode.CONNECTION) {
this.logger.warn("RabbitAdmin auto declaration is not supported with CacheMode.CONNECTION");
return;
}
// Prevent stack overflow...
final AtomicBoolean initializing = new AtomicBoolean(false);
this.connectionFactory.addConnectionListener(connection -> {
if (!initializing.compareAndSet(false, true)) {
// If we are already initializing, we don't need to do it again...
return;
}
try {
/*
* ...but it is possible for this to happen twice in the same ConnectionFactory (if more than
* one concurrent Connection is allowed). It's idempotent, so no big deal (a bit of network
* chatter). In fact it might even be a good thing: exclusive queues only make sense if they are
* declared for every connection. If anyone has a problem with it: use auto-startup="false".
*/
initialize();
}
finally {
initializing.compareAndSet(true, false);
}
});
this.running = true;
}
}
我们可能会在管理员上设置此选项-请随意设置。如果我创建了一个连接并声明了一个队列,那么应该可以使用其他连接访问该队列,那么在连接a或B上声明它们之间的区别是什么?我希望它是在任意连接上创建的,因为某些类型的队列(例如独占队列)仅在创建它们的连接上可用。