Apache是一個跨平台的web服務器,由於其簡單高效、穩定安全的特性,被廣泛應用於計算機技術的各個領域。現在,Apache憑借其龐大的用戶數,已成為用戶數排名第一的web服務器。
盡管如此,在實際的生產環境中,我們仍然不可能直接使用默認配置的Apache來充當服務器。畢竟,為了更充分合理地利用Apache服務器,我們都應該根據自己的實際需要對Apache的默認配置作出一些必要的調整。而針對Apache的優化配置過程中,修改Apache的最大並發連接數就顯得尤為重要。
在修改Apache的最大並發連接數之前,我們需要預先了解一些Apache的相關知識。
眾所周知,Apache是一個跨平台的、采用模塊化設計的服務器。為了應對不同的平台和不同的環境產生的各種不同的需求,也為了在具體的平台或環境下達到最佳的效果,Apache在web服務器的基礎功能方面(端口綁定、接收請求等)也同樣采用了模塊化設計,這個Apache的核心模塊就叫做多路處理模塊(Multi-Processing Module,簡稱MPM)。
Apache針對不同的操作系統提供了多個不同的MPM模塊,例如:mpm_beos
、mpm_event
、mpm_netware
、mpmt_os2
、mpm_prefork
、mpm_winnt
、mpm_worker
。如果條件允許,我們可以根據實際需求將指定的MPM模塊編譯進我們自己的Apache中(Apache的源碼是開放的,允許用戶自行編譯)。不過,如果在編譯時我們沒有選擇,Apache將按照如下表格根據不同的操作系統自行選擇對應的MPM模塊,這也是Apache針對不同平台推薦使用的MPM模塊。
不同操作系統上默認的MPM模塊 | ||
---|---|---|
操作系統 | MPM模塊 | 描述 |
Windows | mpm_winnt | 不用介紹了吧:) |
Unix/Linux | mpm_prefork | 不用介紹了吧:) |
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_winnt
、mpm_prefork
、mpm_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>
配置節點,如下圖所示:
此時,我們就需要根據當前Apache服務器所使用的MPM模塊,來修改對應<IfModule>
節點下的參數配置。首先,我們來看看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表示不限制請求總數(子進程永不結束)。
該參數建議設為非零的值,可以帶來以下兩個好處:
- 可以防止程序中可能存在的內存泄漏無限進行下去,從而耗盡內存。
- 給進程一個有限壽命,從而有助於當服務器負載減輕的時候減少活動進程的數量。
注意:在以上涉及到統計請求數量的參數中,對於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 (此外,還需額外設置ServerLimit參數,該參數最好與MaxClients的值保持一致。) </IfModule>
#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(也就是
mpm_prefork
),MaxClients
表示可以用於處理客戶端請求的最大子進程數量,默認值是256。要增大這個值,你必須同時增大ServerLimit
。對於線程型或者混合型的MPM(也就是
mpm_beos
或mpm_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
的值以降低內存泄露帶來的影響,然后盡快找出程序中的問題之所在。
# BeOS MPM
# StartThreads: how many threads do we initially spawn?
# MaxClients: max number of threads we can have (1 thread == 1 client)
# MaxRequestsPerThread: maximum number of requests each thread will process
<IfModule mpm_beos_module>
StartThreads 10
MaxClients 50
MaxRequestsPerThread 10000
</IfModule>
出處至: Carter的菜園子