C#.Net IBM MQ多线程应用带用户名密码连接部分失败问题
多线程连接带认证的IBM MQ时部分请求失败的问题解决
问题现象
- 多线程环境下连接带用户认证的IBM MQ QueueManager,仅部分请求成功,其余失败
- 线程数设为1时所有请求正常执行
- 线程数≥2时出现部分成功、部分失败的情况
- 不使用用户认证时,多线程连接完全正常
代码问题分析
- 资源释放的空引用风险:在
PutMessageOnQueue_Inward的finally块中,直接调用objMQQueue.Close(),如果AccessQueue调用失败,objMQQueue会为null,此时执行Close会抛出空引用异常,掩盖原本的连接失败问题。 - 频繁创建销毁连接:每个请求都新建
MQQueueManager实例,多线程下短时间内大量并发认证请求,可能触发MQ服务器的并发连接或认证限制。
解决方案
1. 修复资源释放的空引用问题
修改PutMessageOnQueue_Inward的finally块,先判断对象是否有效再执行释放操作:
finally { if (objMQQueue != null && objMQQueue.OpenStatus) { objMQQueue.Close(); } if (objMQQueueManager != null) { objMQQueueManager.Disconnect(); } }
2. 使用连接池复用MQ连接
避免每个请求新建MQQueueManager,改用连接池复用连接,减少并发认证请求的数量:
public class MQConnectionPool { private static readonly object _lockObj = new object(); private static MQQueueManager _sharedQueueManager; private static Hashtable _connectionProperties; public static void Initialize(Hashtable properties) { _connectionProperties = properties; } public static MQQueueManager GetQueueManager() { if (_sharedQueueManager == null || !_sharedQueueManager.IsConnected) { lock (_lockObj) { if (_sharedQueueManager == null || !_sharedQueueManager.IsConnected) { _sharedQueueManager = new MQQueueManager(Common.QUEUEMANAGER_NAME, _connectionProperties); } } } return _sharedQueueManager; } }
修改AML_MQIntegration构造函数,从连接池获取实例(建议在应用启动时初始化一次连接池):
public AML_MQIntegration() { if (MQConnectionPool.GetQueueManager() == null) { Hashtable properties = new Hashtable(); properties.Add(MQC.TRANSPORT_PROPERTY, MQC.TRANSPORT_MQSERIES_MANAGED); properties.Add(MQC.HOST_NAME_PROPERTY, Common.FTS_MQ_HostName); properties.Add(MQC.CHANNEL_PROPERTY, Common.QUEUE_CHANNEL); properties.Add(MQC.PORT_PROPERTY, Common.FTS_MQ_Port); properties.Add(MQC.USER_ID_PROPERTY, Common.FTS_MQ_UserId); properties.Add(MQC.PASSWORD_PROPERTY, Common.FTS_MQ_Password); properties.Add(MQC.USE_MQCSP_AUTHENTICATION_PROPERTY, true); MQConnectionPool.Initialize(properties); } objMQQueueManager = MQConnectionPool.GetQueueManager(); }
3. 检查MQ服务器配置
- 执行
DISPLAY CHANNEL(xxx) MAXINST命令查看通道的最大实例数,适当调整MAXINST和MAXINSTC参数,允许更多并发连接 - 查看MQ服务器的认证日志,确认失败请求的具体错误码(如2035表示认证失败、2009表示连接中断),针对性处理
4. 升级MQ客户端版本
部分旧版本的IBM MQ .NET客户端在多线程认证场景下存在bug,升级到9.3及以上版本可解决这类问题
内容的提问来源于stack exchange,提问作者Pradeep Kumar
相关产品推荐
相关产品推荐

