2

以下策略似乎效果很好:

  • 在侦听器套接字上使用带有非阻塞accept() 调用的单个线程/进程,而不管程序如何处理接受的请求。
  • 在每个进程中使用带有阻塞 accept() 调用的多个线程/进程。当一个连接进来时,这恰好唤醒了一个accept()。

不能正常工作的是 EPOLLIN 在回调中使用 accept() 监视每个线程/进程的侦听器套接字。这会唤醒每个线程/进程,尽管只有一个可以成功地实际接受()。这就像过去阻塞 accept() 的糟糕日子一样,当连接进入时会导致踩踏。

有没有办法在仍然使用 EPOLLIN 的同时只唤醒一个线程/进程来接受()?或者我应该重写以使用阻塞接受(),只是使用线程隔离?

只有一个线程/进程运行accept()不是一个选项,因为我试图以一种方式将进程作为一个池来管理,每个进程不需要知道它是否是唯一的守护进程accept()侦听器套接字。

4

2 回答 2

2

多个套接字监听同一个原型+地址+端口怎么样?这可以通过 Linux 来完成SO_REUSERPORThttps://lwn.net/Articles/542629/。我没有尝试过,但我认为它甚至可以使用 epoll,因为只有一个套接字获取实际事件。

警告购买者这是一个不可移植的、仅限 Linux 的解决方案。SO_REUSEPORT还受到链接文章中详述的一些错误/功能的影响。

于 2013-10-21T14:17:15.360 回答
2

当有新连接进入时,您需要使用EPOLLETorEPOLLONESHOT以便恰好一个线程被EPOLLIN事件唤醒。处理线程然后需要accept在循环中调用,直到它返回EAGAIN( ) 或使用( )EPOLLET手动重置,以便获得更多连接处理。epoll_ctlEPOLLONESHOT

通常在使用多线程和 epoll 时,您希望使用EPOLLETor EPOLLONESHOT。否则当一个事件发生时,会唤醒多个线程来处理它,它们可能会相互干扰。充其量,他们只会浪费时间在再次等待之前找出其他线程正在处理该事件。在最坏的情况下,他们会死锁或损坏东西。

于 2013-10-21T14:29:24.673 回答