Apache vs Nginx(实际考虑因素对比)

  • server

posted on 21 Aug 2019 under category 翻译

原文地址:https://www.digitalocean.com/community/tutorials/apache-vs-nginx-practical-considerations

引言

Apache和Nginx是世界上最常见的两种开源Web服务器。他们共同负责于为互联网上超过50%的流量提供服务。这两种解决方案都能处理各种工作负载,并能够与其他软件一同提供完整web栈(套件)。

虽然Apache和Nginx有许多共性,但是不应该认为它俩是可以完全互相替换的。二者各有所长,根据不同场景,您可能需要重新评估您的Web服务器选择,理解这点是很重要的。本文将专门讨论每种服务器如何在各个领域中表现。

总体概述

在我们深入对比Apache和Nginx的差异前,让我们快速了回顾下两个项目的背景及一般特性。

Apache

Apache HTTP Server由Robert McCool创建于1995年,1999年后一直在Apache Software Foundation主导下发展。由于HTTP Web服务器该基金的原始项目且是迄今为止最受欢迎的软件之一,所以经常被简称为”Apache”。

自1996年以来,Apache一直是互联网上最受欢迎的服务器。由于这种流行,Apache受益于优秀的文档和其他软件项目的全面支持。

由于它的灵活性,功能强大和广泛支持,Apache经常是管理员的首选。它可以通过动态加载的模块系统进行扩展,并可以处理大量的解释型语言而无需连接到单独的软件。

Nginx

在2002年,Igor Sysoev开始开发Nginx来作为解决C10K问题的答案,对于现代Web的要求来说,开始处理一万并发连接对Web服务器是个挑战。Nginx的最初公开版本发布于2004年,它通过依赖异步、事件驱动的架构来实现这个目标。

Nginx自发布以来越来越受欢迎,归根于它的轻量级资源利用率以及能够在最小硬件下轻松扩展的特点。Nginx擅长处理快速提供静态内容,旨在将动态请求转递至更适合这些请求目的的其他软件。

Nginx经常被管理员选择来提高资源效率和负载响应能力。倡导者鼓励Nginx专注于核心Web服务器及代理功能。

连接处理架构

Apache和Nginx之间的一个重要区别是如何处理连接和流量的实际方式。这可能是他们如何对不通流量状况做出响应的最显著差异。

Apache

Apache提供了各种多进程处理模块(MPMs),它们决定着客户端请求如何被处理。总体来说,MPMs允许管理员轻松地切换连接处理架构。具体架构如下:

  • mpm_prefork: 此进程模块用于生成进程,该生成的进程仅有一个线程且用于处理请求。一个子进程只能处理一个连接。只要请求数小于进程数,该MPM模式是非常快的。然而,当请求数超过进程数时,性能就会迅速下降,所以在很多场景下,它不是个好的选择。每个进程都会对内存(RAM)消耗产生显著影响,所以该MPM模式难以被有效扩展。然而请记住,与其他不产生线程的组件配合使用仍然是个不错的选择。例如,PHP是非线程安全的,所以该MPM模式是唯一被推荐与mod_php(用于处理这些文件的Apache模块)一同使用的安全方式。
  • mpm_worker: 该模式产生可以管理多个线程的进程。每个线程可以单独处理一个连接。因为线程的效率优于进程,这意味着该MPM模式比mpm_prefork模式易于扩展。由于线程数量对于进程,这也意味着新的连接可以立即获得空闲线程,而不必等待空闲进程。
  • mpm_event: 再大多数情况下,该模式与mpm_prefork是类似的,但是它是经过优化的用于处理保持活跃的(keep-alive)连接。当使用mpm_worker模式时,只要连接是保持活跃状态,不管是否正在进行请求,它都将占用着一个线程。mpm_event模式通过留出专门的线程来处理保持活跃的连接并将活动的请求转交给其他线程。这样可以防止因保持活跃请求而陷入困境,从而加快执行效率。随着Apache2.4版本的发布,该特性已被标记为稳定。

