关于apache:Web服务器王者之争Apache-vs-Nginx

4次阅读

共计 9930 个字符,预计需要花费 25 分钟才能阅读完成。

Apache 和 Nginx 都属于 Web 服务器,两者都实现了 HTTP 1.1 协定。无论是抉择哪个,都是依据利用场景来决定的,所以些文件仅从利用场景登程,来比照两者之间的各自特点。要让正确的工具,做出正确的事。

Web 服务器

Web 服务器也称为 WWW(WORLD WIDE WEB)服务器,次要性能是提供网上信息浏览服务。

  • 应用层应用 HTTP 协定。
  • HTML 文档格局。
  • 浏览器对立资源定位器(URL)。
Web 服务器经常以 B /S(Browser/Server)形式提供服务。浏览器和服务器的交互方式如下:
 GET /index.php HTTP/1.1
 +---------------+     +----------------+
 |               +---->                 |
 |   Browser     |     |   Server       |
 |               <----+                 |
 +---------------+     +----------------+
               HTTP/1.1 200 OK
  • 浏览器向服务器收回 HTTP 申请(Request)。
  • 服务器收到浏览器的申请数据,通过剖析解决,向浏览器输入响应数据(Response)。
  • 浏览器收到服务器的响应数据,通过剖析解决,将最终结果显示在浏览器中。

Apache

概述

Apache HTTP Server 是 Apache 软件基金会的一个凋谢源代码的网页服务器,能够在大多数计算机操作系统中运行,因为其跨平台和安全性。被宽泛应用,是最风行的 Web 服务器端软件之一。它疾速、牢靠并且可通过简略的 API 裁减,将 Perl/Python 等解释器编译到服务器中。

Apache 组件

Apache 是基于模块化设计的,它的外围代码并不多,大多数的性能都被扩散到各个模块中,各个模块在系统启动的时候按需载入。

 +----------+
      +- | Module   | -----------------+
      |  +----------+                  |
      |                          +------------+
+-----------+   Apache HTTPD     | php module |
| Module    |                    +------------+
+-----------+              +----------+|
      +----------+-------- |  MPM     |+
                 |         +----+---+-+
               +-v-----------+  |   |
               |    ARP      <--+   |
               +------+------+      |
                      |             |
      +---------------v-------------v--+
      |      Operating  System         |
      +--------------------------------+

MPM(Multi -Processing Modules,多重解决模块)是 Apache 的外围组件之一,Apache 通过 MPM 来应用操作系统的资源,对过程和线程池进行治理。Apache 为了可能取得最好的运行性能,针对不同的平台 (Unix/Linux、Window)做了优化,为不同的平台提供了不同的 MPM,用户能够依据理论状况进行抉择,其中最常应用的 MPM 有 prefork 和 worker 两种。至于您的服务器正以哪种形式运行,取决于装置 Apache 过程中指定的 MPM 编译参数, 在 X 零碎上默认的编译参数为 prefork。

因为大多数的 Unix 都不反对真正的线程,所以采纳了预派生子过程 (prefork) 形式,象 Windows 或者 Solaris 这些反对 线程的平台,基于多过程多线程混合的 worker 模式是一种不错的抉择。Apache 中还有一个重要的组件就是 APR(Apache portable Runtime Library),即 Apache 可移植运行库,它是一个对操作系统调用的形象库,用来实现 Apache 外部组件对操作系统的应用,进步零碎的可移植性。Apache 对于 php 的解析,就是通过泛滥 Module 中的 php Module 来实现的。

Apache 生命周期

 +--------------------------------------------------------------+
   |                 +---------------------+       启动阶段        |
   |                 |    系统启动, 配置     |                      |
   |                 +----------+----------+                      |
   |                            |                                 |
   |                 +----------v----------+                      |
   |                 |      模块的初始化     |                      |
   |                 +-+--------+--------+-+                      |
   |                   |        |        |                        |
   |   +-------------+ | +------v-------+| +--------------+       |
   |   | 子过程初始化  |<+ | 子过程初始化   |+>|  子过程初始化  |       |
   |   +------+------+   +-------+------+  +-------+------+       |
   +--------------------------------------------------------------+
   |          |                  |                 |     运行阶段  |
   |     +----v----+        +----v----+       +----v----+         |
   |     | 申请循环 |        |  申请循环 |       | 申请循环 |         |
   |     +----+----+        +----+----+       +----+----+         |
   |          |                  |                 |              |
   |   +------v------+    +------v------+   +------v------+       |
   |   |  子过程完结   |    |  子过程完结  |   |   子过程完结  |       |
   |   +-------------+    +-------------+   +-------------+       |
   +--------------------------------------------------------------+

