我应该使用epoll还是仅仅阻止线程中的recv?

时间:2011-09-09 06:58:42

标签: python sockets webserver epoll

我正在尝试编写可扩展的自定义Web服务器。 这是我到目前为止所做的:

主循环和请求解释器在Cython中。主循环接受连接并将套接字分配给池中的一个进程(必须是进程,由于GIL,线程不会从多核硬件中获得任何好处)。

每个进程都有一个线程池。该进程将套接字分配给线程。 线程在套接字上调用recv(阻塞)并等待数据。当一些显示时,它会通过管道传输到请求解释器,然后通过WSGI发送到该线程中运行的应用程序。

现在我听说过epoll,我有点困惑。使用epoll获取套接字数据然后将其直接传递给进程有什么好处?或者我应该按照通常的路线让每个线程等待recv

PS:epoll实际上用于什么?似乎多线程和阻塞fd调用会完成同样的事情。

2 个答案:

答案 0 :(得分:7)

如果您已经使用多个线程,epoll不会为您提供额外的好处。

epoll的要点是单个线程可以同时监听多个文件选择器上的活动(并在每个文件选择器发生时响应它们),从而提供事件驱动的多任务处理,而不需要产生额外的线程。线程相对便宜(与产生进程相比),但每个 需要一些开销(毕竟,他们每个人都必须维持一个调用)栈)。

如果您愿意,可以使用epoll将池进程重写为单线程,这会减少您的整体线程使用次数,但当然您必须考虑这是否是您关心的事情或者不是 - 通常,对于每个工作者的同时请求数量较少,产生线程的开销并不重要,但如果您希望每个工作者能够处理1000个开放连接,那么开销就会变得很大(这就是epoll闪耀的地方。

可是...

你所描述的内容听起来很可疑,就像你基本上重新发明轮子一样 - 你的:

  1. 主循环和请求解释器
  2. 流程池
  3. 听起来几乎就像:

    1. nginx(或任何其他负载均衡器/反向代理)
    2. 预先分拣tornado app
    3. Tornado是一个使用epoll的单线程Web服务器python模块,它具有内置用于预分叉的功能(意味着它将自身的多个副本生成为单独的进程,有效地创建了一个进程池)。 Tornado基于为Friendfeed提供支持的技术 - 他们需要一种方法来处理寻找新实时更新的长轮询客户的大量开放连接。

      如果您将此作为一个学习过程,那么无论如何,重新发明!这是一个很好的学习方式。但是如果你真的想在这些事情之上构建一个应用程序,我强烈建议考虑使用现有的,稳定的,共同开发的项目 - 它会为你节省大量的时间,错误的启动,以及潜在的陷阱。


      (P.S。我赞同你的头像。< 3)

答案 1 :(得分:0)

epoll函数(以及同一系列中的其他函数pollselect)允许您编写管理多个网络连接的单线程网络代码。由于没有线程,因此不需要像多线程程序那样需要进行同步(这可能很难正确)。

另一方面,您需要为每个连接配备一个显式状态机。在线程程序中,此状态机是隐式的。

这些功能只是提供了一种在流程中复用多个连接的另一种方法。有时候不使用线程更容易,有时你已经在使用线程,因此使用阻塞套接字(在Python中发布GIL)更容易。

相关问题