我们都阅读过基准测试并了解事实 - 基于事件的异步网络服务器比线程对应的服务器更快。想想 lighttpd 或 Zeus 对比。阿帕奇或 IIS。这是为什么?

有帮助吗?

解决方案

我认为基于事件和基于线程不是问题 - 它是一个非阻塞的多路复用I / O,可选套接字,解决方案与线程池解决方案。

在第一种情况下,无论使用什么输入,您都会处理所有输入 - 因此读取时没有阻塞 - 单个“监听器”。单个侦听器线程将数据传递给可以是不同类型的工作线程 - 而不是每个连接一个。同样,在写入任何数据时都没有阻塞 - 因此数据处理程序可以单独运行它。因为这个解决方案主要是IO读/写,所以它不占用很多CPU时间 - 因此你的应用程序可以用它做任何想做的事情。

在线程池解决方案中,您有各自的线程处理每个连接,因此他们必须共享上下文切换的时间 - 每个人都在“监听”。在这个解决方案中,CPU + IO操作在同一个线程中 - 它获得一个时间片 - 所以你最终等待IO操作完成每个线程(阻塞),传统上可以在不使用CPU时间的情况下完成。

Google提供非阻止IO以获取更多详细信息 - 您也可以找到一些与线程池相比较的比较。

(如果有人能澄清这些观点,请随意)

其他提示

事件驱动的应用程序是 不是 本质上更快。

为什么事件是一个坏主意(对于高并发服务器):

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 个请求的服务器而言,约为微秒。我希望虚拟内存系统永远不必为您从磁盘中提取页面!

从基于事件的架构中获得良好的性能可能很棘手,特别是当您考虑延迟而不仅仅是吞吐量时。(当然,使用线程也可能犯很多错误。并发仍然很难。)

对于新服务器应用程序的作者来说,有几个重要问题:

  • 线程在您今天打算支持的平台上表现如何?他们会成为你的瓶颈吗?
  • 如果您仍然遇到错误的线程实现:为什么没有人解决这个问题?

这真的取决于你在做什么;对于非常重要的应用程序来说,基于事件的编程肯定是棘手的。作为一个Web服务器实际上是一个非常简单易懂的问题,事件驱动和线程模型在现代操作系统上运行良好。

在事件模型中正确开发更复杂的服务器应用程序通常非常棘手 - 线程应用程序更容易编写。这可能是决定因素,而不是表现。

这实际上与线程无关。它与线程用于服务请求的方式有关。对于像 lighttpd 这样的东西,您有一个线程通过事件为多个连接提供服务。对于旧版本的 apache,每个连接都有一个进程,该进程会在传入数据时唤醒,因此当有大量请求时,您最终会得到非常大的数字。然而,现在使用 MPM apache 是基于事件的,也请参见 Apache MPM 事件.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top