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

11 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.).

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

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

我怀疑它是在这里的主要元凶互斥的不断锁定/解锁,我试着来分析这个问题,但没有gprof的还是谷歌perftools一直非常合作,无论是引入极端不稳定或纯拒不收集的任何数据所有(这可能是我不知道如何正确使用这些工具.).但是删除锁可能会使链表处于不合理的状态,并可能导致程序崩溃或将程序置于无限循环中.我在使用它时还怀疑select(...)/ pselect(...)超时,但我非常有信心这不是问题,因为即使没有它也会保持低性能.

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

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

bla*_*aze 6

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

  • +1.选择很糟糕.另外,看看`libevent`和/或Boost.ASIO - 这些库正在使用特定于平台的机制.您可以依赖它们或至少将它们用作参考. (2认同)

The*_*der 0

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

但是,如果您从同一客户端多次使用套接字来处理多个请求,那么您将损失 TCP 连接开销并以这种方式获得性能。

确保您的客户端正确使用 keepalive。这可能是获取套接字状态和数据通知的更好方法。也许是轮询设备或对请求进行排队。

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

此页面有一个用于 Linux 处理轮询设备的补丁。也许对其工作原理有所了解,并且您可以在应用程序中使用相同的技术,而不是依赖于可能未安装的设备。