如你所见,Apache提供了灵活的框架给供用户选择不同的连接及请求处理算法。所提供的选择主要取决于服务器的发展变革以及随着互联网环境变化对并发性需求的增加程度。

Nginx

Nginx随着Apache面临着大规模网站的并发问题场景而面世。鉴于这些考虑,Nginx从一开始就被设计为使用异步、非阻塞、事件驱动的连接处理算法。

Nginx产生worker进程,每个进程可以处理数千个连接。worker进程通过实现快速的循环机制来持续检查并处理事件来实现此特性。将实际的工作与连接分离,并允许每个worker仅在新的事件被触发时才去关注自己的连接。

由worker处理的每个连接都被放置在事件循环中,该事件循环与其他连接共用。在循环中,事件以异步方式处理,并允许非阻塞方式工作。当连接关闭,及被移出循环。

这种连接的处理方式允许Nginx在有限资源的情况下进行令人难以置信的扩展。由于服务器是单线程的且新的连接处理无需产生新的进程,因此即使在负载很重的时候,服务器内存与CPU利用率也能保持相对一致。

静态与动态内容对比

就实际使用情况而言,Apache与Nginx的最常见的一项对比在于每个服务器处理静态和动态内容请求的方式。

Apache

Apache服务器可以使用其传统的基于文件的方法来处理静态内容。这些操作的性能表现主要取决于上面所描述MPM方法。

Apache也可以通过嵌入相关语言的处理器到它的worker实例来处理动态内容。这就允许它可以在无需依赖外部组件的情况下,在Web服务器内执行动态内容。可以通过开启动态加载模块来启用这个功能(动态处理器)。

Apache具有在内部处理动态内容的能力意味着动态处理器的配置趋于简单化。通信则不需要借助额外软件协调,并且若内容需求变更,模块可以轻松地被替换。

Nginx

Nginx天生就不具备任何处理动态内容的能力。为了处理PHP和其他动态内容请求,Nginx必须将请求传递给外部处理器执行并等待渲染后的内容返回。最终结果可以被转发至客户端。

对管理员来说,这意味着Nginx必须通过它能识别的协议(http,FastCGI,SCGI,uWSGI,memcache)之一与处理器进行通信。这可能会略感复杂,特别是在尝试预测允许的连接数时,因为每次调用处理器都将造成额外的连接。

然而,这种方式也是有优势的。由于动态解析器并未嵌入在worker进程里,因此它的开销仅存在于动态内容(请求中)。静态内容可以被直接提供,解释器只有在需要时被使用。Apache也可以以这种方式运行,但是这样就失去了上部分描述的优点了。

分布式和集中式配置对比

对于管理员来说,二者最显著的区别之一在于内容目录中是否允许目录级别配置。

Apache

Apache包含一个选项,该选项允许在每个目录的基础上加入额外配置(检查和解析该目录本身内隐藏文件中的指令)。这些(隐藏)文件称之为.htaccess。

由于这些文件存在于内容目录中,当处理请求时,Apache会检查请求目标文件的每个组件中所包含的.htaccess文件并应用该文件中对应的指令。这可以有效地允许将配置分散在Web服务器中,经常用于实现路由重写(URL rewrites)、访问限制(access restrictions)、授权于认证(authorization and authentication)甚至缓存策略(caching policies)。

尽管上述例子可以在Apache主配置文件中设置,.htaccess文件仍然有其他优势。首先,因为这些在请求路径下的文件每次都会被解析,所以在无需重新加载服务器的情况下就能立即生效。其次,它使得允许非特权用户通过控制自身特定层面而无需授权完整的配置文件的权限成为可能。

这为一些Web软件(如内容管理系统)提供了一种简单的方法来配置它们的环境,无需提供对核心配置文件的访问权限。这使得共享主机提供者可以保持对主要配置的控制,而只需给客户端特定目录权限即可。

Nginx

Nginx既不解析.htaccess文件也不提供任何解析主配置文件之外的每个目录配置的机制。这可能不如Apache模型灵活,但是它具有自己的优势。

