一般來(lái)說(shuō),WinNT系統(tǒng)下使用IIS,而Apache在Linux下應(yīng)用的比較多,但是依然有很多人在WinNT系統(tǒng)下使用Apache而非IIS,可能是基于對(duì)Windows系統(tǒng)的熟悉吧。今天就來(lái)說(shuō)一下在Windows系統(tǒng)下如果優(yōu)化Apache的性能。 mpm_winnt.c 是專門(mén)針對(duì)Windows NT優(yōu)化的MPM(多路處理模塊),它使用一個(gè)單獨(dú)的父進(jìn)程產(chǎn)生一個(gè)單獨(dú)的子進(jìn)程,在這個(gè)子進(jìn)程中輪流產(chǎn)生多個(gè)線程來(lái)處理請(qǐng)求。也就是說(shuō) mpm_winnt只能啟動(dòng)父子兩個(gè)進(jìn)程, 不能像Linux下那樣同時(shí)啟動(dòng)多個(gè)進(jìn)程。 mpm_winnt主要通過(guò)ThreadsPerChild和MaxRequestsPerChild兩個(gè)參數(shù)來(lái)優(yōu)化Apache,下面詳細(xì)來(lái)說(shuō)明一下。ThreadsPerChild 這個(gè)參數(shù)用于設(shè)置每個(gè)進(jìn)程的線程數(shù), 子進(jìn)程在啟動(dòng)時(shí)建立這些線程后就不再建立新的線程了. 一方面因?yàn)閙pm_winnt不能啟動(dòng)多個(gè)進(jìn)程, 所以這個(gè)數(shù)值要足夠大,以便可以處理可能的請(qǐng)求高峰; 另一方面該參數(shù)以服務(wù)器的響應(yīng)速度為準(zhǔn)的, 數(shù)目太大的反而會(huì)變慢。因此需要綜合均衡一個(gè)合理的數(shù)值。
mpm_winnt上的默認(rèn)值是64, 最大值是1920. 這里建議設(shè)置為100-500之間,服務(wù)器性能高的話值大一些,反之值小一些。
MaxRequestsPerChild 該參數(shù)表示每個(gè)子進(jìn)程能夠處理的最大請(qǐng)求數(shù), 即同時(shí)間內(nèi)子進(jìn)程數(shù)目.設(shè)置為零表示不限制, mpm_winnt上的默認(rèn)值就是0。官方參考手冊(cè)中不建議設(shè)置為0, 主要基于兩點(diǎn)考慮: (1) 可以防止(偶然的)內(nèi)存泄漏無(wú)限進(jìn)行,從而耗盡內(nèi)存; (2) 給進(jìn)程一個(gè)有限壽命,從而有助于當(dāng)服務(wù)器負(fù)載減輕的時(shí)候減少活動(dòng)進(jìn)程的數(shù)量。因此這個(gè)參數(shù)的值更大程度上取決于服務(wù)器的內(nèi)存,如果內(nèi)存比較大的話可以設(shè)置為0或很大的數(shù)字,否則設(shè)置一個(gè)小的數(shù)值。需要說(shuō)明的是,如果這個(gè)值設(shè)置的太小的話會(huì)造成Apache頻繁重啟,在日志文件中會(huì)看到如下的文字: Process exiting because it reached MaxRequestsPerChild. Signaling the parent 這樣一來(lái)降低了Apache的總體性能。另外,可以通過(guò)查看Apache提供的server-status(狀態(tài)報(bào)告)來(lái)驗(yàn)證當(dāng)前所設(shè)置數(shù)值是否合理,在httpd.conf文件中做如下設(shè)置來(lái)打開(kāi)它:
# 首先需要加載mod_status模塊
LoadModule status_module modules/mod_status.so
# 然后設(shè)置訪問(wèn)的地址
SetHandler server-status
Order deny,allow
Deny from all
# 如果限制某個(gè)IP訪問(wèn)則設(shè)置為 Allow from 192.168.1.1
Allow from all
綜合來(lái)說(shuō),因?yàn)閃indows NT下Apache只能啟動(dòng)父子兩個(gè)進(jìn)程,因此只能通過(guò)增大單個(gè)進(jìn)程的線程數(shù)以及單個(gè)進(jìn)程能夠處理的最大請(qǐng)求數(shù)來(lái)進(jìn)行優(yōu)化。其他優(yōu)化的參數(shù)同Linux系統(tǒng)下是一樣的,大家可以加以參考。下面針對(duì)上述兩個(gè)參數(shù)給出一個(gè)建議的設(shè)置:
ThreadsPerChild 250
MaxRequestsPerChild 5000
其它就和linux下的apache優(yōu)化一樣
三、apache普通配置參數(shù)
1、靜態(tài)還是動(dòng)態(tài)
使用apache的動(dòng)態(tài)載入模塊非常方便,因?yàn)樵谛枰獣r(shí)模塊才會(huì)被載入。雖然有些性能開(kāi)銷,但同時(shí)有利于減少服務(wù)器對(duì)內(nèi)存的需求。
靜態(tài)載入雖然一次性載入所有需要的模塊,增加內(nèi)存消耗。因此我們?nèi)坎捎脛?dòng)態(tài)載入的方法。
2、hhostnamelookups off
域名查找:這增加了處理每個(gè)請(qǐng)求的開(kāi)銷,首先,服務(wù)器會(huì)對(duì)dns系統(tǒng)做一個(gè)反向查詢以找出客戶系統(tǒng)的主機(jī)名,然后又進(jìn)行正向查詢看獲得的主機(jī)名是否真實(shí)指向客戶的ip。大多數(shù)情況下,你可以簡(jiǎn)單的關(guān)閉這個(gè)功能,如果你經(jīng)常處理服務(wù)器日志,這個(gè)工作完全可以在以后進(jìn)行。你可以通過(guò)在設(shè)置文件中加入指示hostnamelookups off來(lái)關(guān)閉這個(gè)功能。
3、options -followsymlinks
符號(hào)連接:當(dāng)打開(kāi)這個(gè)選項(xiàng)時(shí),apache將檢查每個(gè)請(qǐng)求中是否包含對(duì)符號(hào)連接的引用,這將對(duì)請(qǐng)求中包含的每個(gè)路徑調(diào)用一次lstat()系統(tǒng)調(diào)用。除非你準(zhǔn)備使用符號(hào)連接,否則用 options -followsymlinks 來(lái)關(guān)掉它。
4、sethandler server-status
服務(wù)器狀態(tài)信息,默認(rèn)已經(jīng)關(guān)閉。該模塊盡管這對(duì)測(cè)試與監(jiān)控服務(wù)器很有用,但它也為服務(wù)器帶來(lái)了額外的開(kāi)銷,你可以通過(guò)尋找任何類似sethandler server-status的指示來(lái)關(guān)閉,如果可能,你可以在安裝apache時(shí)移除這個(gè)模塊。
5、options -indexes
關(guān)閉目錄瀏覽
6、directoryindex index.php index.html
7、cgi模塊
除非你有很好的理由否則就允許cgi的執(zhí)行,將似有的cgi文件放到一個(gè)特定的目錄并為之設(shè)定正確的權(quán)限,這避免了apache對(duì)每一個(gè)請(qǐng)求都要判斷一次要求的是一個(gè)靜態(tài)文件還是一個(gè)動(dòng)態(tài)文件。
8、寫(xiě)入日志
寫(xiě)入日志信息是一個(gè)很花費(fèi)時(shí)間的工作,apache保持日志文件的打開(kāi)狀態(tài)以節(jié)省打開(kāi)文件的時(shí)間,如果沒(méi)有必要存儲(chǔ)日志信息,你可以關(guān)閉這個(gè)選項(xiàng)以節(jié)省出更多的處理器時(shí)間,只需要在設(shè)置文件中把日志那一行注釋掉就可以關(guān)掉它。
如果必須保留日志,你可以關(guān)閉hostnamelookups選項(xiàng)(見(jiàn)上文)然后把日志文件拷備到另一臺(tái)機(jī)器上做進(jìn)一步分析。
9、allowoverride none
.htaccess文件可以極大的擴(kuò)展apache的設(shè)置參數(shù),而無(wú)需每次你改變?cè)O(shè)計(jì)都要編輯apache主設(shè)置文件,但對(duì)這個(gè)文件的使用也降低了服務(wù)器的性能。
如果使用這個(gè)文件,apache必需首先在當(dāng)前目錄中查找是否存在這個(gè)文件,如果存在就解析這個(gè)文件并在當(dāng)前目錄中應(yīng)用文件中的設(shè)置。更壞的是,apache不僅要查看當(dāng)前的目錄,還要查看當(dāng)前目錄的所有上層目錄是否包括htaccess文件以根據(jù)所有這些文件最終確定設(shè)置。
如果你想最優(yōu)化服務(wù)器的性能,你應(yīng)該禁止使用htaccess文件,任何基本目錄的設(shè)置都可以在主設(shè)置文件中進(jìn)行,而主設(shè)置文件僅在服務(wù)器啟動(dòng)時(shí)解析一次。為了禁用htaccess文件,在任何節(jié)里加上指示allowoverride none。
10、timeout 5
timeout 設(shè)置 apache 等待一個(gè)連接讀寫(xiě)操作的時(shí)間長(zhǎng)度,也就是連接建立后,apache 等待客戶端完成請(qǐng)求發(fā)送的時(shí)間,或者是響應(yīng)開(kāi)始之后,apache 寫(xiě)出數(shù)據(jù)到客戶端連接的時(shí)間長(zhǎng)度。
無(wú)論對(duì)于哪種應(yīng)用來(lái)說(shuō),300秒的缺省值都有些過(guò)長(zhǎng)了,因?yàn)檫@就意味著,如果客戶端發(fā)生了某種未知因素導(dǎo)致的遲滯的話,服務(wù)器的一個(gè)連接和與之對(duì)應(yīng)的所有資源都要維持 300 秒,這個(gè)對(duì)于重載的服務(wù)器來(lái)說(shuō)是在是有些過(guò)長(zhǎng),所以,我建議將其設(shè)置得小一些,這個(gè)長(zhǎng)度只要足夠保證各種客戶端的應(yīng)用能夠正常傳遞數(shù)據(jù)即可。這里需要考慮的因素主要有各種客戶端的連接狀況和服務(wù)器的繁忙程度。一般來(lái)說(shuō),我建議設(shè)置為 3~5。
11、keepalive on
這個(gè)選項(xiàng)明確 httpd 進(jìn)程對(duì)每個(gè)請(qǐng)求的鏈接是否保持長(zhǎng)鏈接。如果保持長(zhǎng)鏈接,則從同一個(gè)客戶端的連續(xù)兩次請(qǐng)求會(huì)使用同一個(gè)連接,而不用重復(fù)發(fā)送請(qǐng)求。
對(duì)于下載類的應(yīng)用,因?yàn)檫B接時(shí)間都比較長(zhǎng),因此這個(gè)值設(shè)置成 on 還是 off 關(guān)系不大,從節(jié)約每一滴資源角度考慮,可以設(shè)置為 off。
對(duì)于網(wǎng)頁(yè)類應(yīng)用來(lái)說(shuō),如果你的靜態(tài)頁(yè)面上有一些圖標(biāo)、圖片、和js、css等東西的話,并且如果有超過(guò)兩個(gè)的資源的話,我建議是設(shè)置為 on。
12、maxkeepaliverequests 100
最多保持多少個(gè)活動(dòng)的長(zhǎng)鏈接
13、 keepalivetimeout 5 apache進(jìn)程在使用內(nèi)存時(shí),是“漸長(zhǎng)”的。也就是說(shuō),直到這個(gè)進(jìn)程死掉,使用內(nèi)存的數(shù)量是一直增長(zhǎng)而不會(huì)減少的。這樣的話,apache進(jìn)程使用內(nèi)存的多少,就決定于你的應(yīng)用程序最大使用內(nèi)存量了。
keepalivetimeout 這個(gè)參數(shù)決定了,在什么都不做之前,一個(gè)http進(jìn)程能夠等待多長(zhǎng)時(shí)間?設(shè)想一下,如果keepalive設(shè)置為on,而 keepalivetimeout設(shè)置為一個(gè)比較大的數(shù)字,apache占用內(nèi)存會(huì)很快的增長(zhǎng)。這是因?yàn)?,一個(gè)apache進(jìn)程完成了一個(gè)任務(wù)(并達(dá)到了一定的內(nèi)存占用,想一下“漸進(jìn)”模式),并不會(huì)馬上退出,而是等待一個(gè)keepalivetimeout時(shí)間。假設(shè)用戶的鏈接請(qǐng)求持續(xù)不斷的到來(lái),則積累起來(lái)的無(wú)用的apache進(jìn)程就會(huì)相當(dāng)多,直到timeout,這些進(jìn)程才會(huì)被殺死。
但是,keepalive的確對(duì)于靜態(tài)的文件,比如圖像文件的傳送是很有效的,因此,keepalive要設(shè)置為on,但是keepalvietimeout要設(shè)置的小些,比如5s
14、serversignature off
默認(rèn)情況下,很多apache安裝時(shí)會(huì)顯示版本號(hào)及操作系統(tǒng)版本,甚至?xí)@示服務(wù)器上安裝的是什么樣的apache模塊。這些信息可以為黑客所用,并且黑客還可以從中得知你所配置的服務(wù)器上的很多設(shè)置都是默認(rèn)狀態(tài)。 serversignature off
servertokens prod
serversignature 出現(xiàn)在apache所產(chǎn)生的像404頁(yè)面、目錄列表等頁(yè)面的底部。servertokens目錄被用來(lái)判斷apache會(huì)在server http響應(yīng)包的頭部填充什么信息。如果把servertokens設(shè)為prod,那么http響應(yīng)包頭就會(huì)被設(shè)置成:server:apache
四、MPM模塊 多處理方式(multi-processing module/mpm)他允許特定平臺(tái)處理多個(gè)并發(fā)連接
apache的mpm模塊可運(yùn)行在多種模式之下,其中beos、mpmt_os2分別是beos和os/2上缺省的mpm, perchild主要設(shè)計(jì)目的是以不同的用戶和組的身份來(lái)運(yùn)行不同的子進(jìn)程。這在運(yùn)行多個(gè)需要cgi的虛擬主機(jī)時(shí)特別有用,會(huì)比1.3版中的suexec 機(jī)制做得更好。leader和threadpool都是基于worker的變體,還處于實(shí)驗(yàn)性階段,某些情況下并不會(huì)按照預(yù)期設(shè)想的那樣工作,所以 apache官方也并不推薦使用。因此,我們主要闡述prefork和worker這兩種和性能關(guān)系最大的產(chǎn)品級(jí)mpm ( 有關(guān)其它的mpm詳細(xì)說(shuō)明,請(qǐng)參見(jiàn)apache官方文檔:http://httpd.apache.org/docs-2.0/mod/)。
1、prefork的工作原理及配置
prefork就是unix平臺(tái)上缺省的mpm。它所采用的預(yù)派生子進(jìn)程方式也是 apache 1.3中采用的模式。prefork本身并沒(méi)有使用到線程,2.0版使用它是為了與1.3版保持兼容性;另一方面,prefork用單獨(dú)的子進(jìn)程來(lái)處理不同的請(qǐng)求,進(jìn)程之間是彼此獨(dú)立的,這也使其成為最穩(wěn)定的mpm之一。
如果是使用debian的apt安裝的apache,使用"apache2ctl -l"來(lái)確定當(dāng)前使用的mpm,應(yīng)該會(huì)看到prefork.c(如果看到worker.c說(shuō)明使用的是worker mpm,依此類推),在apache2.conf中可以找到這一段配置
<IfModule mpm_prefork_module>
StartServers 5
MinSpareServers 5
MaxSpareServers 10
MaxClients 150
MaxRequestsPerChild 0
</IfModule>
prefork的工作原理是,控制進(jìn)程在最初建立"StartServers"個(gè)子進(jìn)程后,為了滿足"MinSpareServers"設(shè)置的需要?jiǎng)?chuàng)建一個(gè)進(jìn)程,等待一秒鐘,繼續(xù)創(chuàng)建兩個(gè),再等待一秒鐘,繼續(xù)創(chuàng)建四個(gè)……如此按指數(shù)級(jí)增加創(chuàng)建的進(jìn)程數(shù),最多達(dá)到每秒32個(gè),直到滿足 MinSpareServers設(shè)置的值為止。這就是預(yù)派生(prefork)的由來(lái)。這種模式可以不必在請(qǐng)求到來(lái)時(shí)再產(chǎn)生新的進(jìn)程,從而減小了系統(tǒng)開(kāi)銷以增加性能。
MaxSpareServers設(shè)置了最大的空閑進(jìn)程數(shù),如果空閑進(jìn)程數(shù)大于這個(gè)值,apache會(huì)自動(dòng)kill掉一些多余進(jìn)程。這個(gè)值不要設(shè)得過(guò)大,但如果設(shè)的值比MinSpareServers小,apache會(huì)自動(dòng)把其調(diào)整為MinSpareServers+ 1。如果站點(diǎn)負(fù)載較大,可考慮同時(shí)加大MinSpareServers和MaxSpareServers。
MaxRequestsPerChild設(shè)置的是每個(gè)子進(jìn)程可處理的請(qǐng)求數(shù)。每個(gè)子進(jìn)程在處理了"MaxRequestsPerChild" 個(gè)請(qǐng)求后將自動(dòng)銷毀。0意味著無(wú)限,即子進(jìn)程永不銷毀。雖然缺省設(shè)為0可以使每個(gè)子進(jìn)程處理更多的請(qǐng)求,但如果設(shè)成非零值也有兩點(diǎn)重要的好處: 在服務(wù)器負(fù)載下降的時(shí)侯會(huì)自動(dòng)減少子進(jìn)程數(shù)。
因此,可根據(jù)服務(wù)器的負(fù)載來(lái)調(diào)整這個(gè)值。但也不能太小,不然系統(tǒng)不斷的開(kāi)啟新的apache進(jìn)程,造成資源浪費(fèi)。
MaxClients是這些指令中最為重要的一個(gè),設(shè)定的是apache可以同時(shí)處理的請(qǐng)求,是對(duì)apache性能影響最大的參數(shù)。其缺省值 150是遠(yuǎn)遠(yuǎn)不夠的,如果請(qǐng)求總數(shù)已達(dá)到這個(gè)值(可通過(guò)ps -ef|grep http|wc -l來(lái)確認(rèn)),那么后面的請(qǐng)求就要排隊(duì),直到某個(gè)已處理請(qǐng)求完畢。這就是系統(tǒng)資源還剩下很多而http訪問(wèn)卻很慢的主要原因。系統(tǒng)管理員可以根據(jù)硬件配置和負(fù)載情況來(lái)動(dòng)態(tài)調(diào)整這個(gè)值。雖然理論上這個(gè)值越大,可以處理的請(qǐng)求就越多,但apache默認(rèn)的限制不能大于256。如果把這個(gè)值設(shè)為大于256,那么 apache將無(wú)法起動(dòng)。事實(shí)上,256對(duì)于負(fù)載稍重的站點(diǎn)也是不夠的。在apache 1.3中,這是個(gè)硬限制。如果要加大這個(gè)值,必須在“configure”前手工修改的源代碼樹(shù)下的src/include/httpd.h中查找 256,就會(huì)發(fā)現(xiàn)“#define hard_server_limit 256”這行。把256改為要增大的值(如4000),然后重新編譯apache即可。在apache 2.0中新加入了serverlimit指令,使得無(wú)須重編譯apache就可以加大maxclients。
<IfModule mpm_prefork_module>
StartServers 10
MinSpareServers 10
MaxSpareServers 15
ServerLimit 600
MaxClients 300
MaxRequestsPerChild 600
</IfModule>
2、worker的工作原理及配置
相對(duì)于prefork,worker是2.0 版中全新的支持多線程和多進(jìn)程混合模型的mpm。由于使用線程來(lái)處理,所以可以處理相對(duì)海量的請(qǐng)求,而系統(tǒng)資源的開(kāi)銷要小于基于進(jìn)程的服務(wù)器。但是, worker也使用了多進(jìn)程,每個(gè)進(jìn)程又生成多個(gè)線程,以獲得基于進(jìn)程服務(wù)器的穩(wěn)定性。這種mpm的工作方式將是apache 2.0的發(fā)展趨勢(shì)。
<IfModule mpm_worker_module>
StartServers 2
MaxClients 150
MinSpareThreads 25
MaxSpareThreads 75
ThreadsPerChild 25
MaxRequestsPerChild 0
</IfModule>
worker的工作原理是,由主控制進(jìn)程生成"startservers"個(gè)子進(jìn)程,每個(gè)子進(jìn)程中包含固定的"threadsperchild"線程數(shù),各個(gè)線程獨(dú)立地處理請(qǐng)求。同樣,為了不在請(qǐng)求到來(lái)時(shí)再生成線程,minsparethreads和maxsparethreads設(shè)置了最少和最多的空閑線程數(shù);而maxclients設(shè)置了所有子進(jìn)程中的線程總數(shù)。如果現(xiàn)有子進(jìn)程中的線程總數(shù)不能滿足負(fù)載,控制進(jìn)程將派生新的子進(jìn)程。
minsparethreads和maxsparethreads的最大缺省值分別是75和250。這兩個(gè)參數(shù)對(duì)apache的性能影響并不大,可以按照實(shí)際情況相應(yīng)調(diào)節(jié)。
threadsperchild是worker mpm中與性能相關(guān)最密切的指令。threadsperchild的最大缺省值是64,如果負(fù)載較大,64也是不夠的。這時(shí)要顯式使用 threadlimit指令,它的最大缺省值是20000。上述兩個(gè)值位于源碼樹(shù)server/mpm/worker/worker.c中的以下兩行:
究竟是選取prefork還是worker需要具體分析,相對(duì)而言高負(fù)載下perfork擁有更高的穩(wěn)定性和運(yùn)行速度,而worker的資源消耗更小。也已經(jīng)有人在對(duì)兩種工作模式作了各種測(cè)試:
實(shí)際情況看來(lái),worker現(xiàn)在還沒(méi)能達(dá)到所期望的效果,性能比f(wàn)refork差一些,資源消耗少一點(diǎn)。更可惜的是debian下worker還不能與PHP5完美結(jié)合,所以只能選用perfork了。
五、性能測(cè)試
為了獲得優(yōu)化有性能提高的幅度,評(píng)估優(yōu)化工作的成效,需要對(duì)apache2服務(wù)器進(jìn)行測(cè)試。 apache2和php5服務(wù)器:debian4.0、apache2.2.3、 php5.2.0-8+etch0、256M內(nèi)存
在另一臺(tái)機(jī)器上使用apachebench工具模擬多個(gè)瀏覽器向服務(wù)器的測(cè)試頁(yè)面發(fā)起HTTP請(qǐng)求,為了減少網(wǎng)絡(luò)帶寬的影響,測(cè)試頁(yè)面的返回值盡可能的小,此處只有1 byte,并為發(fā)起測(cè)試的機(jī)器和服務(wù)器組建了一個(gè)單獨(dú)的局域網(wǎng)。每種并發(fā)測(cè)試11次,以后10次的結(jié)果為準(zhǔn),取平均值。
以下是測(cè)試的數(shù)據(jù):其中并發(fā)數(shù)是指apachebench同時(shí)發(fā)起的請(qǐng)求個(gè)數(shù),優(yōu)化前和優(yōu)化后是指平均每個(gè)請(qǐng)求花費(fèi)的處理時(shí)間,單位毫秒
并發(fā)數(shù)優(yōu)化前(毫秒)優(yōu)化后(毫秒)
102.0481.7549
502.13891.927
1002.20841.9238
2002.76892.5915
4003.05232.797
需要指出的是,盡管高負(fù)載時(shí)優(yōu)化后性能提高的百分比并不明顯,但在并發(fā)數(shù)400時(shí),測(cè)試18次失敗7次,而優(yōu)化后測(cè)試14次失敗3次。優(yōu)化不僅僅提高了服務(wù)器的性能,還提高了負(fù)載的能力。
六、結(jié)論
優(yōu)化可以有效的提高apache2的性能。
對(duì)于WMS等設(shè)備上的配置頁(yè)面,第三部分的“apache普通配置參數(shù)”可以應(yīng)用,MPM主要是以資源換取速度的優(yōu)化,可以酌情調(diào)整。
對(duì)于EMS、升級(jí)系統(tǒng)和應(yīng)用系統(tǒng),可以全面優(yōu)化以提高性能和高負(fù)載能力。
聯(lián)系客服