Web服務器王者之爭:Apache vs Nginx

Apache和Nginx都屬於Web服務器,二者都實現了HTTP 1.1協議。不管是選擇哪一個,都是根據應用場景來決定的,因此些文件僅從應用場景出發,來對比二者之間的各自特色。要讓正確的工具,作出正確的事。

Web服務器

Web服務器也稱爲WWW(WORLD WIDE WEB)服務器,主要功能是提供網上信息瀏覽服務。php

  • 應用層使用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是基於模塊化設計的,它的核心代碼並很少,大多數的功能都被分散到各個模塊中,各個模塊在系統啓動的時候按需載入。nginx

+----------+
      +- | 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來完成的。web

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腳本所繼承。apache

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/...

image

相關文章
相關標籤/搜索