1. 程式人生 > >處理高併發、高訪問之Apache優化

處理高併發、高訪問之Apache優化

前言:

專案100人同時訪問,導致訪問速度變慢,作為一個沒有遇到過這種情況下的轅,在各種查閱資料後,先用刪除日誌更改日誌輸出的方法處理後(處理方法:修改Apache日誌輸出相關配置方法),暫時好緩,後來又出現變慢,在查閱各種部落格後,發現一個處理併發的方法,小試身手,發現有所好轉。總結一下,加深記憶。

多路處理模組MPM(Multi-Processing Module)介紹

作為Apache的核心模組它針對不同的作業系統提供了多個不同的MPM模組,例如:mpm_beosmpm_eventmpm_netwarempmt_os2mpm_preforkmpm_winntmpm_worker

。 如果條件允許,我們可以根據實際需求將指定的MPM模組編譯進我們自己的Apache中(Apache的原始碼是開放的,允許使用者自行編譯)。不過,如果在編譯時我們沒有選擇,Apache將按照如下表格根據不同的作業系統自行選擇對應的MPM模組,這也是Apache針對不同平臺推薦使用的MPM模組。

不同作業系統上預設的MPM模組
作業系統 MPM模組 描述
Windows mpm_winnt Windows系統
Unix/Linux mpm_winnt Unix/Linux系統
BeOS mpm_beos 由Be公司開發的一種多媒體作業系統,官方版已停止更新。
Netware mpm_netware 由NOVELL公司推出的一種網路作業系統
OS/2 mpmt_os2 一種最初由微軟和IBM共同開發的作業系統,現由IBM單獨開發(微軟放棄OS/2,轉而開發Windows)

mpm_event

模組可以看作是mpm_worker模組的一個變種,不過其具有實驗性質,一般不推薦使用。
當然,Apache在其官方網站上也提供了根據不同作業系統已經編譯好對應MPM模組的成品Apache。你可以點選此處進入Apache官方網站下載。

此外,如果我們想要知道某個Apache內部使用的是何種MPM模組,我們可以以命令列的方式進入Apache安裝目錄\bin,然後鍵入命令httpd -l,即可檢視到當前Apache內部使用的何種MPM模組。

由於在平常的開發工作中,BeOS、NetWare、OS/2等作業系統並不常見,這裡我們主要針對Windows和Unix/Linux作業系統上的MPM模組進行講解。在Windows和Unix/Linux作業系統上,MPM模組主要有mpm_winntmpm_preforkmpm_worker三種。

mpm_prefork模組

mpm_prefork模組主要應用於Unix/Linux平臺的Apache伺服器,其主要工作方式是:當Apache伺服器啟動後,mpm_prefork模組會預先建立多個子程序(預設為5個),當接收到客戶端的請求後,mpm_prefork模組再將請求轉交給子程序處理,並且每個子程序同時只能用於處理單個請求。如果當前的請求數將超過預先建立的子程序數時,mpm_prefork模組就會建立新的子程序來處理額外的請求。Apache總是試圖保持一些備用的或者是空閒的子程序用於迎接即將到來的請求。這樣客戶端的請求就不需要在接收後等候子程序的產生。

由於在mpm_prefork模組中,每個請求對應一個子程序,因此其佔用的系統資源相對其他兩種模組而言較多。不過mpm_prefork模組的優點在於它的每個子程序都會獨立處理對應的單個請求,這樣,如果其中一個請求出現問題就不會影響到其他請求。同時,mpm_prefork模組可以應用於不具備執行緒安全的第三方模組(比如PHP的非執行緒安全版本),且在不支援執行緒除錯的平臺上易於除錯。此外,mpm_prefork模組還具有比mpm_worker模組更高的穩定性。

mpm_worker模組

mpm_worker模組也主要應用於Unix/Linux平臺的Apache伺服器,它可以看作是mpm_prefork模組的改進版。mpm_worker模組的工作方式與mpm_prefork模組類似。不過,由於處理相同請求的情況下,基於程序(例如mpm_prefork)比基於執行緒的處理方式佔用的系統資源要多。因此,與mpm_prefork模組不同的是,mpm_worker模組會讓每個子程序建立固定數量的服務執行緒和一個監聽執行緒,並讓每個服務執行緒來處理客戶端的請求,監聽執行緒用於監聽接入請求並將其傳遞給服務執行緒處理和應答。Apache總是試圖維持一個備用或是空閒的服務執行緒池。這樣,客戶端無須等待新執行緒或新程序的建立即可得到處理。

與mpm_prefork模組相比,mpm_worker模組可以進一步減少系統資源的開銷。再加上它也使用了多程序,每個程序又有多個執行緒,因此它與完全基於執行緒的處理方式相比,又增加了一定的穩定性。

mpm_winnt模組

mpm_winnt模組是專門針對Windows作業系統而優化設計的MPM模組。它只建立一個單獨的子程序,並在這個子程序中輪流產生多個執行緒來處理請求。

