如何正确配置WCF NetTcp双工可靠会话?

Eri*_*sch 13 configuration wcf duplex-channel

请原谅明显的自我问答,但这些信息被广泛误解,几乎总是被错误地回答.所以我想把这些信息放在这里,以便人们寻找这个问题的明确答案.

即便如此,仍然有一些我无法确定的信息.我将把这一点放在问题的最后(如果你对序言不感兴趣的话,请跳过这一点).

如何正确配置WCF NetTcp双工可靠会话?

关于此主题有许多问题和答案,几乎所有问题和答案都建议inactivityTimeout="Infinite"您在配置中进行设置.这似乎并没有真正起作用,特别是对于NetTcp的情况(它可能适用于WSDualHttp Bindings,但我从未使用过它们).

还有许多其他问题通常与此相关:包括,客户端或服务器意外断开后频道无故障,10分钟后频道断开连接,频道随机断开...尝试打开时频道抛出异常...无法在同一端点上配置元数据......

通过艰难的试验和错误我已经想出的信息.

  • Infinite 在所有情况下似乎都不是有效的配置设置(当然,Visual Studio验证模式不知道它).
  • 有两个特殊的配置转换器被调用InfiniteIntConverter,InfiniteTimeSpanConverter它们有时可以将值转换InfiniteInt.MaxValue或者TimeSpan.MaxValue,但我还没有弄清楚它看起来有效的情况,因为它有时会起作用,有时却没有.更重要的是,似乎某些库将允许Infinite在配置中,而其他库则不允许,因此您可以在配置的一部分中成功,但在另一部分中失败.
  • 您必须在客户端和服务器上配置BOTH inactivityTimeoutreceiveTimeout.虽然这些值不必相同,但它们可能应该是因为它们可能会导致混淆,如果不是这样的话.(从技术上讲,inactivityTimeout如果你愿意,你可以保留其默认值,但你应该知道它的价值,以及它的作用)
  • inactivityTimeout应该从来没有被设置为一个较大的值,更InfinteTimeSpan.MaxValue.
  • inactivityTimeout有两个功能(这并没有被广泛理解).第一个函数定义了在没有接收任何"基础结构"或"操作"消息的情况下可以在通道上经过的最大时间量.第二个函数定义发送基础结构消息的时间段(指定时间的一半).如果在超时期间未收到任何基础结构或操作消息,则中止连接.
  • receiveTimeout种类只能在操作消息之间​​经过的最长时间.此值可以设置为较大的值,例如TimeSpan.MaxValue(特别是如果您的通道在可信网络上或通过vpn在内部运行).如果客户端和服务器之间没有活动(基础结构消息除外),则此值定义可靠会话将"保持活动"的时间长度.即,您的客户端不会调用该接口的任何方法,并且您的服务器不会回调客户端.
  • 即使客户端和服务器之间没有操作活动,设置短inactivityTimeout和大也receiveTimeout可以使您的可靠会话"加强".短暂的不活动超时(我希望保持默认的10分钟或更短时间)发送基础设施"ping"消息以保持TCP连接活动,而长接收超时使可靠会话保持活动状态.同时在断开连接时提供合理的超时.
  • 如果设置inactivityTimeout为较大的值,则可靠会话将不可靠,因为它无法使Tcp连接保持活动状态,也无法验证连接的完整性.在尝试向该客户端发送消息并发现连接不再存在之前,它不会知道用户是否意外断开连接.这就是为什么许多使用Infinite进行此设置的人会在他们的服务中创建一个"Ping"方法,如果您正确配置了这些设置,这是完全没必要的.
  • 如果设置inactivityTimeout为大receiveTimeout于此值的值,它同样也将不可靠,因为您仍将受到receiveTimeoutfor操作消息的约束.即.如果您忘记设置receiveTimeout并保留默认的10分钟,那么如果用户空闲10分钟,则连接将中止.
  • 当客户端或服务器意外断开连接(应用程序崩溃,网络故障,有人绊倒电源线等)时,另一方可能不会立即注意到.我已经ChannelFaulted在各种测试情况下附加了各种事件处理程序,有时连接会立即出现故障......有时它似乎根本没有故障.我通过反复试验发现的是,当它似乎没有出现故障时,它会在inactivityTimeout到期后失效.(如果它设置为10分钟,那么10分钟后它将调用该ChannelFaulted事件).
  • 我还没有弄清楚为什么在某些情况下它立即注意到断开连接,而其他人等待计时器到期.在这两种情况下,我都注意到框架抛出并处理内部第一次机会通信异常,并且调用Abort连接......但不知何故,对事件处理程序的调用会丢失并且必须等待超时.我的怀疑是这与线程有关.
  • 当尝试将元数据配置为在NetTcp通道上工作时,我得到了零星的结果.有时候它有效,有时则不然.我已经阅读了很多关于元数据不能通过NetTcp工作的报告,并且你必须使用Http通道作为元数据,但实际上我已经在几次使用net.tcp:// url来生成代理.然后我会改变一些东西,重新编译,它将不再起作用.改变一切,它不会再起作用了.因此,使用net.tcp进行元数据功能所需的魔术咒语是非常混乱的,与同一端口上的端点共享(显然具有不同的地址).
  • 在同一服务上配置NetTcp和Metatdata端点,并为listenBacklog和maxConnections等连接参数指定非默认设置时,还需要确保元数据端点使用相同的设置,这通常意味着您必须定义自定义绑定,因为标准tcp mex绑定不提供这些设置.这包括设置listenBacklogmaxPendingConnectionstcpTransport,并groupNamemaxOutboundConnectionsPerEndpointconnectionPoolSettings.
  • ReliableSession的Ordered设置的默认设置是True.这比使其关闭使用更多的开销.如果您不需要订购消息,我建议将其关闭(需要在两侧设置)
  • -

配置我还需要了解:

如何正确配置共享net.tcp元数据端点?(我将在有机会时添加一个示例)目前,我正在指定一个http get url来绕过这个问题.这有点不协调,为什么它有时会起作用,有时却不起作用.在Visual Studio中生成代理时,我不断收到错误"无法识别URI前缀".

为什么WCF有时会在断开连接后立即对通道进行故障,有时会等待inactivityTimeout到期?什么控制/导致一个与另一个行为?