这个生命周期是在 perfork 工作下的示意,从图中能够看出,Apache 对于每一个申请都要启动一个独自的过程来解决。

Apache 的工作模式

prefork 的工作原理

一个独自的管制过程 (父过程) 负责产生子过程,这些子过程用于监听申请并作出应答。Apache 总是试图放弃一些备用的 (spare)或是闲暇的子过程用于迎接行将到来的申请。这样客户端就无需在失去服务前等待子过程的产生。在 Unix 零碎中,父过程通常以 root 身份运行以便邦定 80 端口,而 Apache 产生的子过程通常以一个低特权的用户运行。User 和 Group 指令用于配置子过程的低特权用户。运行子过程的用户必须要对他所服务的内容有读取的权限,然而对服务内容之外的其余资源必须领有尽可能少的权限。

worker 的工作原理

每个过程可能领有的线程数量是固定的。服务器会依据负载状况减少或缩小过程数量。一个独自的管制过程 (父过程) 负责子过程的建设。每个子过程可能建设 ThreadsPerChild 数量的服务线程和一个监听线程,该监听线程监听接入申请并将其传递给服务线程解决和应答。Apache 总是试图维持一个备用 (spare) 或是闲暇的服务线程池。这样,客户端毋庸期待新线程或新过程的建设即可失去解决。在 Unix 中,为了可能绑定 80 端口,父过程个别都是以 root 身份启动,随后,Apache 以较低权限的用户建设子过程和线程。User 和 Group 指令用于配置 Apache 子过程的权限。尽管子过程必须对其提供的内容领有读权限,但应该尽可能给予他较少的特权。另外,除非应用了 suexec,否则,这些指令配置的权限将被 CGI 脚本所继承。

Event MPM

这是 Apache 最新的工作模式,它和 worker 模式很像,不同的是在于它解决了 keep-alive 长连贯的时候占用线程资源被节约的问题,在 event 工作模式中,会有一些专门的线程用来治理这些 keep-alive 类型的线程,当有实在申请过去的时候,将申请传递给服务器的线程,执行结束后,又容许它开释。这加强了在高并发场景下的申请解决。在 *unix 零碎中的 apache2.4 版本应用的就是这个模式。

Apache 的运行

启动阶段

在启动阶段,Apache 次要进行配置文件解析 (例如 http.conf 以及 Include 指令设定的配置文件等)、模块加载(例如 mod_php.so,mod_perl.so 等) 和系统资源初始化(例如日志文件、共享内存段等)工作。在这个阶段,Apache 为了取得系统资源最大的应用权限,将以特权用户 root(X 零碎)或超级管理员 administrator(Windows 零碎)实现启动。

这个过程能够通过下图来深刻理解:
 +--------+
       |  开始   |
       +----+---+
            |
 +----------v------------+   解析主配置文件 http.conf 中配置信息,|     解析配置文件        |   像 LoadModule, AddType
 +----------+------------+   等指令被加载至内存
            |
 +----------v------------+   根据 AddModule, LoadModule 等指令
 |   加载动态 / 动静模块      |   加载 Apache 模块,像 mod_php5.so 被
 +----------+------------+   加载至内存,映射到 Apache 地址空间。|
 +----------v------------+   日志文件、共享内存段,数据库链接
 |     系统资源初始化      |    等初始化
 +----------+------------+
            |
        +---v----+
        |  完结   |
        +--------+
运行阶段

在运行阶段,Apache 次要工作是解决用户的服务申请。在这个阶段,Apache 放弃特权用户级别,应用一般权限,这次要是基于安全性的思考,避免因为代码的缺点引起的安全漏洞。

因为 Apache 的 Hook 机制,Apache 容许模块 (包含外部模块和内部模块,例如 mod_php5.so,mod_perl.so 等) 将自定义的函数注入到申请解决循环中。mod_php5.so/php5apache2.dll 就是将所蕴含的自定义函数,通过 Hook 机制注入到 Apache 中,在 Apache 解决流程的各个阶段负责解决 php 申请。

