.net - IBM MQ 客户端在 10 分钟后断开连接: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 匹配:达到心跳 (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 客户端下载
提供一些关于事情应该如何工作的背景:
- MQ 客户端应用程序在连接到队列管理器时将协商心跳间隔 (
HBINT
),这是一个以秒为单位的值。协商HBINT
的始终是SVRCONN
客户端应用程序和客户端应用程序之间协商的最高值。
注意: ASVRCONN
HBINT
的默认值为300
。 - 基于
HBINT
, TIMEOUT 以两种方式之一计算:- 如果协商
HBINT
小于 60,则 TIMEOUT 为 2xHBINT
。(收到的超时时间是 HBINT 过去后的 HBINT 秒) - 如果协商
HBINT
大于或等于 60,则 TIMEOUT 为HBINT
+ 60。(接收超时为 HBINT 过去后的 60 秒)。
- 如果协商
- 如果在一段时间内没有从队列管理器接收到正常流量,
HBINT
则客户端应该向应该响应的队列管理器发送心跳。客户端应等待接收超时时间量以接收心跳。 - 队列管理器也可以向客户端发起心跳,但为了防止额外的流量,队列管理器
HBINT
在向客户端发送心跳之前等待比协商的多 5 秒。
APAR IT26614 更正了以下三个问题:
在非托管或托管模式下,记录表明,如果您不使用 CCDT,
HBINT
则将使用SVRCONN
通道的值。实际上,如果不使用 CCDTHBINT
,则客户端默认为,因此这是您将看到300
的最低值。HBINT
特定于托管 .NET,客户端
HBINT
不能低于SVRCONN
HBINT
连接将失败并显示 2059。此问题影响有或没有 CCDT。- 使用 CCDT,您无法将 设置为
CLNTCONN
HBINT
小于SVRCONN
HBINT
SVRCONN
HBINT
如果没有 CCDT,如果设置为301
或更高 ,您将受到影响
- 使用 CCDT,您无法将 设置为
特定于托管 .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,这是我怀疑正在发生的事情:
- 无论 SVRCONN HBINT 设置了什么,HBINT 都被协商为 300 秒。
- 托管 XMS.NET 客户端将在 300 秒内未收到来自队列管理器的任何内容后向队列管理器发送心跳。
- 此时,托管 XMS.NET 客户端将仅等待 60 毫秒以等待来自队列管理器的响应。
- 如果托管 XMS.NET 客户端在 60 毫秒内未收到响应,它将向应用程序返回 2009 错误。
- 队列管理器错误日志将显示 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
在连接丢失时自动尝试重新连接到队列管理器几秒钟。重新连接不适用于与队列管理器的初始连接,它仅在您连接后适用。
推荐阅读
- r - tikzDevice 主标题,不带粗体
- linux - 如何使用linux内核和硬件加速绘制三角形?
- security - Apache Struts 2 远程代码执行(RCE)缺陷
- javascript - react 和 react native:uuid react 包是否支持移动设备?
- pyspark - 解码 hdfs 中的 tfrecords 文件错误:tensorflow/core/framework/op_kernel.cc:1192] 未找到:
- python - 如何创建一个可以像数组一样使用的 Python 类数组对象?
- three.js - 三转不能生效
- markdown - 如何在 GitHubPages 中安装/使用 Jekyll 插件?
- scala - 如何在 mapwithstate 或其他类中获取 sparkcontext
- apache-flink - 滑动时间窗口的 Flink 性能问题