我接受TCP连接的服务器有一个奇怪的问题。即使通常有一些进程在等待,但在某些连接数量上它会挂起。
长版:
服务器是用Perl编写的,并使用重用标志绑定$srv
套接字并监听== 5.然后,它分为10个进程,循环为$clt=$srv->accept(); do_processing($clt); $clt->shutdown(2);
用C语言编写的客户端也非常简单 - 它发送一些行,然后接收所有可用的行并执行shutdown(sockfd, 2);
没有任何异步正在进行,最后发送和接收队列都是空的(如报告的那样) netstat
)。
连接仅持续约20ms。所有客户端的行为方式相同,实现方式相同等等。现在假设我接受来自客户端1的X
连接和来自客户端2的另一个X
。进程仍然报告它们都是空闲的时间。如果我从客户端3添加另一个X
连接,突然服务器进程在接受后立即开始挂起。他们在accept();
之后执行的第一个阻止事件是while (<$clt>) ...
- 但是他们没有获得任何数据(在第一次尝试时已经存在)。突然间,所有10个进程都处于此状态,并且不会停止等待。在strace
上,服务器进程似乎挂在read()
上,这是有道理的。
属于该服务器的TIME_WAIT
状态中存在大量连接(问题开始显示时为~100),但这可能是一个红色的鲱鱼。
这里可能会发生什么?
经过一些更多的分析:结果发现客户端有问题,在尝试下一个连接之前没有正确关闭先前的连接。负载平衡列表开头的服务器是旧的连接。
答案 0 :(得分:1)
这可能不是您问题的解决方案,但它可能会解决您将来遇到的问题:完成后不要忘记关闭()套接字! shutdown()将断开流,但它仍然会吃掉文件描述符。
由于你说strace显示进程停留在read()中,那么你的问题似乎是客户端没有发送你希望它发送的数据。您应该修复您的客户端,或者向您的服务器进程添加一个警报(),以便它们能够在死客户端中生存。
答案 1 :(得分:0)
是否会飙升然后暂停很长时间(大约两分钟左右)然后再次激增?如果是这样,您可能没有将系统最大打开文件限制设置得足够高。