NetTcpBinding(WCF)中的ReliableSession发生意外故障

时间:2019-01-11 08:04:42

标签: c# wcf fault reliablesession

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

  • .Net Framework 4.6.1
  • 启用了超线程的Quad Core i7计算机
  • 服务器CPU负载在20%至70%之间
  • 网络负载<5%(GBit NIC)
  • 100个用户
  • 正在运行30个服务(一些管理性服务,每种数据类型一些通用性服务),并且每个用户都已连接到所有服务
  • NetTcpBinding(启用压缩)
  • 已启用ReliableSession
  • 我确实每秒触发一次(服务器端)更新通知,并且所有客户端均从服务器加载约。 100 kB
  • 另外,心跳正在运行(用于测试15秒间隔),该心跳仅以UTC返回服务器时间

有时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)

我确实对设置进行了调整,但情况似乎有所缓解-现在故障更少的客户。我的设置:

  • ReliableSession.InactivityTimeout:01:30:00
  • ReliableSession.Enabled:是
  • ReliableSession.Ordered:错误
  • ReliableSession.FlowControlEnabled:错误
  • ReliableSession.MaxTransferWindowSize:4096
  • ReliableSession.MaxPendingChannels:16384
  • MaxReceivedMessageSize:1073741824
  • ReaderQuotas.MaxStringContentLength:8388608
  • ReaderQuotas.MaxArrayLength:1073741824

我被困住了。为什么所有呼叫都尝试等待WaitQueue中的某个TransmissionStrategy?我不在乎邮件是否乱码发送(我自己会照顾的)。我已经在考虑禁用可靠的消息传递,但是该应用程序已在全球的公司网络中使用。我需要知道我的邮件已经发送。

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

编辑

服务限制的值设置为Int32.MaxValue

我也曾尝试将MaxConnections上的ListenBackLogNetTcpBinding设置为最大值。据我所知,它并没有改变任何东西。

编辑2

检查WCF跟踪会告诉我(德语消息,因此为粗略翻译),可靠消息传递窗口中没有可用空间-然后我得到的都是超时,因为没有更多消息被发送。

那里发生了什么?可靠的消息传递有可能使自己困惑吗?

3 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:1)

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

您的MaxPendingChannels设置为16384,这会使太多的客户端在队列中等待,如果服务器无法及时处理客户端,则通道可能会变为故障状态。

FlowControlEnabled表示当服务器没有剩余空间来保存消息时是否继续向服务器端发送消息。您最好将其设置为true。

InactivityTimeout表示在一定时间内没有消息交换时是否关闭会话。您最好将其设置为合适的值。

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

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

答案 2 :(得分:1)

长话短说:

事实证明,我的WCF设置还可以。

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

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

有趣的细节:在交通繁忙的情况下,这甚至降低了CPU负载。从30%到80%的疯狂涨幅到30%左右的(几乎)稳定值。我只能假定这是由于线程池线程的生成和清理。

编辑

我做了以下事情:

ThreadPool.SetMinThreads(1000, 500)

该值可能类似于使用大锤开裂螺母-但它可以工作。