我有一个用 C++ 编写的服务器程序,它在 Linux 上运行并使用 TCP 实现基于推送的消息服务。由于推送方法,可能有很多同时连接(我计划大约 100 万)必须保持打开更长时间。大多数情况下,这些连接处于空闲状态,偶尔会发出心跳,并且传输通常会同时在许多连接上突发。
为了让事情正常进行,我使用 epoll
来多路复用大量的套接字,并且通过修改 RLIMIT_NOFILE
,它实际上对大量的套接字工作得很好套接字。
我的问题是我还在同一个程序中使用其他类型的连接,最著名的是 FastCGI(使用 FastCGI SDK 中的 libfcgi)来接受 HTTP 请求,它使用 select()
它们的内部文件描述符。当这些文件描述符变得大于 1024 (FD_SETSIZE
) 时,这会导致问题,如果程序的 epoll
部分用完下面的大部分 fd 数字,这必然会发生1024.
我想知道处理这个问题的最佳方法是什么。
我是否只需要修改所有使用 select()
的外部代码并改为使用 poll()
?
有没有办法强制我的基于 epoll
的代码(特别是 accept()
调用)只使用 1024 以上的文件描述符,这样下面的那些为基于select()
的代码保留?
我知道可以通过某种方式增加 FD_SETSIZE
的值,但我认为由于 select()
的工作方式,这会严重损害性能,在我看来,它是一种 hack 而不是真正的解决方案。
最佳答案
我建议将这些东西移动到它们自己的进程中,以便它们获得自己的文件描述符。我建议你有一个协议(protocol),可以在单个 TCP 连接上多路复用大量 TCP 连接。您的服务器将与多路复用器而不是单个客户端通信。多路复用器可以在同一台机器或不同机器上运行,它可以处理数万个客户端连接,并且只会与服务器建立一个连接。
这样做的一大优势是您的服务器机器不必处理大量的 TCP 连接状态。它不必处理 Internet 垃圾,例如丢包、重传、重复包、流氓 SYN、慢速链接等。它不必为每个客户端都设置发送缓冲区,而只需与可以为客户端进行缓冲的快速、干净的多路复用器通信。
如果工作量太大或由于某种原因无法实现,您可以使用 dup2
将文件描述符重新编号为更高编号的描述符。不过,我强烈建议使用多路复用器——您尝试处理的连接数量太大,无法从单个进程处理。
关于c++ - 使用带有大量文件描述符的 select() 的外部代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42962495/