接收超时(receiveTimeout)被设置为无限以防止由于不活动而断开连接。但据我所知,连接仍可能被断开,因此我创建了一个简单的双向保持活动服务方法,客户端每9分钟调用一次以保持连接处于活动状态。连接永远不能断开非常重要。
这是正确的方式吗?或者可以简单地删除我的保持活动,因为接收超时(receiveTimeout)已设置为无限?
编辑: WCF服务的当前app.config: http://1drv.ms/1uEVKIt
不是的。这个被广泛误解了,不幸的是有很多错误信息在外面。
首先,“无限”是一种半有效的值。有两个特殊配置序列化程序将“无限”转换为TimeSpan.MaxValue
或int.MaxValue
(所以它们实际上并不是“无限”的),但是WCF中的并不是所有内容都能够识别它。因此最好使用时间值明确指定超时。
其次,在您的服务中不需要“保持活动”的方法,因为WCF提供了所谓的“可靠会话”。如果添加 <reliableSession enabled="true" />
,那么WCF将通过“基础结构消息”提供自己的保持活动机制。
通过拥有您自己的“保持活动”机制,您实际上会使您的服务负载加倍,并且可能会创建更多问题而不是解决问题。
第三,当使用可靠会话时,您使用reliableSession
的inactivityTimeout
设置。这做两件事情。首先,它控制基础设施(保持活动)消息发送的频率。它们在timeout值的一半处发送,所以如果您将其设置为18分钟,则它们将每9分钟发送一次。其次,如果没有接收到基础设施或操作消息(即作为您数据契约的一部分的消息)在不活动超时期内收到,则连接将被中止,因为可能存在问题(一方已崩溃,存在网络问题等)。
receiveTimeout
是在连接中无法接收任何操作消息之前的最长时间(默认值为10分钟),在这之后会中止连接。将其设置为大值(Int32.MaxValue
某处大约为24天)可以保持连接,将inactivityTimeout设置为较小值(再次,默认值为10分钟)(小于网络路由器在不活动情况下断开连接的最长时间的2倍时间),可以保持连接的活性。
WCF会为您处理所有这些内容。您可以订阅连接中止消息,以知道何时出现真正的连接断开(应用程序崩溃、网络超时、客户端断电等),并允许您重新创建连接。
此外,如果您不需要有序消息,请设置 ordered="false"
,因为这会大大减少可靠会话的开销。默认值为true。
注意:在未活动时间过长(或尝试使用连接)之前,可能不会收到连接中止事件。请注意此问题,并相应地设置超时时间。
互联网上的大多数建议是将receiveTimeout和inactivityTimeout都设置为Infinite。这有两个问题,首先基础设施消息无法及时发送,因此路由器将放弃连接...迫使您进行自己的保持活动操作。其次,大的不活动超时意味着它无法识别连接合法地断开,而您必须依赖于ping终止来知道故障发生的情况。这完全是不必要的,并且实际上甚至可能使您的服务更加不可靠。
24.20:31:23.6470000
。这是Int32.MaxValue,表示最大的毫秒数,如果你计算(2^31) / 1000 / 60 / 60 / 24 = 上面的数字。 - Erik Funkenbusch