为啥 DefaultMessageListenerContainer 不应该使用 CachingConnectionFactory?

Posted

技术标签:

【中文标题】为啥 DefaultMessageListenerContainer 不应该使用 CachingConnectionFactory?【英文标题】:Why DefaultMessageListenerContainer should not use CachingConnectionFactory?为什么 DefaultMessageListenerContainer 不应该使用 CachingConnectionFactory? 【发布时间】:2014-03-25 21:53:55 【问题描述】:

我正在阅读 DefaultMessageListenerContainer 上的 spring 文档

它说“注意:不要将 Spring 的 CachingConnectionFactory 与动态缩放结合使用。理想情况下,根本不要将它与消息侦听器容器一起使用,因为通常最好让侦听器容器本身在其中处理适当的缓存“

谁能解释为什么?

【问题讨论】:

【参考方案1】:
    您确实不需要为侦听器容器缓存会话,因为会话是长期存在的;缓存对于频繁的短期使用非常有用,例如使用 JmsTemplate。 问题出在cacheConsumers = true(默认)的时候。当使用动态缩放并且监听器停止时,会话将返回到缓存中,但代理不知道没有人会真正从该会话中消费,因此您会遇到位于缓存中的消息,直到这些消息才会被读取当音量增加时,该会话恰好被重用。

注意:如果您希望在容器线程上运行的 JmsTemplate 参与容器事务,您应该使用 CachingConnectionFactory 以便可以缓存生产者,但您应该禁用缓存如果您有可变并发,工厂中的消费者。

【讨论】:

感谢加里的回复和解释。 Gary 只是好奇 listener containerDefaultMessageListenerContainer 是否也应该使用 SingleConnectionFactory。因为它是 CachingConnectionFactory 类的超类。 手动,不,没关系;问题在于在容器中使用变量并发时缓存消费者;您最终可能会在缓存中“卡住”实时消费者。 好的,我可以将 SingleConnectionFactory 与 DefaultMessageListenerContainer 一起使用。当我有两个具有 setSubscriptionDurable true 的 DefaultMessageListenerContainer 时出现问题,因此我需要为 setClientId 和 setDurableSubscriptionName 值设置两个不同的值。 如果我使用 SingleConnectionFactory 或 CachingConnectionFactory 总是我得到“无法刷新目标 'topic://branch' 的 JMS 连接 - 在 5000 毫秒内重试。原因:共享连接的代理不支持 setClientID 调用。设置SingleConnectionFactory 上的 'clientId' 属性。" 我不确定您还需要多少详细说明。假设您有 5 个消费者,并且工作负载下降,因此容器停止了消费者。如果缓存到位,消费者将保持打开状态并放入缓存中,而不是关闭它。由于代理对此一无所知,他认为它仍在消费,因此很高兴地向它发送预取消息。由于容器没有使用该消费者,因此在其他 4 个容器中的工作负载增加以决定需要另一个消费者并再次使用缓存的消费者之前,没有人会看到这些消息。

以上是关于为啥 DefaultMessageListenerContainer 不应该使用 CachingConnectionFactory?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 DataGridView 上的 DoubleBuffered 属性默认为 false,为啥它受到保护?

为啥需要softmax函数?为啥不简单归一化?

为啥 g++ 需要 libstdc++.a?为啥不是默认值?

为啥或为啥不在 C++ 中使用 memset? [关闭]

为啥临时变量需要更改数组元素以及为啥需要在最后取消设置?

为啥 CAP 定理中的 RDBMS 分区不能容忍,为啥它可用?