Apache 将申请解决循环分为 11 个阶段,顺次是:Post-Read-Request,URI Translation,Header Parsing,Access Control,Authentication,Authorization,MIME Type Checking,FixUp,Response,Logging,CleanUp。

Apache 解决 http 申请的生命周期:

Apache 解决 http 申请的生命周期

  1. Post-Read-Request 阶段: 在失常申请解决流程中,这是模块能够插入钩子的第一个阶段。对于那些想很早进入解决申请的模块来说,这个阶段能够被利用。
  2. URI Translation 阶段 : Apache 在本阶段的次要工作:将申请的 URL 映射到本地文件系统。模块能够在这阶段插入钩子,执行本人的映射逻辑。mod_alias 就是利用这个阶段工作的。
  3. Header Parsing 阶段 : Apache 在本阶段的次要工作:查看申请的头部。因为模块能够在申请解决流程的任何一个点上执行查看申请头部的工作,因而这个钩子很少被应用。mod_setenvif 就是利用这个阶段工作的。
  4. Access Control 阶段 : Apache 在本阶段的次要工作:依据配置文件查看是否容许拜访申请的资源。Apache 的规范逻辑实现了容许和回绝指令。mod_authz_host 就是利用这个阶段工作的。
  5. Authentication 阶段 : Apache 在本阶段的次要工作:依照配置文件设定的策略对用户进行认证,并设定用户名区域。模块能够在这阶段插入钩子,实现一个认证办法。
  6. Authorization 阶段 : Apache 在本阶段的次要工作:依据配置文件查看是否容许认证过的用户执行申请的操作。模块能够在这阶段插入钩子,实现一个用户权限治理的办法。
  7. MIME Type Checking 阶段 : Apache 在本阶段的次要工作:依据申请资源的 MIME 类型的相干规定,断定将要应用的内容处理函数。规范模块 mod_negotiation 和 mod_mime 实现了这个钩子。
  8. FixUp 阶段 : 这是一个通用的阶段,容许模块在内容生成器之前,运行任何必要的解决流程。和 Post_Read_Request 相似,这是一个可能捕捉任何信息的钩子,也是最常应用的钩子。
  9. Response 阶段 : Apache 在本阶段的次要工作:生成返回客户端的内容,负责给客户端发送一个失当的回复。这个阶段是整个解决流程的外围局部。
  10. Logging 阶段 : Apache 在本阶段的次要工作:在回复曾经发送给客户端之后记录事务。模块可能批改或者替换 Apache 的规范日志记录。
  11. CleanUp 阶段 : Apache 在本阶段的次要工作:清理本次申请事务处理实现之后遗留的环境,比方文件、目录的解决或者 Socket 的敞开等等,这是 Apache 一次申请解决的最初一个阶段。

Nginx

概述

Nginx(发音同 engine x)是一款由俄罗斯程序员 Igor Sysoev 所开发轻量级的网页服务器、反向代理服务器以及电子邮件(IMAP/POP3)代理服务器。起初是供俄国大型的门户网站及搜索引擎 Rambler(俄语:Рамблер)应用。

Nginx 的模块与工作原理

Nginx 由内核和模块组成,其中,内核的设计十分渺小和简洁,实现的工作也非常简单,仅仅通过查找配置文件将客户端申请映射到一个 location block(location 是 Nginx 配置中的一个指令,用于 URL 匹配),而在这个 location 中所配置的每个指令将会启动不同的模块去实现相应的工作。

Nginx 的模块从构造上分为外围模块、根底模块和第三方模块:
  • 外围模块:HTTP 模块、EVENT 模块和 MAIL 模块
  • 根底模块:HTTP Access 模块、HTTP FastCGI 模块、HTTP Proxy 模块和 HTTP Rewrite 模块,
  • 第三方模块:HTTP Upstream Request Hash 模块、Notice 模块和 HTTP Access Key 模块。