与.htaccess目录级别配置系统的最显著改进是性能提升。对于一个典型的允许任何目录存在.htaccess文件的Apache设置,服务器将针对每个请求来检查能到达目标文件的各个父级目录下的(.htaccess)文件。若在搜索过程中发现一个或多个.htaccess文件的话,就必须读取并解析它们。通过不允许目录覆盖,Nginx可以只进行单目录查找和文件读取来更快地处理每个请求(假设该文件在常规的目录结构中找到)。

另一个优势与安全性相关。分发目录级别的配置访问权限仍将安全责任分配给独立用户,这些用户能够完好的处理任务也是不被信任的。确保管理员来维护整个Web服务器的控制权可以防止在权限被授予给其他人的情况下的安全性错误发生。

请记住,若这些问题引起你的共鸣,在Apache中是支持关闭.htaccess文件解析的。

文件解析与基于URI解析的对比

Web服务器如何解析请求并映射到系统的实际资源上是这两个服务器另一个不同点。

Apache

Apache提供了将一个请求解释为文件系统上的物理资源或一个需要更抽象评估的URI地址的能力。通常情况下,对于前者Apache使用<Directory><Files>块,而后者利用<Location>来获取更抽象的资源。

由于Apache一开始就是为Web服务器设计的,所以默认情况下请求通常都是被解析成文件系统资源。首先是获取文档根目录,并在主机和端口号后附加请求部分来尝试找到实际文件。基本上,Web上文件系统的层次结构表示为可用的文档树。

虽然Apache具有在底层文件系统和网站空间上运行的能力,但它仍倾向于文件系统方法。这些可以通过一些设计决策来印证,包括基于每个目录配置的.htaccess文件的使用。Apache文档警告称:当请求映射到底层文件系统时,不要使用基于URI块的方式来限制访问。

Nginx

Nginx既是Web服务器也是代理服务器。归根于这两个角色的所需的体系结构,它主要适用于URIs,仅必要时转换为文件系统。

这些可以在一些构造和解析Nginx配置文件的方式中得到印证。Nginx不提供针对文件系统目录的特定配置的机制,取而代之的是解析自身URI。

例如,Nginx的主要配置块是serverlocationserver模块负责解析主机域名部分,而location块负责匹配主机域名及端口之后的URI部分。此时,请求是被解析为URI而不是文件系统上的一个地址。

对于静态文件,所有的请求最终都将被映射至文件系统上的一个地址上。首先,Nginx选择将处理对应请求的server块和location块,然后将根目录与URI进行组合,根据特定的配置调整任何必要的东西。

这个看起来很相似,但是将请求主要解析为URIs而不是文件系统位置,这允许Nginx能够更容易地在Web,邮件和代理服务器角色中起作用。Nginx通过简单的配置来响应不同的请求模式。在准备好为请求提供服务之前,Nginx是不会检查文件系统的,这也就解释了它为什么没有实现以.htaccess文件作为配置的方式。

模块

Nginx和Apache都是通过模块系统进行扩展的,但是二者的工作方式有着显著的差异。

Apache

Apache的模块系统允许你动态加载或卸载模块来满足你在服务器运行期间做出调整的需求。Apache的核心在于它可以一直运行,同时模块可以打开或关闭、添加或移除附加功能并关联至主服务器上。

Apache将这个功能特性运用各种任务中。归因与该平台的成熟性,有许多模块库可供使用。这些库可以被用于改变服务器的一些核心功能,如mod_php,它可以将PHP解析器嵌入至每个运行的worker中。

然而,模块不仅限于处理动态内容。它还能提供其他功能,如可以用于重写路由(rewriting URLs)、客户端认证(authenticating clients)、强化服务器(hardening the server)、日志(logging)、缓存(caching)、压缩(compression)、代理(proxying)、限速(rate limiting)和加密(encrypting)。动态模块可以在无需额外的工作情况下对核心功能进行扩展。

Nginx

Nginx也实现了模块系统,但是与Apache截然不同。在Nginx中,模块不是动态加载的,所以所需模块必须被编译至核心软件中。

