NetTcpBinding (WCF) 中 ReliableSession 的意外错误

Unexpected fault on ReliableSession in NetTcpBinding (WCF)

我有一个客户端服务器应用程序。我的场景:

有时 WCF 连接会更改为故障状态。通常发生这种情况时,服务器根本没有网络上游。我确实写了一个内存转储,并且能够看到很多 WCF 线程正在等待一些 WaitQueue。调用堆栈是:

Server stack trace: 
   at System.ServiceModel.Channels.TransmissionStrategy.WaitQueueAdder.Wait(TimeSpan timeout)
   at System.ServiceModel.Channels.TransmissionStrategy.InternalAdd(Message message, Boolean isLast, TimeSpan timeout, Object state, MessageAttemptInfo& attemptInfo)
   at System.ServiceModel.Channels.ReliableOutputConnection.InternalAddMessage(Message message, TimeSpan timeout, Object state, Boolean isLast)
   at System.ServiceModel.Channels.ReliableDuplexSessionChannel.OnSend(Message message, TimeSpan timeout)
   at System.ServiceModel.Channels.DuplexChannel.Send(Message message, TimeSpan timeout)
   at System.ServiceModel.Dispatcher.DuplexChannelBinder.Send(Message message, TimeSpan timeout)
   at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
   at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
   at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)

我确实调整了设置,情况似乎有所缓解 - 现在出现故障的客户端减少了。我的设置:

我卡住了。为什么所有调用都尝试等待 TransmissionStrategy 中的某些 WaitQueue?我不关心消息被乱序发送(我自己会处理)。我已经在考虑禁用可靠的消息传递,但该应用程序在全球范围内的公司网络中使用。我需要知道我的消息是否已送达。

有什么想法可以教 WCF 只发送消息而不关心其他任何事情吗?

编辑

服务节流的值设置为Int32.MaxValue

我也曾尝试将 MaxConnectionsListenBackLog(在 NetTcpBinding 上)设置为最大值。它没有改变任何东西——据我所知。

编辑 2

检查 WCF Traces 它告诉我(德语消息,因此是一个粗略的翻译)在可靠的消息传输 window 中没有可用的 space - 然后我得到的只是超时,因为不再发送消息。

那里发生了什么事?可靠的消息传递是否可能混淆了自己?

等待队列可能与 wcf 内置的节流行为有关 https://docs.microsoft.com/en-us/dotnet/framework/configure-apps/file-schema/wcf/servicethrottling 排除故障的最佳方法是启用 wcf 跟踪 https://docs.microsoft.com/en-us/dotnet/framework/configure-apps/file-schema/wcf/servicethrottling 并确切知道根本原因是什么

您是否使用 connectionManagement 来设置客户端的最大连接数?(如果您的会话是双工的) https://docs.microsoft.com/en-us/dotnet/framework/configure-apps/file-schema/network/connectionmanagement-element-network-settings

你的MaxPendingChannels设置为16384,这会导致过多的客户端在队列中等待,如果服务器不能及时处理客户端,通道可能会进入故障状态。

FlowControlEnabled表示当服务器没有space保存消息时是否继续向服务器端发送消息。你最好设置为真。

InactivityTimeout表示在一定时间内没有消息交互时是否关闭session。你最好设置一个合适的值。

此外,您是否设置了绑定的超时时间?

  <netTcpBinding>
    <binding  closeTimeout="" openTimeout="" receiveTimeout="" sendTimeout="" ></binding>
  </netTcpBinding>

长话短说:

原来我的WCF设置没问题

ThreadPool 是限制因素。在高流量(因此高负载)的情况下,我确实会生成很多必须发送给客户端的消息。由于没有足够的工作线程来发送消息,因此它们会排队。在某个时候队列已满 - 而你就在那里。

有关更多详细信息,请查看来自 Russ Bishop 的 question & answer

有趣的细节:这甚至在高流量情况下减少了 CPU 负载。从 30% 到 80% 之间的疯狂飙升到 30% 左右的(n)(几乎)稳定值。我只能假设这是因为线程池线程生成和清理。

编辑

我做了以下事情:

ThreadPool.SetMinThreads(1000, 500)

该值可能就像使用大锤敲螺母一样 - 但它确实有效。