1.Apache概述
??Apache是目前世界上使用最為廣泛的一種Web Server薄疚,它以跨平臺碧信、高效和穩(wěn)定而聞名。
??Apache并不是沒有缺點街夭,它最為詬病的一點就是變得越來越重砰碴,越來越復雜,被普遍認為是重量級的 WebServer板丽。而且Apache的server為process-based server ,也就是基于多進程的HTTP服務器呈枉,它需要對每個用戶請求創(chuàng)建一個子進程進行響應,這樣的缺點是埃碱,如果并發(fā)的請求非常多(在大型門戶網(wǎng)站很常見)猖辫,就會需要非常多的進程,從而占用極多的cpu資源和內(nèi)存砚殿。因此對于并發(fā)處理不是Apache的強項啃憎。
??使用另一種webServer,叫做asynchronous servers 異步服務器瓮具,比如lighttpd,nginx等等荧飞,這些WebServer的優(yōu)點是運行效率很 高,但缺點也很明顯名党,成熟度往往要低于Apache叹阔。
2.Apache組件邏輯圖
??Apache是基于模塊化設計的,總體上看起來代碼的可讀性高于php的代碼传睹,它的核心代碼 并不多耳幢,大多數(shù)的功能都被分散到各個模塊中,各個模塊在系統(tǒng)啟動的時候按需載入。你如果想要閱讀Apache的源代碼睛藻,建議你直接從main.c文件讀起启上,系統(tǒng)最主要的處理邏輯都包含在里面。
??MPM(Multi -Processing Modules店印,多重處理模塊)是Apache的核心組件之 一冈在,Apache通過MPM來使用操作系統(tǒng)的資源,對進程和線程池進行管理按摘。
??Apache為了能夠獲得最好的運行性能包券,針對不同的平臺 (Unix/Linux、Window)做了優(yōu)化炫贤,為不同的平臺提供了不同的MPM溅固,用戶可以根據(jù)實際情況進行選擇,其中最常使用的MPM有 prefork兰珍、worker 和event三種侍郭。至于您的服務器正以哪種方式運行,取決于安裝Apache過程中指定的MPM編譯參數(shù),在X系統(tǒng)上默認的編譯參數(shù)為 prefork掠河。由于大多數(shù)的Unix都不支持真正的線程亮元,取決于平臺特性, 選擇prefork或worker 。 Windows是支持線程的平臺口柳,針對Windows平臺采用Windows NT優(yōu)化的多處理模塊mpm_winnt苹粟。對此感興趣的同學可以閱讀有關資料,此處不再多講跃闹。
??Apache中還有一個重要的 組件就是APR(Apache portable Runtime Library),即Apache可移植運行庫毛好,它是一個對操作系統(tǒng)調(diào)用的抽象庫望艺,用來實現(xiàn)Apache內(nèi)部組件對操作系統(tǒng)的使用,提高系統(tǒng)的可移植性肌访。
??Apache對于php的解析找默,就是通過眾多Module中的php Module來完成的。
3.Apache的生命周期圖
4. Apache的三種工作模式
??Apache服務的三種工作模式:prefork吼驶、worker和event惩激。
prefork的工作原理及配置
工作原理:
??一個單獨的控制進程(父進程)負責產(chǎn)生子進程,這些子進程用于監(jiān)聽請求并作出應答蟹演。Apache總是試圖保持一些備用的 (spare)或是空閑的子進程用于迎接即將到來的請求风钻。這樣客戶端就無需在得到服務前等候子進程的產(chǎn)生。在Unix系統(tǒng)中酒请,父進程通常以root身份運行以便邦定80端口骡技,而 Apache產(chǎn)生的子進程通常以一個低特權的用戶運行。User和Group指令用于配置子進程的低特權用戶。運行子進程的用戶必須要對他所服務的內(nèi)容有讀取的權限布朦,但是對服務內(nèi)容之外的其他資源必須擁有盡可能少的權限囤萤。
??這樣可以減少頻繁創(chuàng)建和銷毀進程的開銷,每個子進程只有一個線程是趴,在一個時間點內(nèi)涛舍,只能處理一個請求。這是一個成熟穩(wěn)定唆途,可以兼容新老模塊做盅,也不需要擔心線程安全問題,但是一個進程相對占用資源窘哈,消耗大量內(nèi)存吹榴,不擅長處理高并發(fā)的場景。
配置說明:
如何配置在Apache的配置文件httpd.conf的配置方式:
<IfModule mpm_prefork_module>
StartServers 5
MinSpareServers 5
MaxSpareServers 10
MaxRequestWorkers 250
MaxConnectionsPerChild 1000
</IfModule>
- StartServers ?服務器啟動時建立的子進程數(shù)量滚婉,默認是5個
- MinSpareServers ?空閑子進程的最小數(shù)量图筹,默認5個;如果當前空閑子進程數(shù)少于MinSpareServers 让腹,那么Apache將以最大每秒一個的速度產(chǎn)生新的子進程远剩。此參數(shù)不要設的太大。
- MaxSpareServers ? 空閑子進程的最大數(shù)量骇窍,默認10瓜晤;如果當前有超過MaxSpareServers數(shù)量的空閑子進程,那么父進程會殺死多余的子進程腹纳。次參數(shù)也不需要設置太大痢掠,如果你將其設置比MinSpareServers 小,Apache會自動將其修改為MinSpareServers +1的數(shù)量嘲恍。
- MaxRequestWorkers ?限定服務器同一時間內(nèi)客戶端最大接入的請求數(shù)量足画,默認是256;任何超過了MaxRequestWorkers限制的請求都要進入等待隊列佃牛,一旦一個個連接被釋放淹辞,隊列中的請求才將得到服務,如果要增大這個數(shù)值俘侠,必須先增大ServerLimit象缀。在Apache2.3.1版本之前這參數(shù)MaxRequestWorkers被稱為MaxClients。
- MaxConnectionsPerChild ? 每個子進程在其生命周期內(nèi)允許最大的請求數(shù)量爷速,如果請求總數(shù)已經(jīng)達到這個數(shù)值央星,子進程將會結束,如果設置為0遍希,子進程將永遠不會結束等曼。在Apache2.3.9之前稱之為MaxRequestsPerChild。
worker的工作原理及配置
工作原理:
和prefork模式相比,worker使用了多進程和多線程的混合模式禁谦,worker模式也同樣會先預派生一些子進程胁黑,然后每個子進程創(chuàng)建一些線程州泊,同時包括一個監(jiān)聽線程丧蘸,每個請求過來會被分配到一個線程來服務。線程比起進程會更輕量遥皂,因為線程是通過共享父進程的內(nèi)存空間力喷,因此,內(nèi)存的占用會減少一些演训,在高并發(fā)的場景下會比prefork有更多可用的線程弟孟,表現(xiàn)會更優(yōu)秀一些;另外样悟,如果一個線程出現(xiàn)了問題也會導致同一進程下的線程出現(xiàn)問題拂募,如果是多個線程出現(xiàn)問題,也只是影響Apache的一部分窟她,而不是全部陈症。由于用到多進程多線程,需要考慮到線程的安全了震糖,在使用keep-alive長連接的時候录肯,某個線程會一直被占用,即使中間沒有請求吊说,需要等待到超時才會被釋放(該問題在prefork模式下也存在)论咏。
配置說明:
配置在Apache的配置文件httpd.conf的配置方式:
<IfModule mpm_worker_module>
StartServers 3
ServerLimit 16
MinSpareThreads 75
MaxSpareThreads 250
ThreadsPerChild 25
MaxRequestWorkers 400
MaxConnectionsPerChild 1000
</IfModule>
- StartServers 服務器啟動時建立的子進程數(shù)量,在workers模式下默認是3個.
- ServerLimit系統(tǒng)配置的最大進程數(shù)量
- MinSpareThreads空閑子進程的最小數(shù)量,默認75
- MaxSpareThreads 空閑子進程的最大數(shù)量疏叨,默認250
- ThreadsPerChild 每個子進程產(chǎn)生的線程數(shù)量潘靖,默認是64
- MaxRequestWorkers /MaxClients 限定服務器同一時間內(nèi)客戶端最大接入的請求數(shù)量.
- MaxConnectionsPerChild 每個子進程在其生命周期內(nèi)允許最大的請求數(shù)量,如果請求總數(shù)已經(jīng)達到這個數(shù)值蚤蔓,子進程將會結束,如果設置為0糊余,子進程將永遠不會結束秀又。在Apache2.3.9之前稱之為MaxRequestsPerChild。
這里建議設置為非零贬芥,注意原因:
1)能夠防止(偶然的)內(nèi)存泄漏無限進行吐辙,從而耗盡內(nèi)存。
2)給進程一個有限壽命蘸劈,從而有助于當服務器負載減輕的時候減少活動進程的數(shù)量(重生的機會)昏苏。
Worker模式下所能同時處理的請求總數(shù)是由子進程總數(shù)乘以ThreadsPerChild 值決定的,應該大于等于MaxRequestWorkers。如果負載很大贤惯,現(xiàn)有的子進程數(shù)不能滿足時洼专,控制進程會派生新的子進程。默認最大的子進程總數(shù)是16孵构,加大時 也需要顯式聲明ServerLimit(最大值是20000)屁商。需要注意的是,如果顯式聲明了ServerLimit颈墅,那么它乘以 ThreadsPerChild的值必須大于等于MaxRequestWorkers蜡镶,而且MaxRequestWorkers必須是ThreadsPerChild的整數(shù)倍,否則 Apache將會自動調(diào)節(jié)到一個相應值恤筛。
event的工作原理及配置
工作原理:
這是Apache最新的工作模式官还,它和worker模式很像,不同的是在于它解決了keep-alive長連接的時候占用線程資源被浪費的問題毒坛,在event工作模式中望伦,會有一些專門的線程用來管理這些keep-alive類型的線程,當有真實請求過來的時候粘驰,將請求傳遞給服務器的線程屡谐,執(zhí)行完畢后,又允許它釋放蝌数。這增強了在高并發(fā)場景下的請求處理愕掏。
配置說明:
配置在Apache的配置文件httpd.conf的配置方式:
<IfModule mpm_event_module>
StartServers 3
ServerLimit 16
MinSpareThreads 75
MaxSpareThreads 250
ThreadsPerChild 25
MaxRequestWorkers 400
MaxConnectionsPerChild 1000
</IfModule>
- StartServers 服務器啟動時建立的子進程數(shù)量,在workers模式下默認是3個.
- ServerLimit系統(tǒng)配置的最大進程數(shù)量
- MinSpareThreads空閑子進程的最小數(shù)量,默認75
- MaxSpareThreads 空閑子進程的最大數(shù)量顶伞,默認250
- ThreadsPerChild 每個子進程產(chǎn)生的線程數(shù)量饵撑,默認是64
- MaxRequestWorkers /MaxClients 限定服務器同一時間內(nèi)客戶端最大接入的請求數(shù)量.
- MaxConnectionsPerChild 每個子進程在其生命周期內(nèi)允許最大的請求數(shù)量,如果請求總數(shù)已經(jīng)達到這個數(shù)值唆貌,子進程將會結束滑潘,如果設置為0,子進程將永遠不會結束锨咙。
5.Apache的運行
Apache運行分為啟動階段和運行階段语卤。
5.1 啟動階段
在啟動階段,Apache主要進行配置文件解析(例如http.conf
以及Include
指令設定的配置文件等)酪刀、模塊加載(例如mod_php.so,mod_perl.so
等)和系統(tǒng)資源初始化(例如日志文件粹舵、共享內(nèi)存段等)工作。
在這個階段骂倘,Apache為了獲得系統(tǒng)資源最大的使用權限眼滤,將以特權用戶root(X系統(tǒng))或超級管理員administrator(Windows系統(tǒng))完成啟動。
Apache中的“php解釋器”的裝配過程就是在這個階段完成的历涝∽缧瑁“php解釋器”就是負責解釋和執(zhí)行你的php代碼的系統(tǒng)模塊漾唉。這塊兒會在PHP底層講解。
把php最終集成到Apache系統(tǒng)中堰塌,還需要對Apache進行一些必要的設置赵刑。這里,我們就以php的mod_php5 SAPI運行模式為例進行講解蔫仙,至于SAPI這個概念后面我們還會詳細講解料睛。
假定我們安裝的版本是Apache2 和 Php5,那么需要編輯Apache的主配置文件http.conf
摇邦,在其中加入下面的幾行內(nèi)容:
Unix/Linux環(huán)境下:
LoadModule php5_module modules/mod_php5.so
AddType application/x-httpd-php .php
注:其中
modules/mod_php5.so
是X系統(tǒng)環(huán)境下mod_php5.so
文件的安裝位置恤煞。
Windows環(huán)境下:
LoadModule php5_module d:/php/php5apache2.dll
AddType application/x-httpd-php .php
注:其中
d:/php/php5apache2.dll
是在Windows環(huán)境下php5apache2.dll
文件的安裝位置。
這兩項配置就是告訴Apache Server施籍,通過URL收到的用戶請求居扒,凡是以php作為后綴,就需要調(diào)用php5_module模塊(mod_php5.so/ php5apache2.dll
)進行處理丑慎。
這個過程可以參考以下的示意圖:
注:在unix/linux下, so后綴文件是一個DSO文件喜喂,
DSO
與windows系統(tǒng)下的dll
是等價概念,都是把一堆函數(shù)封裝在一個二進制文件中竿裂。調(diào)用它們的進程把它們裝入內(nèi)存后玉吁,會將其映射到自己的地址空間。
DSO全稱為Dynamic Shared Object
腻异,即動態(tài)共享對象进副。DLL全稱為Dynamic Link Library
即動態(tài)鏈接庫。
Apache 服務器的體系結構的最大特點悔常,就是高度模塊化影斑。如果你為了追求處理效率,可以把這些dso
模塊在apache編譯的時候靜態(tài)鏈入机打,這樣會提高Apache 5%左右的處理性能矫户。
5.2運行階段
運行階段概述
在運行階段,Apache主要工作是處理用戶的服務請求残邀。
在這個階段皆辽,Apache放棄特權用戶級別,使用普通權限芥挣,這主要是基于安全性的考慮膳汪,防止由于代碼的缺陷引起的安全漏洞。像微軟的IIS就曾遭受“紅色代碼(Code Red)”和“尼姆達(Nimda)”等惡意代碼的溢出攻擊九秀。
運行階段流程
Apache將請求處理循環(huán)分為以下11個階段:
- 1、Post-Read-Request階段
??在正常請求處理流程中粘我,這是模塊可以插入鉤子的第一個階段鼓蜒。對于那些想很早進入處理請求的模塊來說痹换,這個階段可以被利用。
2都弹、URI Translation階段
??Apache在本階段的主要工作:將請求的URL映射到本地文件系統(tǒng)娇豫。模塊可以在這階段插入鉤子,執(zhí)行自己的映射邏輯畅厢。mod_alias就是利用這個階段工作的冯痢。3、Header Parsing階段
??Apache在本階段的主要工作:檢查請求的頭部框杜。由于模塊可以在請求處理流程的任何一個點上執(zhí)行檢查請求頭部的任務浦楣,因此這個鉤子很少被使用。mod_setenvif就是利用這個階段工作的咪辱。4振劳、Access Control階段
??Apache在本階段的主要工作:根據(jù)配置文件檢查是否允許訪問請求的資源。Apache的標準邏輯實現(xiàn)了允許和拒絕指令油狂。mod_authz_host就是利用這個階段工作的历恐。5、Authentication階段
??Apache在本階段的主要工作:按照配置文件設定的策略對用戶進行認證专筷,并設定用戶名區(qū)域弱贼。模塊可以在這階段插入鉤子,實現(xiàn)一個認證方法磷蛹。6吮旅、Authorization階段
??Apache在本階段的主要工作:根據(jù)配置文件檢查是否允許認證過的用戶執(zhí)行請求的操作。模塊可以在這階段插入鉤子弦聂,實現(xiàn)一個用戶權限管理的方法鸟辅。7、MIME Type Checking階段
??Apache在本階段的主要工作:根據(jù)請求資源的MIME類型的相關規(guī)則莺葫,判定將要使用的內(nèi)容處理函數(shù)匪凉。標準模塊mod_negotiation和mod_mime實現(xiàn)了這個鉤子。8捺檬、FixUp階段
??這是一個通用的階段再层,允許模塊在內(nèi)容生成器之前,運行任何必要的處理流程堡纬。和Post_Read_Request類似聂受,這是一個能夠捕獲任何信息的鉤子,也是最常使用的鉤子烤镐。9蛋济、Response階段
??Apache在本階段的主要工作:生成返回客戶端的內(nèi)容,負責給客戶端發(fā)送一個恰當?shù)幕貜团谝丁_@個階段是整個處理流程的核心部分碗旅。10渡处、Logging階段
??Apache在本階段的主要工作:在回復已經(jīng)發(fā)送給客戶端之后記錄事務。模塊可能修改或者替換Apache的標準日志記錄祟辟。11医瘫、CleanUp階段
??Apache在本階段的主要工作:清理本次請求事務處理完成之后遺留的環(huán)境,比如文件旧困、目錄的處理或者Socket的關閉等等醇份,這是Apache一次請求處理的最后一個階段。