使用@JmsListener配置concurrency后,Solace连接数超出预期
问题分析与解决方案
你遇到的核心问题是Spring JMS的concurrency参数控制的是消费者线程数,而非Solace的连接/绑定数,实际绑定数超标的原因可能有以下几点:
1. 对concurrency参数的误解
@JmsListener的concurrency="5"表示监听器容器会维护一个固定大小为5的消费者线程池,每个线程对应一个JMS消费者。但这些消费者是否共享连接/会话,取决于你配置的listenerContainerFactory的缓存策略:
- 如果工厂配置了
cacheLevel=CACHE_CONSUMER(Spring默认):所有消费者线程共享同一个JMS连接和会话,此时Solace上应该对应5个消费者绑定,但连接数为1。 - 如果工厂配置了
cacheLevel=CACHE_NONE或CACHE_CONNECTION:每个消费者线程会创建独立的连接或会话,这会导致连接数/绑定数直接等于线程数,甚至更多(比如会话数翻倍)。
2. 容器工厂的额外配置覆盖
检查你的listenerContainerFactory是否有以下配置:
- 是否显式设置了
maxConcurrentConsumers属性且值大于5?concurrency="5"等价于"5-5",但如果工厂里设置了更高的maxConcurrentConsumers,可能会覆盖这个值。 - 是否开启了动态扩容?部分Solace专属的Spring集成组件可能允许根据消息负载自动扩容消费者,导致实际线程数超过设置的5。
3. 多监听器实例或重复注册
- 检查代码中是否存在多个
@JmsListener注解监听同一个队列,或者该监听器Bean被Spring容器多次初始化(比如多配置类扫描、Bean作用域错误)。 - 如果是Spring Boot应用,确认是否通过配置文件(如
application.yml)重复配置了该队列的监听器。
4. Solace端的绑定残留
如果消费者线程异常退出,Solace可能不会立即清理绑定(取决于Solace的client-profile配置,比如idle-timeout设置),导致旧绑定未释放,新绑定又被创建,从而总数超过5。
解决步骤
- 修正容器工厂的缓存策略
确保你的listenerContainerFactory配置了正确的缓存级别,示例代码:@Bean public DefaultJmsListenerContainerFactory listenerContainerFactory(ConnectionFactory connectionFactory) { DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory(); factory.setConnectionFactory(connectionFactory); factory.setCacheLevel(DefaultMessageListenerContainer.CACHE_CONSUMER); // 共享连接和会话 return factory; } - 验证
concurrency的实际生效值
可以通过Spring Actuator的metrics端点(如/actuator/jms/listeners)查看当前活跃的消费者线程数,确认是否确实是5。 - 检查Solace客户端配置
查看Solace连接工厂的配置,是否开启了sharedConnection或类似的共享连接选项,确保多个消费者复用同一个连接。 - 清理Solace端残留绑定
登录Solace管理控制台,手动清理该客户端的旧绑定,同时调整client-profile的idle-timeout参数,缩短空闲绑定的存活时间。
内容的提问来源于stack exchange,提问作者Yogi
相关产品推荐
相关产品推荐

