为什么 Apache 事件 MPM 性能不佳?

Event MPM的设计与Nginx并不完全相同,但显然是为了让keepalives更站得住脚,并更快地发送静态文件。我的理解是,事件 MPM 有点用词不当,因为:

  1. 尽管连接已传递到 kqueue/epoll,
  2. 某些非常重要的模块(如mod_gzip和mod_ssl)将阻塞/消耗线程,直到响应完成,
  3. 对于大文件来说,这是一个问题,但对于PHP生成的HTML文档等来说可能不是。

不幸的是,Apache不断失去市场份额,大多数基准测试都对MPM事件进行了诅咒。基准测试是否有缺陷,或者事件MPM在Nginx上真的做得那么差?即使有这些限制,在正常流量(非恶意)和较小的文件下,它应该与Nginx有一定的竞争力。例如,在慢速连接上,通过php-fpm提供PHP生成的文档应该是竞争性的,因为文档将被缓冲(即使被sl'd和gzip'd)并异步发送。使用压缩或不压缩的SSL和非SSL连接都不应该与在Nginx中在这样的工作负载上工作有意义地不同。

那么,为什么它没有在各种基准测试中大放异彩呢?这是怎么回事?或者基准测试有什么问题?一个主要网站是否将其用作对它可以执行的权威的呼吁?


答案 1

它比nginx慢,因为具有事件MPM的Apache(非常)大致相当于Apache前面的事件驱动的HTTP代理(nginx,varnish,haproxy)与工作线程MPM。事件 worker,但事件 MPM 的线程不是将每个新连接传递给线程的生存期,而是将连接传递给辅助线程,辅助线程将其推送到队列上,或者在保持活动状态关闭或已过期时将其关闭。

与工作线程相比,事件的真正好处是资源使用情况。如果需要维持 1,000 个并发连接,则工作线程 MPM 需要 1,000 个线程,而事件 MPM 可能会在事件队列中管理 100 个活动线程和 900 个空闲连接。事件 MPM 将使用该假设中工作 MPM 资源的一小部分,但缺点仍然存在:每个请求都由一个单独的线程处理,该线程必须由内核调度,因此将产生切换上下文的成本。

另一方面,我们有nginx,它使用事件模型本身作为其调度程序。Nginx只是在每个连接上处理尽可能多的工作,然后再转到下一个连接。无需额外的上下文切换。

事件 MPM 真正闪耀的一个用例是处理在 Apache 中运行大量应用程序的设置,并且为了节省在保持活动状态期间空闲的线程的资源,您将在 apache 前面部署代理(如 nginx)。如果您的前端没有其他用途(例如静态内容,代理到其他服务器等),则事件MPM可以很好地处理该用例,并消除对代理的需求。


答案 2

对我来说,主要的操作差异是:

  • 处理程序(负责生成响应的插件)是同步的 - 如果它们执行计算或I / O,它们将占用线程
  • 核心必须使用跨线程锁来保护关键数据结构,因为它是多线程的,可以支持如此多的这些同步请求

这就是为什么像nginx(或Apache Traffic Server或任何现代商业/高性能代理)这样的高容量服务器通常会排在前面。

IMO 您问题中的要点有点偏离了标准,SSL和放气并没有真正造成太大的差异,因为它们都是过滤器,并没有真正导致可伸缩性问题,甚至不会将httpd与其关于请求或连接的生命周期的传统API保证联系起来。像这样的过滤器(与处理程序或负责低级I / O的核心过滤器)可能是与处理模型相关的最少的事情。

但是,我也不认为相比之下,除了最极端的工作负载或极其受限的系统之外,它的表现都不那么糟糕。我见过的大多数基准测试的质量都非常差,原因如此之深。

我认为,在很大程度上,人们希望他们今天所谓的Web服务器成为更复杂的应用程序服务器(Java EE,PHP等)的代理,并且旨在在没有API包袱的情况下最有效地移动I / O的服务器将具有优势。


推荐