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