NetTcpBinding(WCF)中的ReliableSession出现意外错误



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

  • .Net框架4.6.1
  • 启用超线程的四核i7机器
  • 服务器CPU负载从20-70%
  • 网络负载<5%(GBit NIC)
  • 100个用户
  • 运行30个服务(有些是管理服务,有些是每个数据类型的通用服务),每个用户都连接到所有服务
  • NetTcpBinding(启用压缩)
  • 已启用ReliableSession
  • 每秒钟我都会触发(服务器端)一个更新通知,所有客户端从服务器加载大约100kB
  • 另外,一个心跳正在运行(用于测试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)

我确实调整了设置,似乎情况有所缓解——现在客户的失误减少了。我的设置:

  • 可靠会话。不活动超时:01:30:00
  • ReliableSession.Enabled:True
  • ReliableSession。有序:False
  • ReliableSession.FlowControlEnabled:False
  • ReliableSession.MaxTransferWindowSize:4096
  • ReliableSession.MaxPendingChannels:16384
  • 最大接收消息大小:1073741824
  • ReaderQuotas.MaxStringContentLength:838808
  • 读卡器配额最大排列长度:1073741824

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

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

编辑

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

我还尝试将MaxConnectionsListenBackLog(在NetTcpBinding上)设置为它们的最大值。据我所知,这并没有改变任何事情。

编辑2

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

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

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

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

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

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

InactivityTimeout表示在一定时间段内没有消息交换时是否关闭会话。你最好把它设置成一个合适的值。

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

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

长话短说:

事实证明,我的WCF设置很好。

ThreadPool是一个限制因素。在高流量(因此高负载)的情况下,我确实会生成太多必须发送到客户端的消息。由于没有足够的工作线程来发送消息,这些线程已排队。在某个时刻,队列已经满了——你就在那里。

要了解更多详细信息,请查看此问题&拉斯·毕晓普的回答。

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

编辑

我做了以下事情:

ThreadPool.SetMinThreads(1000, 500)

这种价值观可能就像用大锤敲坚果一样,但它是有效的。

相关内容

  • 没有找到相关文章

最新更新