Spring 如何同时使用兔子连接缓存模式和自动声明功能?

Spring 如何同时使用兔子连接缓存模式和自动声明功能?,spring,spring-amqp,spring-rabbit,Spring,Spring Amqp,Spring Rabbit,报告说: 从1.3版开始,可以将CachingConnectionFactory配置为缓存连接以及通道。在这种情况下,每次调用createConnection()都会创建一个新连接(或从缓存中检索一个空闲连接)。关闭连接会将其返回到缓存(如果尚未达到缓存大小)。在这样的连接上创建的通道也被缓存。在某些环境中,使用单独的连接可能很有用,例如使用HA集群中的数据,结合负载平衡器,连接到不同的集群成员。将cacheMode设置为cacheMode.CONNECTION 我在负载平衡器后面有一个HA集群

报告说:

从1.3版开始,可以将
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上声明它们之间的区别是什么?我希望它是在任意连接上创建的,因为某些类型的队列(例如独占队列)仅在创建它们的连接上可用。