带有epoll的TCP服务器的线程和扩展模型

时间:2011-11-29 08:11:55

标签: linux sockets tcp epoll

我已经阅读了C10K doc以及有关扩展套接字服务器的许多相关文章。所有道路都指向以下内容:

  1. 避免使用“每个连接的线程”的经典错误。

  2. 优先选择epoll。

  3. 同样,unix中的遗留异步io机制可能很难使用。

  4. 我的简单TCP服务器只是在专用端口上侦听侦听套接字上的客户端连接。收到新连接后,解析请求,然后发回响应。然后优雅地关闭套接字。

    我认为我可以很好地处理如何使用epoll在单个线程上扩展它。只有一个循环调用epoll_wait作为listen套接字以及现有的客户端连接。返回后,代码将处理新的创建新客户端连接以及管理现有连接的状态,具体取决于刚刚发出信号的套接字。也许还有一些逻辑来管理连接超时,正常关闭套接字以及为每个连接分配有效的资源。看起来很简单。

    但是,如果我想扩展它以利用多个线程和多个cpu核心呢?我想到的核心理念是:

    一个专用线程,用于侦听TCP侦听套接字上的传入连接。然后是一组N个线程(或线程池)来处理所有活动的并发客户端连接。然后发明一些线程安全的方法,其中监听线程将“新的连接(套接字)”“分派”到一个可用的工作线程。 (Windows中的ala IOCP)。工作线程将在它处理的所有连接上使用epoll循环来执行单线程方法的操作。

    我是否在正确的轨道上?或者是否有一个标准的设计模式用于在多个线程上使用epoll 执行TCP服务器

    有关监听线程如何将新连接分派给线程池的建议?

2 个答案:

答案 0 :(得分:2)

  1. 首先,请注意它是C * 10K *。如果你不到100(在一个典型的系统上),不要担心自己。即使这样,它依赖于你的套接字正在做什么
  2. 是的,但请记住,epoll操作需要系统调用,而且他们的成本可能会或可能不会比自己管理一些fd_set的成本更高。 poll也是如此。在低计数时,每次迭代在用户空间中进行处理的成本更低。
  3. 如果您不仅限于几个可以根据需要进行操作的套接字,那么异步IO会非常痛苦。大多数人通过使用事件循环来应对,但这会破坏并反转您的程序流。它通常还需要为此目的使用大而笨重的框架,因为可靠且快速的事件循环不容易正确。
  4. 第一个问题是,你需要这个吗?如果您通过产生线程来处理每个传入的请求来轻松应对现有流量,那么继续这样做。代码将更简单,并且您的所有库都可以很好地运行。

    正如我上面提到的,同时处理请求可能很复杂。如果您想在一个循环中执行此操作,则还需要在生成响应时保证CPU饥饿。

    如果生成的响应成本很高,那么您提出的调度模型是典型的第一步解决方案。您可以分叉或使用线程。在选择池化机制时,分支或生成线程的成本不应该是一个考虑因素:而应该使用这样的机制来限制或命令系统上的负载。

    将套接字批处理到多个epoll循环上是过分的。如果您非常绝望,请使用多个流程。请注意,来自多个线程和进程的套接字可以accept

答案 1 :(得分:-1)

我猜你是在正确的轨道上。但我也认为细节取决于具体情况(bandwidh,请求模式,无差别请求处理等)。我认为你应该尝试,并仔细测量基准。