IBM MQ 客户端在 10 分钟后断开连接:IBM.XMS.IllegalStateException

IBM MQ Client disconnect after 10 minutes: 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 分钟后重新连接?

您描述的症状似乎与 APAR IT26614: MQ dotnet (.NET) client channel ends abnormally when the heartbeat (HBINT) is reached

匹配
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 Clients or MQC91: IBM MQ Clients

下载

给出一些关于事情应该如何运作的背景:

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

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

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

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

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


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

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

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

我建议您试用 9.0.0.7 或 9.1.0.3 Managed XMS.NET 客户端,看看它是否能解决您的问题,因为在这些版本中,它会等待整整 60 秒才能收到 Heart Beat 响应来自队列管理器。


如果您想将重新连接添加到示例中,如果不使用包含 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 秒,如果连接丢失。重新连接不适用于与队列管理器的初始连接,它仅在您连接后适用。