《搞懂 Spring 的 CachingConnectionFactory:为什么发送消息别直接用原始 ConnectionFactory》

99 阅读3分钟

大家好,我是G探险者!

系列文章的第 5 篇,本篇将聚焦在 发送端的连接池机制,也就是大家在使用 JmsTemplate 发送消息时最常见但容易忽略的问题 —— 是否使用了 CachingConnectionFactory


📌 引入场景

你是否遇到过这样的问题:

  • 用 JmsTemplate 发送消息,第一次成功,第二次就抛连接异常?
  • 每次发送消息都重新连接 MQ,发送延迟很高?
  • MQ 重启后,监听可以恢复,发送却彻底挂死?

这背后的根本原因是:

你直接用了原始的 ConnectionFactory 而没有加上连接池管理。


✅ 一、ConnectionFactory 和 CachingConnectionFactory 是什么?

1️⃣ ConnectionFactory(原始)

  • 来自 JMS 标准(javax.jms.ConnectionFactory
  • 每次创建连接都是真实连接
  • 不具备自动重连、连接复用、Session 缓存能力

2️⃣ CachingConnectionFactory(Spring 提供)

  • 包装一个原始的 JMS ConnectionFactory
  • ✅ 重用连接(默认只有一个连接)
  • ✅ 支持 session 缓存(提升性能)
  • ✅ 支持重连恢复(底层连接失效时自动重建)

⚙️ 二、配置示例:推荐使用方式

// 原始 MQ 连接工厂(IBM MQ 示例)
MQQueueConnectionFactory rawFactory = new MQQueueConnectionFactory();
rawFactory.setHostName("192.168.1.100");
rawFactory.setPort(1414);
rawFactory.setQueueManager("QM1");
rawFactory.setChannel("CHANNEL1");
rawFactory.setTransportType(WMQConstants.WMQ_CM_CLIENT);

// 使用 Spring 的缓存连接工厂进行包装
CachingConnectionFactory cachingFactory = new CachingConnectionFactory(rawFactory);

// ✅ 可选设置缓存 session 数量
cachingFactory.setSessionCacheSize(10);

// 创建 JmsTemplate
JmsTemplate jmsTemplate = new JmsTemplate(cachingFactory);

📊 三、对比分析

功能点原始 ConnectionFactoryCachingConnectionFactory
每次连接是否复用❌ 否,每次都新建✅ 是,复用同一个连接
是否支持自动重连❌ 否✅ 是(连接断开后自动恢复)
Session 是否缓存❌ 否✅ 是(默认缓存一个)
性能表现⛔️ 低,大量连接开销✅ 高,复用连接和 session
使用场景调试、非常简单应用✅ 生产强烈推荐

🔁 四、消息发送中的连接复用机制

JmsTemplate 每次发送消息的流程大致如下:

→ 从 ConnectionFactory 获取连接
→ 创建 Session
→ 创建 Producer
→ 发送消息
→ 关闭资源(除非有缓存)

若使用 CachingConnectionFactory

  • 第一步中,连接将被复用
  • 第二步中,session 会被从缓存中取出或复用
  • 避免每次都连接 MQ,极大提升性能

🧯 五、发送端的重连机制:和监听端不同!

对象重连机制靠谁维护?
DefaultMessageListenerContainerSpring 内部有自动重连逻辑
JmsTemplate❌ 没有内建重连机制,依赖底层连接工厂

因此:

若你使用原始 ConnectionFactory,一旦 MQ 重启,发送端将直接挂死!

只有使用 CachingConnectionFactory,它才会在连接失败时尝试自动重建连接,保证长时间可用性


⚠️ 六、一些开发误区

误区正确做法
JmsTemplate 能自动帮我处理连接❌ 不行,必须自己包装连接工厂
使用事务就能保证可靠发送❌ 发送失败了都不会 retry,要靠连接池重连
MQ 能自动恢复连接❌ 不在发送端,需要 CachingConnectionFactory

☑️ 七、总结建议

场景推荐配置
使用 JmsTemplate 发送消息✅ 使用 CachingConnectionFactory
发送性能要求高✅ 设置 sessionCacheSize ≥ 并发数
需要自动重连✅ CachingConnectionFactory 自动支持
一定要避免每次连接创建开销❗ 千万不要直接使用裸 ConnectionFactory

📘 下一篇预告:

第 6 篇:《JMS 中的事务机制与消息确认模式全解:AUTO_ACK、CLIENT_ACK、SESSION_TRANSACTED 有啥区别?》
我们将系统讲解 JMS 的 4 种消息确认模式,事务控制与 ACK 的关系,以及在 Spring 中如何灵活切换并掌握失败处理策略。