在本土的http服务器上支持保持活动套接字的问题

时间:2011-04-22 10:44:43

标签: c linux http pthreads

我目前正在尝试构建一个http服务器。服务器由一个监听线程使用select(...)和由线程池管理的四个工作线程进行多线程处理。我目前在Core I3 330M上每秒管理大约14k-16k的请求,文件长度为70字节,响应时间为6-10ms。但这是没有保持活力的,我服务的任何插座在工作完成时我立即接近。

编辑:当检测到套接字上的活动时,工作线程处理已调度的“作业”,即。服务请求。 “工作”完成后,如果没有“工作”,我们会睡觉,直到有更多的“工作”被派遣,或者如果已经有一些“工作”,我们就会开始处理其中的一个。

当我开始尝试实现keep-alive支持时,我的问题就出现了。通过keep-alive激活,我只需要每秒管理1.5k-2.2k请求,并且有100个开放套接字。这个数字增加到大约12k,1000个开放插座。在这两种情况下,响应时间大约为60-90ms。我觉得这很奇怪,因为我目前的假设认为请求应该上升,而不是下降,响应时间应该会下降,但绝对不会上升。

我尝试了几种不同的策略来解决低绩效问题:
    

    1。使用超时值调用select(...)/ pselect(...),以便我们可以重建FD_SET结构并侦听阻塞后到达的任何其他套接字,并为任何检测到的套接字活动提供服务。      (除了低性能之外,在我们阻塞时还存在套接字被关闭的问题,导致select(...)/ pselect(...)报告错误的文件描述符。)
    
    2。有一个只接受新连接的监听线程和一个保持活动线程,该线程通过管道通知在我们阻塞和任何新套接字活动后到达的任何新套接字,并重建FD_SET。      (这里的另外一个问题与'1'相同。)
    
    3。选择(...)/ pselect(...)超时,当要完成新工作时,分离具有活动的套接字的链接列表条目,并在请求被服务时将其添加回来。重建FD_SET有望更快。这样我们也可以避免尝试收听任何错误的文件描述符。
    
    4。合并(2.)和(3.)。

      
      - 可能还有一些,但他们逃脱了我的压力。

    保持活动套接字存储在一个简单的链接列表中,其添加/删除方法由pthread_mutex锁定,负责重建FD_SET的函数也具有此锁定。

    我怀疑这是互斥锁的持续锁定/解锁是这里的主要罪魁祸首,我试图描述问题,但gprof或google-perftools都不是非常合作,要么引入极端不稳定,要么明显拒绝收集所有数据(这可能是我不知道如何正确使用这些工具。)。但是删除锁可能会使链表处于不合理的状态,并可能导致程序崩溃或将程序置于无限循环中。 当我使用它时,我也怀疑select(...)/ pselect(...)超时,但我非常有信心这不是问题,因为即使没有它也会保持低性能。 / p>

    我不知道应该如何处理保持活动的套接字,我想知道你们那里的人是否对如何修复低性能有任何建议,或者对我可以使用的任何替代方法有任何建议去支持keep-alive套接字。

    • 如果您需要更多信息以便能够正确回答我的问题,请不要犹豫,我会尽力为您提供必要的信息并使用这些新信息更新问题。

5 个答案:

答案 0 :(得分:6)

尝试彻底摆脱选择。您可以在每个流行的平台上找到某种事件通知:freebsd()上的kqueue / kevent,Linux上的epoll等。这样您就不需要重建FD_SET并且可以随时添加/删除监视的fds。

答案 1 :(得分:0)

有很多选择:

  • 使用进程代替线程,并通过Unix套接字传递文件描述符。
  • 维护每个线程的套接字列表。您甚至可以accept()直接在工作线程上。
  • 等...

答案 2 :(得分:0)

您的测试客户端是否重用套接字?他们正确处理还活着吗? 我可以看到这样一种情况:您只需传递keep alive标头即可在基准测试代码中进行最小的更改,但不会更改您的代码,以便在收到付费数据包后在客户端关闭套接字。 这将带来所有保持活力的成本,而没有任何好处。

答案 3 :(得分:0)

您之前尝试做的事情已经完成。考虑阅读Leader-Follower网络服务器模式http://www.kircher-schwanninger.de/michael/publications/lf.pdf

答案 4 :(得分:0)

当客户端将套接字用于多个请求时,时间增加将更加明显。如果您只是打开和关闭但仍然告诉客户端保持活着,那么您的情况与没有保持活动状态的情况相同。但是现在你有插座的开销。

但是,如果您从同一客户端多次使用套接字进行多次请求,那么您将失去TCP连接开销并以此方式获得性能。

确保您的客户正确使用keepalive。并且可能是获得套接字状态和数据通知的更好方法。也许是民意调查设备或排队请求。

http://www.techrepublic.com/article/using-the-select-and-poll-methods/1044098

此页面有一个用于处理民意调查设备的Linux补丁。也许对它是如何工作有一些了解,你可以在你的应用程序中使用相同的技术,而不是依赖于可能没有安装的设备。