我们有一个使用 select() 设计的 web 服务器,直到上周才真正看到太多负载,并且在我们 500-1000 conn/s 的负载下总是可以正常工作。然而,我们最近开始看到更高的负载(和峰值),并且在看到套接字句柄 > FD_SETSIZE 后遇到了 select() 变得疯狂的问题。如果它的 FD_SET 中有任何 > FD_SETSIZE 的内容,这只会冻结服务器,并且在重复超时后选择进入一个牢不可破的循环。切换到 poll(或 epoll)的选项现在不存在,我们必须坚持使用 select。我现在修复它的方法是增加侦听队列并停止接受新连接,当我看到一个新连接返回 accept() 为 >= FD_SETSIZE 并返回到侦听套接字上的 select() 时。这是有效的,因为操作系统会回收文件句柄并始终尝试提供最小的可用句柄。但不利的一面是,如果套接字句柄 >= FD_SETSIZE,则在调用 accept() 时,我最终会向某些连接发送 RST。目前这仍然是可以接受的,因为它使服务器保持运行并且连接丢失约为 5%。有没有办法可以在不断开这些连接的情况下做到这一点。我不想记录所有使用过的手柄和使它变得过于复杂的东西。正在创建一个伪造的套接字,在调用 accept 之前检查它的句柄并关闭它,这将相当准确地估计操作系统接下来会给我什么句柄。目前这仍然是可以接受的,因为它使服务器保持运行并且连接丢失约为 5%。有没有办法可以在不断开这些连接的情况下做到这一点。我不想记录所有使用过的手柄和使它变得过于复杂的东西。正在创建一个伪造的套接字,在调用 accept 之前检查它的句柄并关闭它,这将相当准确地估计操作系统接下来会给我什么句柄。目前这仍然是可以接受的,因为它使服务器保持运行并且连接丢失约为 5%。有没有办法可以在不断开这些连接的情况下做到这一点。我不想记录所有使用过的手柄和使它变得过于复杂的东西。正在创建一个伪造的套接字,在调用 accept 之前检查它的句柄并关闭它,这将相当准确地估计操作系统接下来会给我什么句柄。
while(max_conn_to_accept--){
SOCKET a_s = accept(..);
if(a_s >= FD_SETSIZE){
close(a_s);
return;
}