我有一个 Windows 服务托管一个高级 WCF 服务,该服务通过 TCP(netTCP) 与 protobuf.net 通信,有时还与证书通信。
receiveTimeout 设置为无限,永远不会因不活动而断开连接。但据我所知,无论如何连接都可能被断开,所以我创建了一个简单的双向 keepalive 服务方法,客户端每 9 分钟调用一次以保持连接有效。连接永不中断非常重要。
这是正确的方法吗?或者我是否可以因为 receiveTimout 设置为无限而简单地删除我的 keep live?
编辑:WCF 服务的当前 app.config:http://1drv.ms/1uEVKIt
最佳答案
没有。这被广泛误解,不幸的是,那里有很多错误信息。
首先,“无限”是一种半有效值。有两个特殊的配置序列化程序可以将“Infinite”转换为 TimeSpan.MaxValue
。或 int.MaxValue
(所以无论如何它们都不是真正的“无限”),但并不是 WCF 中的所有内容似乎都认识到这一点。所以最好用时间值明确指定超时。
其次,您的服务中不需要“keepalive”方法,因为 WCF 提供了所谓的“可靠 session ”。如果添加 <reliableSession enabled="true" />
然后 WCF 将通过“基础结构消息”提供它自己的保持事件机制。
通过拥有自己的“keepalive”机制,您可以有效地将服务负载加倍,而且实际上制造的问题多于解决的问题。
第三,在使用可靠 session 时,您使用 inactivityTimeout
reliableSession
的设置.这有两件事。首先,它控制发送基础设施(保持事件)消息的频率。它们以超时值的一半发送,因此如果您将其设置为 18 分钟,那么它们将每 9 分钟发送一次。其次,如果在不活动超时内没有收到基础设施或操作消息(即作为数据契约(Contract)的一部分的消息),则连接将中止,因为可能存在问题(一侧已崩溃,存在网络问题等)。 .).
receiveTimeout
是连接中止之前无法接收到任何操作消息的最长时间(默认为 10 分钟)。将其设置为较大的值(Int32.MaxValue
接近 24 天)保持连接稳定,将 inactivityTimeout 设置为较小的值(同样,默认值为 10 分钟)(小于 2x 的时间网络路由器因不活动而断开连接之前的最长时间)保持连接有效。
WCF 为您处理所有这一切。然后,您可以简单地订阅“连接中止”消息,以了解连接何时因真正原因(应用程序崩溃、网络超时、客户端断电等)而断开,并允许您重新创建连接。
此外,如果您不需要有序消息,请设置 ordered="false"
,因为这大大减少了可靠 session 的开销。默认为真。
注意:在 inactivityTimeout 过期(或您尝试使用连接)之前,您可能不会收到连接中止事件。请注意这一点,并相应地设置超时。
互联网上的大多数建议都是将 receiveTimeout 和 inactivityTimeout 都设置为 Infinite。这有两个问题,第一个基础设施消息没有及时发送,所以路由器会断开连接……迫使你做自己的保活。其次,长时间的不活动超时意味着它无法识别连接何时合法断开,您必须依靠 ping 中止来了解何时发生故障。这完全没有必要,实际上甚至会使您的服务更加不可靠。
另见:How do I correctly configure a WCF NetTcp Duplex Reliable Session?
关于c# - KeepAlive 与 WCF 和 TCP?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26732515/