MQ XMS.NET消息确认时出现MQCMIT失败异常求助
偶发MQCMIT失败异常排查与解决
问题详情
近2-4周,消息消费者在确认消息时偶发以下异常:
The method MQCMIT failed.
A IBM MQ call failed.
堆栈跟踪:
StackTrace = at IBM.XMS.Client.WMQ.WmqSession.Syncpoint(Boolean commit, Boolean fromOnMessage, String methodName) at IBM.XMS.Client.WMQ.WmqSession.Commit(Boolean fromOnMessage) at IBM.XMS.Client.Impl.XmsSessionImpl.CommitTransaction() at IBM.XMS.Client.Impl.XmsMessageImpl.Acknowledge()
消费者创建代码:
// Get an instance of factory. xmsFactoryIn = XMSFactoryFactory.GetInstance(XMSC.CT_WMQ); // Create WMQ Connection Factory. connectionFactoryIn = xmsFactoryIn.CreateConnectionFactory(); // Set the properties if (MQMode == (int)Location.Local) { LogMessage($"CreateConsumerIn: MQ Location=Local ", Tracing.LogCategory.Debug, Tracing.LogLevel.DebugLow, null); } else if (MQMode == (int)Location.Remote) { connectionFactoryIn.SetStringProperty(XMSC.WMQ_HOST_NAME, MQHostName); connectionFactoryIn.SetIntProperty(XMSC.WMQ_PORT, MQPort); connectionFactoryIn.SetStringProperty(XMSC.WMQ_CHANNEL, MQChannel); LogMessage($"CreateConsumerIn: MQ Location=Remote. MQHostName = {MQHostName} MQPort = {MQPort} MQChannel = {MQChannel} ", Tracing.LogCategory.Debug, Tracing.LogLevel.DebugLow, null); } connectionFactoryIn.SetIntProperty(XMSC.WMQ_CONNECTION_MODE, XMSC.WMQ_CM_CLIENT); connectionFactoryIn.SetStringProperty(XMSC.WMQ_QUEUE_MANAGER, MQManagerName); connectionFactoryIn.SetStringProperty(XMSC.WMQ_QUEUE_NAME, MQQueueNameIn); // In case of network issues - reconnect to same queue manager connectionFactoryIn.SetIntProperty(XMSC.WMQ_CLIENT_RECONNECT_OPTIONS, XMSC.WMQ_CLIENT_RECONNECT_Q_MGR); connectionFactoryIn.SetStringProperty(XMSC.WMQ_CONNECTION_NAME_LIST, String.Format("{0}({1})", MQHostName, MQPort)); connectionFactoryIn.SetIntProperty(XMSC.WMQ_CLIENT_RECONNECT_TIMEOUT, ReconnectInterval); // Create connection. connectionIn = connectionFactoryIn.CreateConnection(); LogMessage($"CreateConsumerIn: MQ Connection created - {this.Name}", Tracing.LogCategory.Debug, Tracing.LogLevel.DebugMedium, null); connectionIn.ExceptionListener = new ExceptionListener(OnExceptionIn); // Create session sessionIn = connectionIn.CreateSession(false, AcknowledgeMode.ClientAcknowledge); LogMessage($"CreateConsumerIn: MQ Session created - {this.Name}", Tracing.LogCategory.Debug, Tracing.LogLevel.DebugMedium, null); // Create destination destinationIn = sessionIn.CreateQueue(MQQueueNameIn); destinationIn.SetIntProperty(XMSC.WMQ_READ_AHEAD_ALLOWED, XMSC.WMQ_READ_AHEAD_ALLOWED_ENABLED); LogMessage($"CreateConsumerIn: MQ Destination created - {this.Name}", Tracing.LogCategory.Debug, Tracing.LogLevel.DebugMedium, null); // Create consumer messageConsumerIn = sessionIn.CreateConsumer(destinationIn); LogMessage($"CreateConsumerIn: MQ Consumer created - {this.Name}", Tracing.LogCategory.Debug, Tracing.LogLevel.DebugMedium, null); //Create message listener and assign it to the Message consumer messageListenerIn = new MessageListener(OnMessage); messageConsumerIn.MessageListener = messageListenerIn; connectionIn.Start();
可能原因
- 网络闪断与重连后的会话失效:虽然配置了客户端重连,但重连过程中原有会话(
sessionIn)已与队列管理器断开,此时调用Acknowledge()会触发会话事务提交,导致MQCMIT失败。 - 会话线程安全问题:XMS的
Session并非线程安全,如果消息处理逻辑中存在多线程操作会话,可能导致会话状态紊乱,引发提交失败。 - 队列管理器端异常:队列管理器出现资源不足、事务超时或内部错误时,会拒绝commit请求,返回MQCMIT失败。
- 消息确认时机不当:若在消息未完全处理完成前就调用
Acknowledge(),后续处理中连接异常会导致已触发的commit操作失败。
解决方案
1. 异常触发时重建会话与消费者
在OnExceptionIn异常监听器中,捕获连接/会话相关异常后,销毁当前的sessionIn、messageConsumerIn,重新创建会话和消费者:
private void OnExceptionIn(Exception ex) { LogMessage($"MQ Exception: {ex.Message}", Tracing.LogCategory.Error, Tracing.LogLevel.High, ex); // 销毁原有资源 messageConsumerIn?.Close(); sessionIn?.Close(); // 重新创建会话和消费者 sessionIn = connectionIn.CreateSession(false, AcknowledgeMode.ClientAcknowledge); destinationIn = sessionIn.CreateQueue(MQQueueNameIn); destinationIn.SetIntProperty(XMSC.WMQ_READ_AHEAD_ALLOWED, XMSC.WMQ_READ_AHEAD_ALLOWED_ENABLED); messageConsumerIn = sessionIn.CreateConsumer(destinationIn); messageConsumerIn.MessageListener = messageListenerIn; }
2. 确保会话的线程安全
XMS的Session、MessageConsumer均为线程绑定对象,禁止在多线程间共享。确保每个消费者的会话仅在自身消息处理线程中使用。
3. 检查队列管理器日志
查看MQ队列管理器的AMQERR01.LOG日志,定位具体错误码(如2009=连接中断、2059=队列管理器不可达),针对性解决网络或队列管理器配置问题。
4. 调整重连与事务配置
- 延长
WMQ_CLIENT_RECONNECT_TIMEOUT值,避免短时间内频繁重连导致的会话不稳定; - 若业务允许,可考虑将确认模式改为
AutoAcknowledge(自动在消息接收后确认),但需注意消息丢失风险; - 对于必须确保处理成功才确认的场景,在
Acknowledge()调用前后增加连接状态检查,或捕获异常后重试确认(需避免重复处理消息)。
5. 优化消息处理逻辑
确保在消息处理完全成功(如数据库操作完成、业务逻辑执行无异常)后再调用Acknowledge(),避免因后续操作失败导致的无效确认请求。
内容的提问来源于stack exchange,提问作者b_patil
相关产品推荐
相关产品推荐