修改MPM模組配置

在對Apache的MPM模組具備一定了解後,我們就可以針對不同的MPM模組來修改Apache的最大併發連線數配置了。

  1. 啟用MPM模組配置檔案

    在Apace安裝目錄/conf/extra目錄中有一個名為httpd-mpm.conf的配置檔案。該檔案主要用於進行MPM模組的相關配置。不過,在預設情況下,Apache的MPM模組配置檔案並沒有啟用。因此,我們需要在httpd.conf檔案中啟用該配置檔案,如下所示:

    
    # Server-pool management (MPM specific)
    
    
    # Include conf/extra/httpd-mpm.conf (去掉該行前面的註釋符號"#")
    
  2. 修改MPM模組配置檔案中的相關配置

    在啟動MPM模組配置檔案後,我們就可以使用文字編輯器開啟該配置檔案,我們可以看到,在該配置檔案中有許多<IfModule>配置節點,如下圖所示:
    httpd-mpm.conf檔案截圖

此時,我們就需要根據當前Apache伺服器所使用的MPM模組,來修改對應節點下的引數配置。首先,我們來看看mpm_winnt模組下的預設配置:

mpm_winnt模組

#由於mpm_winnt模組只會建立1個子程序,因此這裡對單個子程序的引數設定就相當於對整個Apache的引數設定。

<IfModule mpm_winnt_module>
ThreadsPerChild      150 #推薦設定:小型網站=1000 中型網站=1000~2000 大型網站=2000~3500
MaxRequestsPerChild    0 #推薦設定:小=10000 中或大=20000~100000
</IfModule>

對應的配置引數作用如下:

ThreadsPerChild:每個子程序的最大併發執行緒數。
MaxRequestsPerChild:每個子程序允許處理的請求總數。如果累計處理的請求數超過該值,該子程序將會結束(然後根據需要確定是否建立新的子程序),該值設為0表示不限制請求總數(子程序永不結束)。
該引數建議設為非零的值,可以帶來以下兩個好處:
1. 可以防止程式中可能存在的記憶體洩漏無限進行下去,從而耗盡記憶體。
2. 給程序一個有限壽命,從而有助於當伺服器負載減輕的時候減少活動程序的數量。

注意:在以上涉及到統計請求數量的引數中,對於KeepAlive的連線,只有第一個請求會被計數。

接著,我們再來看看mpm_perfork模組和mpm_worker模組下的預設配置:

mpm_perfork模組

<IfModule mpm_prefork_module>
StartServers          5 #推薦設定:小=預設 中=20~50 大=50~100
MinSpareServers       5 #推薦設定:與StartServers保持一致
MaxSpareServers      10 #推薦設定:小=20 中=30~80 大=80~120 
MaxClients          150 #推薦設定:小=500 中=500~1500 大型=1500~3000
MaxRequestsPerChild   0 #推薦設定:小=10000 中或大=10000~500000
</IfModule>

此外,還需額外設定ServerLimit引數,該引數最好與MaxClients的值保持一致。


# StartServers:  數量的伺服器程序開始

# MinSpareServers:  最小數量的伺服器程序,儲存備用

# MaxSpareServers:  最大數量的伺服器程序,儲存備用

# MaxRequestWorkers:  最大數量的伺服器程序允許開始

# MaxConnectionsPerChild:  最大連線數的一個伺服器程序服務

  prefork 控制程序在最初建立 “StartServers”個子程序後,為了滿足MinSpareServers設定的需要建立一個程序,等待一秒鐘,繼續建立兩 個,再等待一秒鐘, 繼續建立四個……如此按指數級增加建立的程序數,最多達到每秒32個,直到滿足MinSpareServers設定的值為止。這種模式 可以不必在請求到 來時再產生新的程序,從而減小了系統開銷以增加效能。MaxSpareServers設定了最大的空閒程序數,如果空閒程序數大於這個 值,Apache 會自動kill掉一些多餘程序。這個值不要設得過大,但如果設的值比MinSpareServers小,Apache會自動把其調整 為 MinSpareServers+1。如果站點負載較大,可考慮同時加大MinSpareServers和MaxSpareServers。

  MaxRequestsPerChild設定的是每個 子程序可處理的請求數。每個子程序在處理了“MaxRequestsPerChild”個請求後將自 動銷燬。0意味著無限,即子程序永不銷燬。雖然預設 設為0可以使每個子程序處理更多的請求,但如果設成非零值也有兩點重要的好處:

  1. 可防止意外的記憶體洩 漏。
  2. 在伺服器負載下降的時侯會自動減少子程序數。

因此,可根據伺服器的負載來調整這個值。

  MaxRequestWorkers指令集同時將服務請求的數量上的限制。任何連線嘗試在MaxRequestWorkerslimit將通常被排隊,最多若干基於上ListenBacklog指令。