Nginx 的模块从性能上分为如下三类:
  • Handlers(处理器模块)。此类模块间接解决申请,并进行输入内容和批改 headers 信息等操作。Handlers 处理器模块个别只能有一个。
  • Filters(过滤器模块)。此类模块次要对其余处理器模块输入的内容进行批改操作,最初由 Nginx 输入。
  • Proxies(代理类模块)。此类模块是 Nginx 的 HTTP Upstream 之类的模块,这些模块次要与后端一些服务比方 FastCGI 等进行交互,实现服务代理和负载平衡等性能。
 +                    ^
        Http Request |                    |  Http Response
                     |                    |
    +---------+------v-----+         +----+----+
    |  Conf   | Nginx Core |         | FilterN |
    +---------+------+-----+         +----^----+
                     |                    |
                     |               +----+----+
                     |               | Filter2 |
choose a handler     |               +----^----+
based conf           |                    |
                     |               +----+----+
                     |               | Filter1 |
                     |               +----^----+
                     |                    | Generate content
               +-----v--------------------+----+
               |           Handler             |
               +-------------------------------+

Nginx 自身做的工作理论很少,当它接到一个 HTTP 申请时,它仅仅是通过查找配置文件将此次申请映射到一个 location block,而此 location 中所配置的各个指令则会启动不同的模块去实现工作,因而模块能够看做 Nginx 真正的劳动工作者。通常一个 location 中的指令会波及一个 handler 模块和多个 filter 模块(当然,多个 location 能够复用同一个模块)。handler 模块负责解决申请,实现响应内容的生成,而 filter 模块对响应内容进行解决。

Nginx 架构及工作流程

Nginx 架构

上图是 Nginx 的架构,这个架构相似于 Apache 的 Worker 工作状态,Nginx 的每一个 Worker 过程都治理着大量的线程,真正解决申请的是 Worker 之下的线程。

所有实际上的业务解决逻辑都在 worker 过程。worker 过程中有一个函数,执行有限循环,一直解决收到的来自客户端的申请,并进行解决,直到整个 nginx 服务被进行。Worker 中这个函数执行内容如下:

  • 操作系统提供的机制(例如 epoll, kqueue 等)产生相干的事件。
  • 接管和解决这些事件,如是承受到数据,则产生更高层的 request 对象。
  • 解决 request 的 header 和 body。
  • 产生响应,并发送回客户端。
  • 实现 request 的解决。
  • 从新初始化定时器及其他事件。

Nginx 和 FastCGI

FastCGI

FastCGI 是一个可伸缩地、高速地在 HTTP server 和动静脚本语言间通信的接口。少数风行的 HTTP server 都反对 FastCGI,包含 Apache、Nginx 和 lighttpd 等。同时,FastCGI 也被许多脚本语言反对,其中就有 PHP。

FastCGI 是从 CGI 倒退改良而来的。传统 CGI 接口方式的次要毛病是性能很差,因为每次 HTTP 服务器遇到动静程序时都须要重新启动脚本解析器来执行解析,而后将后果返回给 HTTP 服务器。这在解决高并发拜访时简直是不可用的。另外传统的 CGI 接口方式安全性也很差,当初曾经很少应用了。

FastCGI 接口方式采纳 C / S 构造,能够将 HTTP 服务器和脚本解析服务器离开,同时在脚本解析服务器上启动一个或者多个脚本解析守护过程。当 HTTP 服务器每次遇到动静程序时,能够将其间接交付给 FastCGI 过程来执行,而后将失去的后果返回给浏览器。这种形式能够让 HTTP 服务器专一地解决动态申请或者将动静脚本服务器的后果返回给客户端,这在很大水平上进步了整个利用零碎的性能。

Nging 和 FastCGI 单干

Nginx 不反对对外部程序的间接调用或者解析,所有的内部程序(包含 PHP)必须通过 FastCGI 接口来调用。FastCGI 接口在 Linux 下是 socket(这个 socket 能够是文件 socket,也能够是 ip socket)。

