我们都已阅读基准并了解事实 - 基于事件的异步网络服务器比线程对等服务器更快。想想lighttpd或Zeus与Apache或IIS。那是为什么?
答案 0 :(得分:5)
我认为基于事件和基于线程不是问题 - 它是一个非阻塞的多路复用I / O,可选套接字,解决方案与线程池解决方案。
在第一种情况下,无论使用什么输入,您都会处理所有输入 - 因此读取时没有阻塞 - 单个“监听器”。单个侦听器线程将数据传递给可以是不同类型的工作线程 - 而不是每个连接一个。同样,在写入任何数据时都没有阻塞 - 因此数据处理程序可以单独运行它。因为这个解决方案主要是IO读/写,所以它不占用很多CPU时间 - 因此你的应用程序可以用它做任何想做的事情。
在线程池解决方案中,您有各自的线程处理每个连接,因此他们必须共享上下文切换的时间 - 每个人都在“监听”。在这个解决方案中,CPU + IO操作在同一个线程中 - 它获得一个时间片 - 所以你最终等待IO操作完成每个线程(阻塞),传统上可以在不使用CPU时间的情况下完成。
Google提供非阻止IO以获取更多详细信息 - 您也可以找到一些与线程池相比较的比较。
(如果有人能澄清这些观点,请随意)
答案 1 :(得分:3)
事件驱动的应用程序不本来就更快。
来自Why Events Are a Bad Idea (for High-Concurrency Servers):
We examine the claimed strengths of events over threads and show that the
weaknesses of threads are artifacts of specific threading implementations
and not inherent to the threading paradigm. As evidence, we present a
user-level thread package that scales to 100,000 threads and achieves
excellent performance in a web server.
这是在2003年。从那时起,现代操作系统的线程状态肯定有所改善。
编写基于事件的服务器的核心意味着在代码中重新发明协作式多任务(Windows 3.1样式),最有可能在已经支持正确的先发制人多任务处理的操作系统上,并且没有透明的上下文切换的好处。这意味着您必须管理堆上的状态,该状态通常由指令指针隐含或存储在堆栈变量中。 (如果你的语言有它们,那么闭包可以显着减轻这种痛苦。尝试在C语言中这样做很有趣。)
这也意味着您获得了合作多任务所暗示的所有警告。如果您的某个事件处理程序因任何原因需要一段时间才能运行,那么它将停止该事件线程。完全不相关的请求滞后。即使是冗长的CPU耗费操作也必须在其他地方发送以避免这种情况。当您谈论高并发服务器的核心时,“冗长操作”是一个相对术语,对于预期每秒处理100,000个请求的服务器,大约为微秒。我希望虚拟内存系统永远不必为你从磁盘中提取页面!
从基于事件的体系结构中获得良好的性能可能会非常棘手,尤其是在考虑延迟而不仅仅是吞吐量时。 (当然,你也可以用线程做出很多错误。并发性仍然很难。)
新服务器应用程序作者的几个重要问题:
答案 2 :(得分:1)
这真的取决于你在做什么;对于非常重要的应用程序来说,基于事件的编程肯定是棘手的。作为一个Web服务器实际上是一个非常简单易懂的问题,事件驱动和线程模型在现代操作系统上运行良好。
在事件模型中正确开发更复杂的服务器应用程序通常非常棘手 - 线程应用程序更容易编写。这可能是决定因素,而不是表现。
答案 3 :(得分:0)
这不是真正的线程。它是关于线程用于服务请求的方式。对于像lighttpd这样的东西,你有一个通过事件服务多个连接的线程。对于旧版本的apache,每个连接都有一个进程,并且进程在传入数据时醒来,因此当有大量请求时,您最终会得到一个非常大的数字。现在,使用MPM apache基于事件也可以看到apache MPM event。