【问题标题】:Service becomes unresponsive with many sockets in CLOSE_WAIT state服务变得无响应,许多套接字处于 CLOSE_WAIT 状态
【发布时间】:2013-09-26 07:28:24
【问题描述】:

我有一个带有 NetTcpBinding 的 WCF 服务,它与大约 100 个客户端一起运行。客户端定期从服务器轮询信息,一段时间后服务不再响应。

查看 netstat,我可以看到许多处于 CLOSE_WAIT 状态的连接。

这是我的绑定:

<netTcpBinding>
  <binding  name="default" maxReceivedMessageSize="2147483647" maxBufferPoolSize="2147483647" maxConnections="10000">
    <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
  </binding>
</netTcpBinding>

我也尝试将 closeTimeout 的值从默认的 00:01:00 更改为 00:00:10,但没有任何效果。 p>

机器是 Windows Server 2008 R2 64bit。

更新:

我现在加了ServiceThrottlingBehavior,结果还是一样。

new ServiceThrottlingBehavior
{
 MaxConcurrentCalls = 1000,
 MaxConcurrentInstances = 1000,
 MaxConcurrentSessions = 1000
};

更新2

我已将 SessionMode 设置为 NotAllowed 并将绑定更改为流式传输。

任何想法我可以做些什么来提高性能或找出问题?

【问题讨论】:

    标签: wcf nettcpbinding servicehost


    【解决方案1】:

    从您的描述看来:1.最初客户端能够毫无问题地连接到您的服务器,因此这排除了配置问题2.一段时间后服务器停止响应,但您没有说多久,请求率有多大,服务器是完全停止响应,还是只是间歇性地响应。基于此,一种可能性是服务器端出现问题。你注意到服务器端有什么异常吗?要寻找的是:

    1. 线程计数 - 是描述的线程池(作为某些设置 可以设置线程池线程的上限)?尤其是尝试新的发布 服务器并观察线程数直到它停止 回应,那里有什么模式吗?你可能有死锁,很长 阻塞操作等使线程保持太久。
    2. 内存 -- 是否存在内存泄漏问题?
    3. 它是自助托管服务吗?您是否有适当的代码来捕获 ServiceHost.Faulted 事件(以及 重启服务)?如果 ServiceHost 出现故障,它不会响应 任何请求。
    4. 看看WCF performance counter 告诉你什么,尤其是队列大小和活动连接数。从性能计数器中,您将知道服务是否正在接受任何请求,或者您的限制 配置是必要的。
    5. 终极诊断工具:开启服务端WCF tracing?打开一个跟踪文件将 绝对告诉你请求发生了什么。如果你看到任何 跟踪文件中的异常,您将找到根本原因。

    【讨论】:

    • 原来是几个问题的组合。有一些操作需要很长时间才能完成,同时客户端会超时。但是由于操作还在运行,所以服务器在操作完成后才关闭socker,才意识到客户端已经断开连接。您的回答很好地总结了您在这种情况下可以采取的步骤,大多数情况下无需进行任何代码修改。
    【解决方案2】:

    听起来您的客户永远不会断开连接。

    1. 您确定您的客户正确关闭了频道吗?请注意,您应该调用 ChannelFactory.Close,而不仅仅是 Dispose。

    2. 将 receiveTimeout 设置为较低的值,以验证这是问题所在。

    【讨论】:

    • 根据文档:CLOSE_WAIT表示服务器已经收到客户端的第一个FIN信号,正在关闭连接。
    【解决方案3】:

    您的客户端通过调用 close() 关闭了连接,这将 FIN 发送到服务器套接字,服务器套接字确认了 FIN 并且其状态现在更改为 CLOSE_WAIT,并保持这种状态,除非服务器发出 close() 调用插座。

    您的服务器程序需要检测客户端是否中止了连接,然后立即 close() 以释放端口。如何?请参阅读取()。在读取文件结尾(意味着收到 FIN)时,返回零。

    您可以检测客户端是否断开连接。

    任何 WCF 通道都实现 ICommunicationObject ,它为通道生命周期提供事件。

    您应该收听 Faulted 事件 sessionId 可以像往常一样从 OperationContext.Current 属性中访问。 当您的客户打开频道时(在第一次操作时),注册到适当的事件:

    OperationContext.Current.Channel.Faulted += new EventHandler(Channel_Faulted);
    OperationContext.Current.Channel.Closed += new EventHandler(Channel_Faulted);
    

    void Channel_Faulted(object sender, EventArgs e)
     {
         Logout((IContextChannel)sender);
     }
    
     protected void Logout(IContextChannel channel)
     {
            string sessionId = null;
    
            if (channel != null)
            {
                sessionId = channel.SessionId;
            }
     }
    

    如果套接字断开连接,您应该得到一个通道故障事件。 Closed 事件在客户端正常关闭时引发,Faulted 事件在意外(如网络故障的情况下)时引发。

    查看以下链接。它有点类似。它帮助了我..

    TCP Socket Server Builds Up CLOSE_WAITs Occasionally Over Time Until Inoperable

    【讨论】:

      【解决方案4】:

      验证路由器不是问题,因为一些消费级路由器对允许打开的套接字/连接的数量有上限。

      【讨论】:

        猜你喜欢
        • 2013-07-31
        • 1970-01-01
        • 1970-01-01
        • 2014-10-02
        • 1970-01-01
        • 1970-01-01
        • 2014-02-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多