本文將先講解何謂Apache的多進程處理模式(Multi-Processing Module,MPM),透過此種模式為何能夠充分發揮主機硬體的效能。然後,再介紹httperf這個網站壓力測試軟體,說明如何其安裝及使用,示範怎樣透過此工具軟體測試出網站伺服器的最大服務效能極限。
說起網站伺服器,相信許多人的腦海裡浮現的第一個念頭應該是Apache。多年來挾其優異的效能及廣泛的支援,已成為網站伺服器建置的不二首選。但大部分的使用者,通常在初次安裝Apache後,往往都是利用預設的組態運作,如此一來,即使主機有再多優異的硬體設備,也無法完全發揮其效能。
對此,在本文中將說明Apache的多進程處理模式(Multi-Processing Module,簡稱MPM),以MPM模式來充分地發揮主機硬體效能。
除此之外,也將介紹一套有名的網站壓力測試軟體httperf,可利用此測試軟體找出網站伺服器的服務效能極限,此次所使用的環境為CentOS 7和Apache 2.4.39版。
何謂MPM工作模式
在使用MPM工作模式之前,必須先確定主機上的CPU是否支援多核心,唯有支援多核心功能,方可使用MPM工作模式。截至目前為止,Apache提供了Prefork、Work、Event三種MPM工作模式,如下所述:
Prefork工作模式
Prefork是Apache最早期所支援的多進程處理模式,是個古老又穩定的處理模式。在此模式下,Apache在啟動後會預先以fork模式建立多個子進程(Child Process),然後等待來自使用者端請求(Request),藉此減少頻繁建立及銷毀進程的時間,而且每個進程在同個時間只會單獨處理一個連線,處理效率較高。
但相對地,由於建立進程(Process)所消耗的系統資源較高,因此在此種模式下,Apache需要較好的硬體設備,才能應付建立進程所需要的損耗。簡而言之,Prefork模式的優點在於相對成熟穩定,並且單一進程個別獨立處理不同的使用者端請求,即使某個使用者端請求出現問題,也不會影響到其他的使用者端請求。
而Prefork模式的缺點是進程相對占用更多的系統資源,消耗更多的系統記憶體,所以並無法有效地同時處理頻繁的使用者要求。因此,Apache開始使用消耗系統資源較少的線程(Thread)方式來處理使用者的要求,希望利用此種方式讓Apache能同時處理更多的使用者端請求。
在Prefork模式下,提供了下列的組態來設定:
設定Apache伺服器啟動時,會預先建立的子進程數量,預設為5。
設定Apache啟動後,最少備用的子進程數量。當Apache的子進程數量小於此設定值時,Apache會自動新建子進程數量。由於新建進程都需要消耗相當的系統資源,因此建議此組態值不要設定過大。
設定Apache啟動後最大備用子進程的數量,如果目前系統有發現超過MaxSpareServers數量的備用子進程,那麼父進程就會中斷多餘的備用子進程。想當然耳,此組態值一定會比MinSpareServers組態值還要大,但如果設置比MinSpareServers小,那麼Apache會自動將其修改為MinSpareServers +1的數量。
此組態值即為早期的MaxClients組態,主要是用來設定限制Apache伺服器在同一個時間內所能處理的使用者端請求,預設值為256。亦即在預設的情況下,同時間僅能服務256個連使用者端請求。當使用者要求的數量超過此組態值時,便會將該使用者要求暫時置於等待隊列(Queue)中等待Apache的服務,所以在未調整預設組態的情況下,就算有再高檔的硬體設備,也無法同時服務超過256個使用者端請求。
設定每個子進程在其生命週期內允許服務的最大使用者端請求數量,一旦使用者端請求數量達到這個數值,便會自動結束此子進程。如果設置為0,就表示子進程將永遠不會結束。
Worker工作模式
由於建立進程所需要的系統資源較高,因此在Worker模式導入了相對所需資源較低的線程(Thread)觀念。使用了多進程和多線程的混合模式,當Apache啟動時,同樣地利用fork預先建立多個子進程,並且在每個子進程內新建多個線程,而後再利用線程來服務使用者端請求,也因此能夠更有效率地服務使用者端請求。
但相對於Prefork模式而言,由於一個進程內可能會處理多個不同的使用者端請求,因此當進程無預警地停止後,可能會影響多個不同的使用者端請求。
在Worker模式下,提供了以下的組態來設定:
限定Apache在運作時所能產生的最大進程數。
當Apache伺服器啟動時,所要預先建立的子進程數量,預設為3。
設定每個子進程所產生的線程數量。
設定可用於處理使用者要求的最少備用線程數量。
設定可用於處理使用者要求的最多備用線程數量。
MaxRequestWorkers
設定限制Apache伺服器在同一個時間內所能處理的使用者端請求數量。此組態值與ServerLimit組態值相關,在設定MaxRequestWorkers的值時,須注意要小於或等於ServerLimit的值乘以進程裡之線程數的值。也就是說,MaxRequestWorkers的值須小於或等於ServerLimit組態值乘以ThreadsPerChild組態值。否則會出現錯誤,而無法啟動Apache伺服器。
設定每個子進程在其生命週期內允許最大的使用者要求數量,一旦使用者要求數量達到這個數值,就會自動結束此子進程。如果設置為0,表示子進程將永遠不會結束。
Event工作模式
Event是Apache的最新運作模式,就如同Worker運作模式一樣,Event運作模式也是利用線程及進程的方式來服務使用者端請求。與Worker運作模式較為不同的是,Event運作模式在於解決Keep-alive在長時間連接時,占用線程資源被浪費的問題。
Keep-alive是一種保持連線存在的機制,如果每次的使用者端請求,都須要再重新建立連線,那系統將會耗費太多的資源在建立連線上,因此在HTTP通訊協定中提出Keep-alive的概念。當一個連線被建立時,可設定暫時保存此連線存在的時間,後續的使用者端請求即可利用此已存在的連線繼續傳輸資料,藉此避免掉重新建立連線的成本。
但如果Keep-alive的保存時限設定過長,就可能會在系統上保持許多長時間未使用的連線,而Event運作模式即是利用專門的線程來管理Keep-alive類型的連線,以避免Keep-alive連線長時間占用系統資源的問題。Event所提供的組態設定,基本上與Worker執行模式相同,這裡就不多加贅述。
在簡單說明Apache所提供的MPM工作模式後,接著可以執行「httpd -V」指令來得知網站伺服器所支援的MPM模式,如圖1所示,本例支援Event模式。
在了解MPM的相關工作模式後,接著便需要一套客觀的網站服務效能評估工具,藉此評估網站伺服器的處理效能,並測試出網站伺服器所能服務的極限值。以下介紹一套開源碼有名的httperf網站效能測試軟體,可用來測試以MPM工作模式的網站伺服器,並藉此來調整出最佳的效能參數。
安裝及使用httperf
httperf是一套可對網站伺服器做壓力測試的工具,能夠在短時間內模擬大量的使用者端要求對受測的網站伺服器從事壓力測試,藉以找出網站伺服器服務效能的臨界點。一開始,先安裝httperf軟體,請連結至官方下載網站(https://github.com/httperf/httperf)取得最新版本,接著進行編譯及安裝作業:
httperf安裝成功後,將會產生一個名為httperf的主要執行檔,可利用此執行檔對受測的網站伺服器進行壓力測試,以下先來說明httperf所提供的常見參數:
--hog:在未指定此參數的情況之下,httperf僅能使用非特權通訊埠(通訊埠1024至65536)來與受測的網站伺服器進行連線測試。在此情況下,通訊埠數量可能會不敷使用,因此加上此參數,就能夠使用特權通訊埠(通訊埠1024以下)。
--server:指定受測的網站伺服器的位置,可使用IP或網址的形式。
--uri:指定受測的網站伺服器上的網頁位址,httperf會將所產生的使用者端要求,直接發送所指定的網頁位址上。
--num-conn:設定單次測試要產生的連線(Connection)數量。
--num-call:設定每個連線數內產生的使用者端要求數,所以總共會產生的使用者端要求數量為--num-conn所設定的值乘上num-call的設定的值。
--timeout:設定受測網站伺服器針對處理每個使用者端要求的逾時(Timeout)時間(單位為秒),當網站伺服器無法在逾時的時限內正確地回覆使用者端要求,就會將此情況視為發生錯誤,而加以統計。
--rate:設定在每秒內要產生並發送的連線數目。預設為0,表示循序的建立及發送連線(前一個使用者要求發送成功後,便繼續下一個使用者要求發送)至受測網站伺服器上。可利用--wsess選項,來重新設定發送的速率。
--wsess N1,N2,X:此組態共有三個參數,其中N1表示本次總共要產生連線數量(即num-conn設定值),而N2便是每個連線所要產生的使用者端要求(即num-call設定值),而最後的X就表示每個連線發送的間隔時間(單位為秒),通常這個組態會與--burst-length組態同時併用。
--burst-length:設定每一次傳遞至網站伺服器的使用者端要求數量。
--port:指定受測網站伺服器所使用的通訊埠資訊,例如80或443。
--failure-status:以網站伺服器的回覆狀態碼來判定是否失敗,當httperf接收到符合的回覆狀態碼,就視為失敗而加以統計。例如設定為403,表示當網站伺服器處理使用者端要求後,如果回覆403,便認定為失敗。
--http-version:設定產生的使用者端要求所使用的HTTP通訊協定版本,通常為1.0或1.1。
以下列指令為例,表示針對該受測網站伺服器(通訊埠為80)上的index.php,發送5,000個連線數且每個連線數內含10個使用者端要求,代表總共要用50,000個(5,000 × 10)使用者端要求來測試,並且測試的速率為每秒鐘要產生200個連線數(亦即每秒產生2,000個使用者端要求,並且設定每個使用者端要求的回覆時間為5秒,如果網站伺服器在5秒內未回覆此使用者端要求,即表示逾時並視為失敗而列入統計:
httperf --server <受測網站伺服器IP 資訊> --port 80 --uri index. php --num-conn 5000 --num-call 10 --rate 200 --timeout 5
執行成功後,會產生包含使用者端送出要求、回覆的平均時間等資訊,如圖2所示。對本文而言,最重要的資訊是發生錯誤的個數統計,因此將僅說明報告中關於錯誤統計的區段。
client-timo:指的是從httperf發送使用者端要求至網站伺服器,而網站伺服器未在時限(由--timeout參數指定,在本例為5秒)內回覆的統計次數,這個數值通常可用來測試受測網站伺服器的最大連線數的門檻值,如果httperf發送了超過受測網站伺服器所能承受的連線量,那麼受測網站伺服器將會因不能即時處理如此大量的連線,而無法即時在時限內回覆,便產生了大量的client-timo,使用者可藉此評估受測網站伺服器的最大連線量的門檻值。
socket-timo:可計算在與受測網站伺服器進行TCP連線時,發生的Socket層級錯誤的次數。
connrefused:可計算httperf發出使用者端要求至受測網站伺服器,被網站伺服器拒絕的次數。
connreset:計算httperf發出使用者端要求至受測網站伺服器,被網站伺服器重置(Reset)的次數。
進行網站伺服器效能調整
由於網站伺服器的效能,絕大部分是取決於主機上的硬體設備,因此預期的效能調整效益是能在相同的硬體設備上配置出能同時服務最多使用者端要求的數量,亦即可設定MaxRequestWorkers的最佳值。
本文將以Event工作模式(可利用「httpd -V」指令來得知網站伺服器上的工作模式)為例,要先計算主機上的總記憶體最多能夠產生多少個Apache子進程(記得要預留記憶體以供系統其他程式運用),可以下列的公式進行計算:
(系統總記憶體容量減去預定保留的記憶體) / 每個子行程所消耗的記憶體
接著,繼續計算每個Apache子進程所消耗的記憶體容量,可至下列網址取得計算程式:
http://cloudinservice.com/wp-content/uploads/2011/03/ap.sh.zip
如果使用者無法下載此檔案,也可利用下列的Shell指令來計算:
ps -ylC httpd | awk '{x += $8;y += 1} END {print "Apache Memory Usage (MB): "x/1024; print "Average Proccess Size (MB): "x/((y-1)*1024)}'
要特別提醒的是,其中httpd為Apache啟動時所使用的程序名稱,必須根據實際運作的程序名稱進行更改。執行結果如圖3所示,結果表示每個子進程須花費10MB記憶體來建立。
以一個擁有8G記憶體的主機為例,假設預定保留1G的記憶體,且建立子進程,平均要消耗掉10MB的記憶體所能支援的進程數量為(8G - 1G) / 10M,約等於700,為保險起見,取數值為600。因此,理論上應可最少同時服務600個使用者端要求。
接下來,在httpd-mpm.conf的mpm_event區段,設定如下的組態(必須注意MaxRequestWorkers要小於或等於ServerLimit乘以ThreadsPerChild):
<fModule mpm_event_module>
ServerLimit 32
StartServers 3
MinSpareThreads 75
MaxSpareThreads 250
ThreadsPerChild 25
MaxRequestWorkers 600
MaxConnectionsPerChild 0
</IfModule>
重新啟動Apache後,即可利用「httperf --server <受測網站伺服器IP資訊> --port 80 --num-conn 5000 --num-call 10 --rate 200 --timeout 5」指令觀察輸出資訊的錯誤區段,主要觀察的重點在於是否有出現統計錯誤的數量。並依次漸增--num-conn及--num-call的數字,直到測試結果有出現明顯的統計錯誤數量,就代表網站伺服器所能服務的最大連線數。如此一來,便可找出網站伺服器在設定MPM的情況下所能同時服務的最大連線數,並以同樣的方式測試關閉MPM模式的網站伺服器能夠同時服務的最大連線數。藉此,比較開啟MPM模式時是否能同時服務更多的使用者端要求。
<本文作者:吳惠麟,多年資安經驗,喜好利用開源碼建構相關解決方案,著有「資訊安全原理與實驗」等書。>