我正在尝试创建一个我希望具有高性能要求的服务器。这个问题涉及服务器核心。哪些编程思想最能支持快速性能?
我意识到其中一些取决于用例。例如,如果存在大量小数据包,则关闭TCP_NODELAY的6会产生负面影响。 3听起来如果响应微不足道可能会更快。我还没有想到任何影响性能的其他问题。
答案 0 :(得分:3)
我将从单线程方法开始:在Linux上使用非阻塞I / O和快速轮询机制,如边缘触发的epoll。 (其他平台也有类似的技术。)将轮询循环中的所有内容居中,大大简化了程序设计,因此我肯定会将signalfds,timerfds和eventfds放在那里。然后一切都由一个中央循环处理。
如果需要多线程,这可能就像同时运行主循环一样简单。如果你将事件设置为“一次性”,它们将从轮询中被禁用,直到重新启动,因此处理事件的线程可以安全地假设是唯一的线程这样做(并在最后重新设置事件) )。您只需要同步程序不同部分之间的通信或共享数据访问,但轮询器已经完成了很多同步。
答案 1 :(得分:2)
在我看来,最简单的代码是使用阻塞I / O的每个连接一个线程。使用您喜欢的线程模型也可以轻松编写。
多路复用非阻塞I / O的问题是维护每个连接的状态。例如,我想写1024个字节但write
只消耗900个......所以现在必须记住124个字节以便稍后写入它们。这只是处于原始“发送缓冲区”级别的状态;考虑整个协议的状态,它可以很快变得复杂。当然,没有什么是不可能的,但是使用阻塞调用要简单得多,假设连接不需要彼此交互(很多)。
我已经将这种方法用于适当数量(〜几十个)的连接,并在一对10GbE链路上以每秒超过一千兆字节的速度移动数据。 Linux内核的调度程序非常适合处理此范围内的线程计数。
对于为成千上万或几万个客户提供服务的Web服务器类型......好吧,我没有亲自尝试过。我已经读过多路复用技术(epoll
等)在这种情况下更快。正如其他人所说,这取决于你的申请。
但是如果你的应用程序就像我的(连接数量适中,它们之间的交互有限),那么“每个连接一个线程”的方法就会失败,IMO。
答案 2 :(得分:0)
取决于。
这类问题很难回答;这将是项目本身的角色之一。您需要在工作负载下测量服务器的性能,然后查看哪些选项最适合您的用例。
例如,设置TCP_NODELAY将减少请求的延迟,但该选项是有原因的;您将通过设置TCP_NODELAY来降低吞吐量。
以下网站提供了一些您应该查看的信息:http://www.kegel.com/c10k.html。其中一些现在有点旧(几年),但它包含了您应该考虑使用的技术列表:epoll,异步I / O.
您应该开始以模块化方式设计系统,以便您的工作人员不依赖于特定的实现(select / poll / epoll)。像setsockopt这样的东西可以在以后轻松更改,你根本不用担心它们。
让它先工作 - 然后让它“快速”;无论你的意思是什么“快”。如果你想要一些可扩展的东西,那就要注意算法的大O(O(n),O(n ^ 2)......等)。