首页 > 解决方案 > IBM MQ 客户端在 10 分钟后断开连接:IBM.XMS.IllegalStateException

问题描述

我正在使用 IBM 的这个示例。我刚刚复制并粘贴了代码:

https://github.com/ibm-messaging/mq-dev-patterns/blob/master/dotnet/dotNetGet.cs

我可以看到一个非常奇怪的行为。应用程序正常运行并且能够获取消息。但它会在整整 10 分钟后断开连接。总是 10 分钟。

这是捕获的错误:

IBM.XMS.IllegalStateException: Failed to get a message from destination MY_QUEUE.
IBM MQ classes for XMS attempted to perform an MQGET; however IBM MQ reported an error.
Use the linked exception to determine the cause of this error.
   at IBM.XMS.Client.Impl.XmsMessageConsumerImpl.ReceiveInboundMessage(Int64 timeout)
   at IBM.XMS.Client.Impl.XmsMessageConsumerImpl.Receive(Int64 millis)
   at Mq_Get_Tests.SimpleConsumer.ReceiveMessages() in C:\Users\osotorrio\Projects\Temporal\Mq_Get_Tests\Mq_Get_Tests\SimpleConsumer.cs:line 137
Linked Exception : CompCode: 2, Reason: 2009*

IBM 示例是否缺少一些配置设置以允许客户端在 10 分钟不活动后重新连接?

标签: .netibm-mq

解决方案


您描述的症状似乎与 APAR IT26614 匹配:达到心跳 (HBINT) 时 MQ dotnet (.NET) 客户端通道异常结束

The fix is targeted for delivery in the following PTFs:

Version    Maintenance Level
v8.0       8.0.0.13
v9.0 LTS   9.0.0.7
v9.1 CD    9.1.3
v9.1 LTS   9.1.0.3

截至 2019 年 8 月 7 日,9.0.0.7 和 9.1.0.3 已发布,可从MQC9:IBM MQ V9 客户端MQC91:IBM MQ 客户端下载


提供一些关于事情应该如何工作的背景:

  1. MQ 客户端应用程序在连接到队列管理器时将协商心跳间隔 ( HBINT),这是一个以秒为单位的值。协商HBINT的始终是SVRCONN客户端应用程序和客户端应用程序之间协商的最高值。
    注意: ASVRCONN HBINT的默认值为300
  2. 基于HBINT, TIMEOUT 以两种方式之一计算:
    1. 如果协商HBINT小于 60,则 TIMEOUT 为 2x HBINT。(收到的超时时间是 HBINT 过去后的 HBINT 秒)
    2. 如果协商HBINT大于或等于 60,则 TIMEOUT 为HBINT+ 60。(接收超时为 HBINT 过去后的 60 秒)。
  3. 如果在一段时间内没有从队列管理器接收到正常流量,HBINT则客户端应该向应该响应的队列管理器发送心跳。客户端应等待接收超时时间量以接收心跳。
  4. 队列管理器也可以向客户端发起心跳,但为了防止额外的流量,队列管理器HBINT在向客户端发送心跳之前等待比协商的多 5 秒。

APAR IT26614 更正了以下三个问题:

  1. 在非托管或托管模式下,记录表明,如果您不使用 CCDT,HBINT则将使用SVRCONN通道的值。实际上,如果不使用 CCDT HBINT,则客户端默认为,因此这是您将看到300的最低值。HBINT

  2. 特定于托管 .NET,客户端HBINT不能低于SVRCONN HBINT连接将失败并显示 2059。此问题影响有或没有 CCDT。

    • 使用 CCDT,您无法将 设置为CLNTCONN HBINT小于SVRCONN HBINT
    • SVRCONN HBINT如果没有 CCDT,如果设置为301或更高 ,您将受到影响
  3. 特定于托管 .NET,客户端接收超时以毫秒而不是秒计算。在这种情况下,根据 IBM 的说法,该缺陷已存在很长时间,但直到 APAR IT16167 才出现:托管 .NET 客户端应用程序不向队列管理器发送心跳请求是在 8.0.0.10 和 9.0.0.4 中引入的(IBM还确认这存在于 GA 9.1.0.0 中)。以前不是问题的原因是托管 .NET 从未启动心跳,队列管理器总是会在 HBINT + 5 秒时发送心跳,并且 .NET 客户端会响应。一旦这被纠正,接收超时的错误计算就会出现。


基于托管 XMS.NET 客户端版本 9.1.0.1,这是我怀疑正在发生的事情:

  1. 无论 SVRCONN HBINT 设置了什么,HBINT 都被协商为 300 秒。
  2. 托管 XMS.NET 客户端将在 300 秒内未收到来自队列管理器的任何内容后向队列管理器发送心跳。
  3. 此时,托管 XMS.NET 客户端将仅等待 60 毫秒以等待来自队列管理器的响应。
  4. 如果托管 XMS.NET 客户端在 60 毫秒内未收到响应,它将向应用程序返回 2009 错误。
  5. 队列管理器错误日志将显示 AMQ9209,并显示“通过 TCP/IP 从 'dnsname (xx.xx.xx.xx) 接收数据时出错。

您提到仅在 10 分钟(600 秒)时看到它,但根据网络的延迟,我以任何 300 秒的间隔看到它。如果您要连接到同一服务器或同一本地网段中的队列管理器,您可能永远不会看到此问题。如果您通过高延迟 WAN 电路进行连接,则可能每 300 秒就会遇到一次。如果您通过接近 30 毫秒的网段连接,您可能会间歇性地看到它。

我建议您试用 9.0.0.7 或 9.1.0.3 Managed XMS.NET 客户端,看看它是否为您解决了问题,因为在这些版本中,它将等待队列管理器的心跳响应整整 60 秒。


如果您想在不使用包含 APAR IT26614 的 MQ 版本的情况下将重新连接添加到将掩盖问题的示例,您可以使用以下设置:

cf.SetIntProperty(XMSC.WMQ_CLIENT_RECONNECT_OPTIONS, XMSC.WMQ_CLIENT_RECONNECT);
cf.SetIntProperty(XMSC.WMQ_CLIENT_RECONNECT_TIMEOUT, XMSC.WMQ_CLIENT_RECONNECT_TIMEOUT_DEFAULT);
//Note that XMSC.WMQ_CLIENT_RECONNECT_TIMEOUT_DEFAULT is 1800

请注意,即使您使用带有 APAR IT26614 的 MQ 版本,上述做法也是一个很好的做法,因为它会告诉托管 XMS.NET 客户端XMSC.WMQ_CLIENT_RECONNECT_TIMEOUT在连接丢失时自动尝试重新连接到队列管理器几秒钟。重新连接不适用于与队列管理器的初始连接,它仅在您连接后适用。


推荐阅读