对于许多用户来说,这将使得Nginx的灵活性降低。对于那些不习惯在其传统的发行版软件包系统之外维护他们自己编译的软件的用户来说确实如此。虽然发行版的软件包往往都已包含了比较常用的模块,但是如果你需要非标准的模块,则必须自己根据源代码来构建服务器。

尽管如此,Nginx的模块仍是非常有用的,它允许你只需包含你打算使用的功能模块来指示服务器所需内容。一些用户也可能认为这样更安全,因为任何组件都无法直接被关联至服务器。然而,如果你的服务器可以做到这点,那你的服务器大概率已经受损。 Nginx的模块提供着许多与Apache模块相同的功能。如Nginx模块提供代理支持(proxying support)、压缩(compression)、限速(rate limiting)、日志(logging)、重写(rewriting)、地理位置(geolocation)、认证(authentication)、加密(encryption)、流传输(streaming)和邮件(mail)等功能。

支持、兼容性、生态系统与文档

需要考虑的关键点是,启动和运行的实际过程将在其他软件中获得可用怎样的帮助和支持前景。

Apache

由于Apache已经流行很久了,所以对该服务器的支持已相当普遍。有一大堆第一方及第三方文档库,可用于核心服务器和基于任务(Apache与其他软件挂钩使用)的场景。

除文档之外,许多工具和Web项目在Apache环境中包含自行引导工具。这可能会包含在项目自身中或在你发行版软件包团队所维护的包中。

总体来说,Apache仅因为它的市场份额及面世时间久的缘故而获得第三方项目的支持。管理员对Apache有更多的使用经验不是因为它的流行程度,而是因为大多数人是从共享主机场景起步的,这导致几乎完全依赖于Apache的由.htaccess实现的分布式管理能力。

Nginx

Nginx因越来越多的用户采用其性能配置正获得越来越多的支持,但是在一些关键领域仍需赶超。

在过去,因为大多数的早期开发和文档都在俄罗斯,所以很难找到关于Nginx的综合性英文版文档。随着项目的发展兴致的提升,文档已经被添加完毕,且目前在Nginx网站和其他第三方平台上有大量的管理资源。

关于第三方应用程序,支持和文档正变得越来越容易获得,且在某些情况下,包维护者开始为Apache和Nginx的自动配置提供选择。即使没有支持,配置Nginx与可供选择的软件一同工作通常是直截了当的,只要项目自身无需记录其需要内容(如权限和头部信息等)。

Apache与Nginx配合使用

在了解了Apache和Nginx的优点与局限后,你将知道哪个服务器更适合你的需求。然而,许多用户发现可以结合二者各自的强项来共同使用。

一种普遍的结合配置是在Apache之前加入Nginx作为反向代理层。这将允许Nginx处理所有来自客户端的请求。这利用了Nginx的快速处理速度和同时处理大量连接的能力。

对于静态请求,Nginx擅长处理,所以文件将被快速提供并直接返回客户端。对于动态内容,比如PHP文件,Nginx将请求代理至Apache,然后Apache处理结果并返回渲染后页面。最后Nginx可以将内容返回给客户端。

这种设置适用于许多人,因为这过程中的Nginx被作为分拣机功能。它将处理所有请求并可以将它自身不具备处理能力的请求传递给他人来处理。通过减少对Apache服务器的请求处理,我们可以减轻一些由Apache进程或现线程占用导致的阻塞。

这种配置允许你根据需要来添加后台服务器进行扩展。Nginx可以轻松地将配置传递至服务器池,从而提高该配置对故障与性能的恢复能力。

结论

如你所见,Apache和Nginx都是很强大、灵活及功能丰富。确定使用哪个服务器最适合你,主要是评估你的特定需求以及使用你所想看到的模式进行测试。

这两个项目间存在对原始性能、功能性以及对每个解决方案的启动和运行所需要的实现时间产生非常实际的影响的差异。然而,这些通常是一系列不应被忽视的而最终权衡后的结果。最后,并不存在一个适合所有人的Web服务器,所以请使用最符合你目标的解决方案。