在apache2.3.13以前的版本MaxRequestWorkers被稱為MaxClients 。

MaxClients是這些指令中最為重要的一個,設定的是 Apache可以同 時處理的請求,是對Apache效能影響最大的引數。其預設值150是遠遠不夠的,如果請求總數已達到這個值(可通過 ps -ef|grep http|wc -l來確認),那麼後面的請求就要排隊,直到某個已處理請求完畢。這就是系統資源還剩下很多而HTTP訪問卻很 慢的主要原因。雖然理論上這個值越大,可以 處理的請求就越多,但Apache預設的限制不能大於256。

mpm_worker模組

<IfModule mpm_worker_module>
StartServers          2 #推薦設定:小=預設 中=3~5 大=5~10
MaxClients          150 #推薦設定:小=500 中=500~1500 大型=1500~3000
MinSpareThreads      25 #推薦設定:小=預設 中=50~100 大=100~200
MaxSpareThreads      75 #推薦設定:小=預設 中=80~160 大=200~400 
ThreadsPerChild      25 #推薦設定:小=預設 中=50~100 大型=100~200
MaxRequestsPerChild   0 #推薦設定:小=10000 中或大=10000~50000
(此外,如果MaxClients/ThreadsPerChild大於16,還需額外設定ServerLimit引數,ServerLimit必須大於等於 MaxClients/ThreadsPerChild 的值。)
</IfModule>

對應的配置引數作用如下:

StartServers 啟動Apache時建立的子程序數。

MinSpareServers 處於空閒狀態的最小子程序數。
所謂空閒子程序是指沒有正在處理請求的子程序。如果當前空閒子程序數少於MinSpareServers,那麼Apache將以最大每秒一個的速度產生新的子程序。只有在非常繁忙機器上才需要調整這個引數。此值不宜過大。

MaxSpareServers 處於空閒狀態的最大子程序數。
只有在非常繁忙機器上才需要調整這個引數。此值不宜過大。如果你將該指令的值設定為比MinSpareServers小,Apache將會自動將其修改成MinSpareServers+1。

MaxClients 允許同時連線的最大請求數量。
任何超過MaxClients限制的請求都將進入等待佇列,直到達到ListenBacklog指令限制的最大值為止。

mpm_prefork

MaxClients表示可以用於處理客戶端請求的最大子程序數量,預設值是256。要增大這個值,你必須同時增大ServerLimit。

對於執行緒型或者混合型的MPM(也就是mpm_beosmpm_worker),MaxClients表示可以用於處理客戶端請求的最大執行緒數量。執行緒型的mpm_beos的預設值是50。對於混合型的MPM預設值是16(ServerLimit)乘以25(ThreadsPerChild)的結果。因此要將MaxClients增加到超過16個程序才能提供的時候,你必須同時增加ServerLimit的值。

MinSpareThreads 處於空閒狀態的最小執行緒數。 不同的MPM對這個指令的處理是不一樣的:

mpm_worker的預設值是75。這個MPM將基於整個伺服器監視空閒執行緒數。如果伺服器中總的空閒執行緒數太少,子程序將產生新的空閒執行緒。mpm_netware的預設值是10。既然這個MPM只執行單獨一個子程序,此MPM當然亦基於整個伺服器監視空閒執行緒數。mpm_beos和mpmt_os2的工作方式與mpm_netware差不多,mpm_beos的預設值是1;mpmt_os2的預設值是5。

MaxSpareThreads 處於空閒狀態的最大執行緒數。 不同的MPM對這個指令的處理是不一樣的:

注: mpm_worker的預設值是250。這個MPM將基於整個伺服器監視空閒執行緒數。如果伺服器中總的空閒執行緒數太多,子程序將殺死多餘的空閒執行緒。mpm_netware的預設值是100。既然這個MPM只執行單獨一個子程序,此MPM當然亦基於整個伺服器監視空閒執行緒數。mpm_beos和mpmt_os2的工作方式與mpm_netware差不多,mpm_beos的預設值是50;mpmt_os2的預設值是10。

備註:ServerLimit表示Apache允許建立的最大程序數。 值得注意的是,Apache在編譯時內部有一個硬限制ServerLimit 20000(對於mpm_prefork模組為ServerLimit 200000)。你不能超越這個限制。
使用這個指令時要特別當心。如果將ServerLimit設定成一個高出實際需要許多的值,將會有過多的共享記憶體被分配。如果將ServerLimit和MaxClients設定成超過系統的處理能力,Apache可能無法啟動,或者系統將變得不穩定。

注意:在配置相關引數時,請先保證伺服器具備足夠的硬體效能(例如:CPU、記憶體等)。 如果發現自啟動後,隨著伺服器的執行時間增加,伺服器的記憶體佔用也隨之增加,可能是程式中出現記憶體洩露,請向下調整引數MaxRequestsPerChild的值以降低記憶體洩露帶來的影響,然後儘快找出程式中的問題之所在。