使用Apache NMS故障转移URI时连接阻塞及工厂实现缺失问题
问题分析与解决方案
1. 修复No IConnectionFactory implementation found异常
这个错误的核心是故障转移URI格式错误:
- 错误格式:
activemq:failover:(activemq:tcp://localhost:61616,...) - 正确格式:
failover:(tcp://localhost:61616,tcp://localhost:61617,tcp://localhost:61618) - 原因:
failover是NMS定义的传输协议方案,用于封装底层ActiveMQ TCP连接,不需要额外添加activemq:前缀,否则NMS无法识别对应的连接工厂实现。
2. 解决异步调用阻塞问题
阻塞通常由同步上下文死锁或异步调用处理不当导致,可通过以下方式修复:
- 全程使用异步await+ConfigureAwait(false):避免捕获当前同步上下文,防止死锁,示例代码:
// 创建连接工厂 var factory = new ConnectionFactory("failover:(tcp://localhost:61616,tcp://localhost:61617,tcp://localhost:61618)"); // 创建连接 var connection = await factory.CreateConnectionAsync().ConfigureAwait(false); // 启动连接 await connection.StartAsync().ConfigureAwait(false); // 创建会话 var session = await connection.CreateSessionAsync(AcknowledgementMode.AutoAcknowledge).ConfigureAwait(false); - 禁止混用同步阻塞调用:子Task中不要使用
.Result、.Wait()等同步等待方法,全程用await,否则会在有同步上下文的环境(如ASP.NET、WPF)中触发死锁。 - 检查Polly重试策略:确保重试逻辑针对异步方法设计,使用Polly的
AsyncPolicy而非同步Policy,示例:var retryPolicy = Policy .Handle<NMSConnectionException>() .WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))); await retryPolicy.ExecuteAsync(async () => { using var connection = await factory.CreateConnectionAsync().ConfigureAwait(false); await connection.StartAsync().ConfigureAwait(false); // 后续生产逻辑 });
3. 额外排查点
- 确认所有ActiveMQ Classic Broker节点的
transportConnector配置正常,确保开启了TCP连接支持,且没有限制故障转移相关的参数(如wireFormat.maxInactivityDuration不要设置过小)。 - 尝试将NMS.ActiveMQ版本降级至v2.0.0,与NMS v2.0.0版本保持一致,避免版本不兼容引发的隐性问题。
- 每个子Task独立创建IConnection、ISession实例,不要跨Task共享这些资源,故障转移客户端每个连接实例维护独立的故障转移状态。
内容的提问来源于stack exchange,提问作者Aidos
相关产品推荐
相关产品推荐

