Apache和Nginx都屬於Web服務器,二者都實現了HTTP 1.1協議。不管是選擇哪一個,都是根據應用場景來決定的,因此些文件僅從應用場景出發,來對比二者之間的各自特色。要讓正確的工具,作出正確的事。
Web服務器也稱爲WWW(WORLD WIDE WEB)服務器,主要功能是提供網上信息瀏覽服務。php
GET /index.php HTTP/1.1 +---------------+ +----------------+ | +----> | | Browser | | Server | | <----+ | +---------------+ +----------------+ HTTP/1.1 200 OK
Apache HTTP Server是Apache軟件基金會的一個開放源代碼的網頁服務器,能夠在大多數計算機操做系統中運行,因爲其跨平臺和安全性。被普遍使用,是最流行的Web服務器端軟件之一。它快速、可靠而且可經過簡單的API擴充,將Perl/Python等解釋器編譯到服務器中。前端
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
+--------------------------------------------------------------+ | +---------------------+ 啓動階段 | | | 系統啓動, 配置 | | | +----------+----------+ | | | | | +----------v----------+ | | | 模塊的初始化 | | | +-+--------+--------+-+ | | | | | | | +-------------+ | +------v-------+| +--------------+ | | | 子進程初始化 |<+ | 子進程初始化 |+>| 子進程初始化 | | | +------+------+ +-------+------+ +-------+------+ | +--------------------------------------------------------------+ | | | | 運行階段 | | +----v----+ +----v----+ +----v----+ | | | 請求循環 | | 請求循環 | | 請求循環 | | | +----+----+ +----+----+ +----+----+ | | | | | | | +------v------+ +------v------+ +------v------+ | | | 子進程結束 | | 子進程結束 | | 子進程結束 | | | +-------------+ +-------------+ +-------------+ | +--------------------------------------------------------------+
這個生命週期是在perfork工做下的示意,從圖中能夠看出,Apache對於每個請求都要啓動一個單獨的進程來處理。算法
一個單獨的控制進程(父進程)負責產生子進程,這些子進程用於監聽請求並做出應答。Apache老是試圖保持一些備用的 (spare)或是空閒的子進程用於迎接即將到來的請求。這樣客戶端就無需在獲得服務前等候子進程的產生。在Unix系統中,父進程一般以root身份運行以便邦定80端口,而 Apache產生的子進程一般以一個低特權的用戶運行。User和Group指令用於配置子進程的低特權用戶。運行子進程的用戶必需要對他所服務的內容有讀取的權限,可是對服務內容以外的其餘資源必須擁有儘量少的權限。數據庫
每一個進程可以擁有的線程數量是固定的。服務器會根據負載狀況增長或減小進程數量。一個單獨的控制進程(父進程)負責子進程的創建。每一個子進程可以創建ThreadsPerChild數量的服務線程和一個監聽線程,該監聽線程監聽接入請求並將其傳遞給服務線程處理和應答。Apache老是試圖維持一個備用(spare)或是空閒的服務線程池。這樣,客戶端無須等待新線程或新進程的創建便可獲得處理。在Unix中,爲了可以綁定80端口,父進程通常都是以root身份啓動,隨後,Apache以較低權限的用戶創建子進程和線程。User和Group指令用於配置Apache子進程的權限。雖然子進程必須對其提供的內容擁有讀權限,但應該儘量給予他較少的特權。另外,除非使用了suexec ,不然,這些指令配置的權限將被CGI腳本所繼承。apache
這是Apache最新的工做模式,它和worker模式很像,不一樣的是在於它解決了keep-alive長鏈接的時候佔用線程資源被浪費的問題,在event工做模式中,會有一些專門的線程用來管理這些keep-alive類型的線程,當有真實請求過來的時候,將請求傳遞給服務器的線程,執行完畢後,又容許它釋放。這加強了在高併發場景下的請求處理。在*unix系統中的apache2.4版本使用的就是這個模式。後端
在啓動階段,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請求的生命週期
Nginx(發音同engine x)是一款由俄羅斯程序員Igor Sysoev所開發輕量級的網頁服務器、反向代理服務器以及電子郵件(IMAP/POP3)代理服務器。起初是供俄國大型的門戶網站及搜索引擎Rambler(俄語:Рамблер)使用。
Nginx由內核和模塊組成,其中,內核的設計很是微小和簡潔,完成的工做也很是簡單,僅僅經過查找配置文件將客戶端請求映射到一個location block(location是Nginx配置中的一個指令,用於URL匹配),而在這個location中所配置的每一個指令將會啓動不一樣的模塊去完成相應的工做。
+ ^ 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的架構,這個架構相似於Apache的Worker工做狀態,Nginx的每個Worker進程都管理着大量的線程,真正處理請求的是Worker之下的線程。
全部實際上的業務處理邏輯都在worker進程。worker進程中有一個函數,執行無限循環,不斷處理收到的來自客戶端的請求,並進行處理,直到整個nginx服務被中止。Worker中這個函數執行內容以下:
FastCGI是一個可伸縮地、高速地在HTTP server和動態腳本語言間通訊的接口。多數流行的HTTP server都支持FastCGI,包括Apache、Nginx和lighttpd等。同時,FastCGI也被許多腳本語言支持,其中就有PHP。
FastCGI是從CGI發展改進而來的。傳統CGI接口方式的主要缺點是性能不好,由於每次HTTP服務器遇到動態程序時都須要從新啓動腳本解析器來執行解析,而後將結果返回給HTTP服務器。這在處理高併發訪問時幾乎是不可用的。另外傳統的CGI接口方式安全性也不好,如今已經不多使用了。
FastCGI接口方式採用C/S結構,能夠將HTTP服務器和腳本解析服務器分開,同時在腳本解析服務器上啓動一個或者多個腳本解析守護進程。當HTTP服務器每次遇到動態程序時,能夠將其直接交付給FastCGI進程來執行,而後將獲得的結果返回給瀏覽器。這種方式可讓HTTP服務器專注地處理靜態請求或者將動態腳本服務器的結果返回給客戶端,這在很大程度上提升了整個應用系統的性能。
Nginx不支持對外部程序的直接調用或者解析,全部的外部程序(包括PHP)必須經過FastCGI接口來調用。FastCGI接口在Linux下是socket(這個socket能夠是文件socket,也能夠是ip socket)。
Nginx和Apache同樣,都是HTTP服務器軟件,在功能實現上都採用模塊化結構設計,都支持通用的語言接口,如PHP、Perl、Python等,同時還支持正向和反向代理、虛擬主機、URL重寫、壓縮傳輸、SSL加密傳輸等。
因爲Nginx和Apache各自的優點,如今不少人選擇了讓二者在服務器中共存。在服務器端讓Nginx在前,Apache在後。由Nginx作負載均衡和反向代理,而且處理靜態文件,將動態請求(如PHP應用)交給Apache去處理。
做者:未知
原文: https://blog.csdn.net/pkgray/...