netstat 显示有 153 个连接处于 CLOSE_WAIT 状态。这些连接永远不会关闭。因此,随着时间的推移,服务器会充满这些连接,从而占用大量 RAM,现在网站无法加载。
netstat 显示许多类似以下内容的信息:
tcp 160 0 my_server_name:http my_server_name:51584 CLOSE_WAIT
tcp 160 0 my_server_name:http my_server_name:51586 CLOSE_WAIT
tcp 0 0 my_server_name:http my_server_name:50827 CLOSE_WAIT
tcp 0 0 my_server_name:http my_server_name:50830 CLOSE_WAIT
tcp 312 0 my_server_ip.static.:http rate-limited-proxy-72:61249 CLOSE_WAIT
tcp 382 0 my_server_ip.static.:http b3090792.crawl.yahoo.:58663 CLOSE_WAIT
tcp 382 0 my_server_ip.static.:http b3090792.crawl.yahoo.:34655 CLOSE_WAIT
tcp 382 0 my_server_ip.static.:http b3090792.crawl.yahoo.:56681 CLOSE_WAIT
tcp 382 0 my_server_ip.static.:http b3090792.crawl.yahoo.:40829 CLOSE_WAIT
tcp 576 0 my_server_ip.static.:http b3090792.crawl.yahoo.:38278 CLOSE_WAIT
tcp 47 0 my_server_ip.static.:http 203.200.5.143.ill-bgl:49379 CLOSE_WAIT
如果我查看 appache error_log,在 CLOSE_WAIT 情况出现之前,会出现如下行
[warn] child process 15670 still did not exit, sending a SIGTERM
[error] child process 15670 still did not exit, sending a SIGKILL
[notice] child pid 3511 exit signal Segmentation fault (11)
我的设置是 Apache 2.2.3 RAM 1024 MB(最大 2048 MB)CentOS 版本 5.3(最终版)运行 2 个 WPMU 2.9.2 安装
答案1
背景
当远程端发送设置了 FIN 标志的数据包终止连接时,套接字将进入 CLOSE_WAIT 状态。然后,它在此状态下等待本地应用程序对close()
套接字的响应,然后向客户端发送自己的 FIN,并将套接字转换为 LAST_ACK 状态。另请参阅TCP 状态转换图和RFC 793。
还要注意,CLOSE_WAIT 与臭名昭著的 TIME_WAIT 无关,因为前者发生在被动关闭分支(远程端首先关闭),而后者发生在主动关闭分支(本地端首先关闭)。
问题描述
通常,连接会很快从 CLOSE_WAIT 转换到 LAST_ASK。如果远程地址和端口持续快速变化,则大量处于 CLOSE_WAIT 状态的连接可能只是大量连接打开、使用和关闭的结果。应该检查系统性能,但这本身并不构成问题。
如果远程地址和端口变化缓慢,则表明应用程序进程需要等待 CPU,在这种情况下高负载平均数将证实这一点。
另一方面,如果远程地址和端口保持不变,而处于 CLOSE_WAIT 状态的连接数不断增加,则很可能表明应用程序存在问题。这是资源泄漏错误的一种特殊情况:应用程序泄漏打开的套接字而不是及时关闭它们。这会消耗内核内存,一旦达到打开文件描述符的最大数量,最终会导致应用程序失败。
但请注意,泄漏的速度可能很慢。通常情况下,此类错误是由于未能处理请求中间的异常而导致的,从而中断了工作线程中的执行流程,这随后可能会阻止清理(包括套接字关闭)。有问题的异常可能很少发生。
临时解决方案
问题的临时解决方案是增加打开文件描述符的限制,并在问题开始影响性能时(最好在此之前)定期重新启动应用程序。请注意,这可能会无意中影响当前打开的连接。冗余服务器和负载平衡的存在可以帮助向用户隐藏问题。
永久解决方案
问题的永久解决方案是部署没有错误的应用程序版本。临时解决方案对用户和业务的损害程度、修补版本的准备情况以及最后一个工作版本的状态有助于决定是否回滚到应用程序的最后一个工作版本或等待修复。