提问人:Banshee 提问时间:11/4/2014 最后编辑:Banshee 更新时间:5/17/2018 访问量:17992
使用 WCF 和 TCP 保持活动状态?
KeepAlive with WCF and TCP?
问:
我有一个 Windows 服务托管一个高级 WCF 服务,该服务通过 TCP(netTCP) 与 protobuf.net 通信,有时也与证书通信。
receiveTimeout 设置为 infinite,以永远不会因非活动状态而断开连接。但据我了解,无论如何连接都可能被断开,所以我创建了一个简单的双向 keepalive 服务方法,客户端每 9 分钟调用一次以保持连接处于活动状态。连接永不中断非常重要。
这是正确的方法吗?或者我可以简单地删除我的 keep live,因为 receiveTimout 设置为无限?
编辑:WCF 服务的当前 app.config:http://1drv.ms/1uEVKIt
答:
不。这被广泛误解了,不幸的是,那里有很多错误的信息。
首先,“无限”是一种半有效值。有两个特殊的配置序列化程序将“Infinite”转换为 or (所以它们无论如何都不是真正的“无限”),但并不是 WCF 中的所有内容都能识别这一点。因此,最好始终使用时间值显式指定超时。TimeSpan.MaxValue
int.MaxValue
其次,您的服务中不需要“keepalive”方法,因为 WCF 提供了所谓的“可靠会话”。如果添加,则 WCF 将通过“基础结构消息”提供它自己的保持活动机制。<reliableSession enabled="true" />
通过拥有自己的“keepalive”机制,您实际上将服务的负载增加了一倍,并且您实际上可以产生比它解决的问题更多的问题。
第三,在使用可靠会话时,使用 .这做了两件事。首先,它控制基础结构 (keepalive) 消息的发送频率。它们以超时值的一半发送,因此如果将其设置为 18 分钟,则它们将每 9 分钟发送一次。其次,如果在非活动超时期间未收到任何基础结构或操作消息(即数据协定中的消息),则连接将中止,因为可能存在问题(一侧崩溃、网络问题等)。inactivityTimeout
reliableSession
receiveTimeout
是连接中止之前无法接收任何操作消息的最长时间(默认值为 10 分钟)。将此值设置为较大的值(在 24 天附近的某个位置)可保持连接正常,将 inactivityTimeout 设置为较小的值(同样,默认值为 10 分钟)(小于网络路由器从非活动状态断开连接之前最大时间的 2 倍的时间)可保持连接处于活动状态。Int32.MaxValue
WCF 将为您处理所有这些问题。然后,只需订阅“连接已中止”消息,即可了解连接何时因实际原因(应用程序崩溃、网络超时、客户端断电等)而断开,并允许您重新创建连接。
此外,如果您不需要有序消息,请设置 ,因为这大大减少了可靠会话的开销。默认值为 true。ordered="false"
注意:在 inactivityTimeout 过期(或尝试使用连接)之前,您可能不会收到连接中止事件。请注意这一点,并相应地设置超时。
Internet 上的大多数建议是将 receiveTimeout 和 inactivityTimeout 都设置为 Infinite。这有两个问题,首先基础设施消息没有及时发送,因此路由器会断开连接......强迫你自己做 keepalives。其次,较大的非活动超时意味着它无法识别连接何时合法断开,您必须依靠该 ping 中止来了解何时发生故障。这一切都是完全不必要的,实际上甚至会使您的服务更加不可靠。
另请参阅:如何正确配置 WCF NetTcp 双工可靠会话?
评论