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
- 我正在连接到 MQ 服务器版本 9.0.0.5
- 我正在使用控制台应用程序 .Net Framework 4.6.1
- 我本地机器安装的MQ客户端是9.1.0.1
我看到一个非常奇怪的行为。应用程序 运行 正常并且能够接收消息。但它会在整整 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
下载
给出一些关于事情应该如何运作的背景:
- MQ 客户端应用程序在连接到队列管理器时将协商心跳间隔 (
HBINT
),这是一个以秒为单位的值。协商的 HBINT
始终是 SVRCONN
和客户端应用程序之间协商的最高值。
注意: A SVRCONN
HBINT
的默认值为 300
。
- 基于
HBINT
,超时是通过以下两种方式之一计算的:
- 如果协商的
HBINT
小于 60,则超时为 2x HBINT
。 (在 HBINT 过去后接收到的超时是 HBINT 秒)
- 如果协商的
HBINT
大于或等于 60,则超时为 HBINT
+ 60。(接收超时为 HBINT 传递后的 60 秒)。
- 如果在
HBINT
时间内未从队列管理器接收到正常流量,则客户端应向队列管理器发送心跳信号,队列管理器应作出响应。客户端应等待接收超时时间以接收心跳。
- 队列管理器也可以向客户端发起心跳,但为了防止额外的流量,队列管理器在向客户端发送心跳之前比协商的
HBINT
多等待五秒。
APAR IT26614 更正了以下三个问题:
在非托管或托管模式下,如果您不使用 CCDT,则 HBINT
将使用 SVRCONN
通道的值。实际上,如果不使用 CCDT,客户端的 HBINT
默认为 300
,因此这是您将看到的最低 HBINT
。
特定于 Managed .NET 客户端 HBINT
不能低于 SVRCONN
HBINT
连接将失败并显示 2059。此问题影响两者有或没有 CCDT。
- 使用 CCDT,您无法将
CLNTCONN
HBINT
设置为小于 SVRCONN
HBINT
的值
- 没有 CCDT 如果
SVRCONN
HBINT
设置为 301
或更高,您将受到影响
特定于托管 .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 这是我怀疑正在发生的事情:
- 无论 SVRCONN HBINT 的设置如何,HBINT 都协商为 300 秒。
- 托管 XMS.NET 客户端将在 300 秒内未从队列管理器接收到任何内容后向队列管理器发送心跳信号。
- 此时托管 XMS.NET 客户端将仅等待 60 毫秒以等待队列管理器的响应。
- 如果托管 XMS.NET 客户端在 60 毫秒内未收到响应,它将 return 向应用程序发送 2009 错误。
- 队列管理器错误日志将显示 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
秒,如果连接丢失。重新连接不适用于与队列管理器的初始连接,它仅在您连接后适用。
我正在使用 IBM 的这个示例。我刚刚复制并粘贴了代码:
https://github.com/ibm-messaging/mq-dev-patterns/blob/master/dotnet/dotNetGet.cs
- 我正在连接到 MQ 服务器版本 9.0.0.5
- 我正在使用控制台应用程序 .Net Framework 4.6.1
- 我本地机器安装的MQ客户端是9.1.0.1
我看到一个非常奇怪的行为。应用程序 运行 正常并且能够接收消息。但它会在整整 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
下载给出一些关于事情应该如何运作的背景:
- MQ 客户端应用程序在连接到队列管理器时将协商心跳间隔 (
HBINT
),这是一个以秒为单位的值。协商的HBINT
始终是SVRCONN
和客户端应用程序之间协商的最高值。
注意: ASVRCONN
HBINT
的默认值为300
。 - 基于
HBINT
,超时是通过以下两种方式之一计算的:- 如果协商的
HBINT
小于 60,则超时为 2xHBINT
。 (在 HBINT 过去后接收到的超时是 HBINT 秒) - 如果协商的
HBINT
大于或等于 60,则超时为HBINT
+ 60。(接收超时为 HBINT 传递后的 60 秒)。
- 如果协商的
- 如果在
HBINT
时间内未从队列管理器接收到正常流量,则客户端应向队列管理器发送心跳信号,队列管理器应作出响应。客户端应等待接收超时时间以接收心跳。 - 队列管理器也可以向客户端发起心跳,但为了防止额外的流量,队列管理器在向客户端发送心跳之前比协商的
HBINT
多等待五秒。
APAR IT26614 更正了以下三个问题:
在非托管或托管模式下,如果您不使用 CCDT,则
HBINT
将使用SVRCONN
通道的值。实际上,如果不使用 CCDT,客户端的HBINT
默认为300
,因此这是您将看到的最低HBINT
。特定于 Managed .NET 客户端
HBINT
不能低于SVRCONN
HBINT
连接将失败并显示 2059。此问题影响两者有或没有 CCDT。- 使用 CCDT,您无法将
CLNTCONN
HBINT
设置为小于SVRCONN
HBINT
的值
- 没有 CCDT 如果
SVRCONN
HBINT
设置为301
或更高,您将受到影响
- 使用 CCDT,您无法将
特定于托管 .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 这是我怀疑正在发生的事情:
- 无论 SVRCONN HBINT 的设置如何,HBINT 都协商为 300 秒。
- 托管 XMS.NET 客户端将在 300 秒内未从队列管理器接收到任何内容后向队列管理器发送心跳信号。
- 此时托管 XMS.NET 客户端将仅等待 60 毫秒以等待队列管理器的响应。
- 如果托管 XMS.NET 客户端在 60 毫秒内未收到响应,它将 return 向应用程序发送 2009 错误。
- 队列管理器错误日志将显示 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
秒,如果连接丢失。重新连接不适用于与队列管理器的初始连接,它仅在您连接后适用。