接下来以 Nginx 下 PHP 的运行过程来阐明。PHP-FPM 是治理 FastCGI 的一个管理器,它作为 PHP 的插件存在。
  • FastCGI 过程管理器 php-fpm 本身初始化,启动主过程 php-fpm 和启动 start_servers 个 CGI 子过程。主过程 php-fpm 次要是治理 fastcgi 子过程,监听 9000 端口。fastcgi 子过程期待来自 Web Server 的连贯。
  • 当客户端申请达到 Web Server Nginx 是时,Nginx 通过 location 指令,将所有以 php 为后缀的文件都交给 127.0.0.1:9000 来解决,即 Nginx 通过 location 指令,将所有以 php 为后缀的文件都交给 127.0.0.1:9000 来解决。
  • FastCGI 过程管理器 PHP-FPM 抉择并连贯到一个子过程 CGI 解释器。Web server 将 CGI 环境变量和规范输出发送到 FastCGI 子过程。
  • FastCGI 子过程实现解决后将规范输入和错误信息从同一连贯返回 Web Server。当 FastCGI 子过程敞开连贯时,申请便告解决实现。
  • FastCGI 子过程接着期待并解决来自 FastCGI 过程管理器(运行在 WebServer 中)的下一个连贯。

Apache 和 Nginx 比拟

性能比照

Nginx 和 Apache 一样,都是 HTTP 服务器软件,在性能实现上都采纳模块化结构设计,都反对通用的语言接口,如 PHP、Perl、Python 等,同时还反对正向和反向代理、虚拟主机、URL 重写、压缩传输、SSL 加密传输等。

  • 在性能实现上,Apache 的所有模块都反对动、动态编译,而 Nginx 模块都是动态编译的,
  • 对 FastCGI 的反对,Apache 对 Fcgi 的反对不好,而 Nginx 对 Fcgi 的反对十分好;
  • 在解决连贯形式上,Nginx 反对 epoll,而 Apache 却不反对;
  • 在空间应用上,Nginx 安装包仅仅只有几百 K,和 Nginx 比起来 Apache 相对是硕大无朋。

Nginx 绝对 apache 的长处

  • 轻量级,同样起 web 服务,比 apache 占用更少的内存及资源
  • 动态解决,Nginx 动态解决性能比 Apache 高 3 倍以上
  • 抗并发,nginx 解决申请是异步非阻塞的,而 apache 则是阻塞型的,在高并发下 nginx 能放弃低资源低消耗高性能。在 - – Apache+PHP(prefork)模式下,如果 PHP 解决慢或者前端压力很大的状况下,很容易呈现 Apache 过程数飙升,从而拒绝服务的景象。
  • 高度模块化的设计,编写模块绝对简略
  • 社区沉闷,各种高性能模块出品迅速啊

apache 绝对 nginx 的长处

  • rewrite,比 nginx 的 rewrite 弱小
  • 模块超多,根本想到的都能够找到
  • 少 bug,nginx 的 bug 绝对较多
  • 超稳定
  • Apache 对 PHP 反对比较简单,Nginx 须要配合其余后端用
抉择 Nginx 的劣势所在
  • 作为 Web 服务器: Nginx 解决动态文件、索引文件,主动索引的效率十分高。
  • 作为代理服务器,Nginx 能够实现无缓存的反向代理减速,进步网站运行速度。
  • 作为负载平衡服务器,Nginx 既能够在外部间接反对 Rails 和 PHP,也能够反对 HTTP 代理服务器对外进行服务,同时还反对简略的容错和利用算法进行负载平衡。
  • 在性能方面,Nginx 是专门为性能优化而开发的,在实现上十分重视效率。它采纳内核 Poll 模型(epoll and kqueue),能够反对更多的并发连贯,最大能够反对对 50 000 个并发连接数的响应,而且只占用很低的内存资源。
  • 在稳定性方面,Nginx 采取了分阶段资源分配技术,使得 CPU 与内存的占用率非常低。Nginx 官网示意,Nginx 放弃 10 000 个没有流动的连贯,而这些连贯只占用 2.5MB 内存,因而,相似 DOS 这样的攻打对 Nginx 来说基本上是没有任何作用的。
  • 在高可用性方面,Nginx 反对热部署,启动速度特地迅速,因而能够在不间断服务的状况下,对软件版本或者配置进行降级,即便运行数月也无需重新启动,简直能够做到 7×24 小时不间断地运行。

同时应用 Nginx 和 Apache

因为 Nginx 和 Apache 各自的劣势,当初很多人抉择了让两者在服务器中共存。在服务器端让 Nginx 在前,Apache 在后。由 Nginx 做负载平衡和反向代理,并且解决动态文件,将动静申请(如 PHP 利用)交给 Apache 去解决。

作者:未知
原文:https://blog.csdn.net/pkgray/…

正文完
 0