1

我们有一个使用 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;
}
4

1 回答 1

1

只是提高FD_SETSIZE-DFD_SETSIZE=16384在编译器命令行上指定。

我认为您的版本足够新,没有其他问题。如果您在头文件中遇到错误,您可能需要调整一两行。

例如,如果您看到如下内容:

#undef __FD_SETSIZE
#define __FD_SETSIZE    1024

将其更改为:

#undef __FD_SETSIZE
#ifndef FD_SETSIZE
#define __FD_SETSIZE    1024
#else
#define __FD_SETSIZE    FD_SETSIZE
#endif

或者,如果您看到:

#define FD_SETSIZE      1024

将其更改为:

#ifndef FD_SETSIZE
#define FD_SETSIZE      1024
#endif

但是,我认为你不需要改变任何东西。

于 2012-09-10T16:40:41.473 回答