鏈接:https://www.zhihu.com/question/23786410/answer/153455460
來源:知乎
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
有一台正在運行的apache服務器,用戶A訪問該apache的時候apache建立一個新的進程1處理用戶A的請求。
這時又有一個用戶B訪問該apache,apache又建立一個新的進程2處理用戶B的請求。
后來又有用戶C,D,E訪問該apache,apache又建立三個進程3,4,5處理他們的請求。
如果每當一個新用戶訪問該apache,apache再建立一個新的進程處理用戶的請求,是不是太慢了呢?
所以apache的prefork模式在apache第一次啟動的時候就建立5個進程,等待用戶的連接請求,有一個用戶訪問,就有一個進程處理他的請求。
那么如果有5個用戶同時訪問apache,apache第一次建立的5個進程全部用光了,所以apache就再從新在建立5個進程,等待下一批用戶的請求。
prefork模式會根據服務器的硬件情況,設定apache最多只能同時建立256個進程。再多的請求就只能等待前面的進程處理完畢在進行處理。
假設完畢!
上面的假設就是prefork模式的工作原理。但是上面假設中具體的數字不是定死的,而是通過prefork模式的配置來設置的。下面是http.conf中的配置信息。
*帶井號的為注釋部分
prefork模式的幾個重要的參數:
---------------------------------------------------------------------------------------------------------------
名稱 默認值 說明
StartServers 5 apache啟動時候默認開始的進程數
MinSpareServers 5 最小的閑置進程數
MaxSpareServers 10 最大的閑置進程數
ServerLimit 256 最大的進程總數(參考,實際看MaxClients)
MaxClients 256 最大的進程總數
MaxRequestsPerChild 4000 每個進程處理的最多請求數
----------------------------------------------------------------------------------------------------------------
(1)StartServers:這個看了就明白了。
(2)MinSpareServers:舉個例子就明白了。
apache在沒有用戶訪問時候有5個閑置的進程,如果有一個用戶訪問網站。則閑置的進程就只有4個,這個值小於MinSpareServers,所以apache就以第一秒1個進程,第二秒2個進程,第三秒4個進程的速度新建空閑進程。直到大於等於MinSpareServers個空閑進程才結束。
(3)MaxSpareServers:還是舉個例子就明白了。
apache在沒有用戶訪問時候有5個閑置的進程,如果有5個用戶同時訪問網站。則閑置的進程就只有0個,這個值小於 MinSpareServers,所以apache就以第一秒1個進程,第二秒2個進程,第三秒4個進程的速度新建空閑進程。直到大於等於 MinSpareServers個空閑進程才結束。在這個例子中直到第三秒,一共生成1+2+4個進程才能滿足大於等於MinSpareServers的要求。后來這5個用戶訪問完apache,訪問結束,關閉瀏覽器。所以apache就有了5+7個空閑的進程。這時空閑的進程比較多,apache就開始關閉一些進程,直到滿足小於MaxSpareServers個空閑進程才結束。如果該值小於MinSpareServers則apache默認將該值設置成MinSpareServers+1。
(4)ServerLimit:這個參數是控制apache的進程總數的,那為什么會有兩個參數控制apache的進程總數呢?這個參數在apache1的時代是沒有的,因為那個時候有個256M內存的服務器就很厲害了。后來apache2的時代到來,服務器的硬件也得到升級。很多服務器都是4G內存,還有很多比4G內存大的服務器出現。apache1的時代只有一個MaxClients參數控制進程總數就夠了,而這個參數最大值是256定死了。但是到了apache2的時代必須調整ServerLimit值大於256才能使MaxClient支持大於256的值。
(5)MaxClients:apache最大的進程數。apache1的時代只有一個MaxClients參數控制進程總數就夠了,而這個參數最大值是256定死了。但是到了apache2的時代必須調整ServerLimit值大於256才能使MaxClient支持大於256的值。
(6)MaxRequestsPerChild:舉個例子就明白了。
apache在沒有用戶訪問的時候有5個空閑進程。當一個用戶訪問網站,訪問完又離開。則apache的第一個進程就處理了一個請求,從新進入閑置狀態。再有一個用戶訪問網站,訪問完后離開。則apache的第一個進程就處理了1+1個請求。這樣繼續訪問3998個用戶,這個進程就處理了4000個請求,之后就自動關閉這個進程。這個時候apache就只有4個限制的進程,小於MinSpareServers值所以apache從今建立一個空閑進程。至於為什么處理完4000個請求就要關閉這個進程呢?答案之一:為了防止內存的泄露。
下面圖文介紹這些參數(要深刻理解一個知識就要親自去體驗)
測試環境參數
說明
操作系統
centos4.5(虛擬機)
服務器
apache2.2.6
內存
1G
服務器地址
192.168.212.128
客戶端地址
192.168.212.1
測試文件index.php
<?php
for($i = 0;$i <= 10;$i++){
echo date('H:i:s',time());
echo '<br/>';
sleep(10);
}
?>
測試http.conf的prefork模式設置:(設置有點極端,但是可以很好的理解說明)
首先查看apache第一次啟動時候的空閑進程:
linux(centos)下查看apache的進程可以使用#ps -ef|grep httpd命令,查看apache進程的內存使用情況可以使用#ps –U apache –u apache u命令
#service httpd restrat:重啟apache,初始化進程
#ps -ef|grep httpd:用戶名為apache的才是apache用於處理用戶請求的進程
#ps –U apache –u apache u:查看用戶名為apache的進程(即apache為了處理用戶請求而建立的進程詳情)
當前為沒有任何用戶訪問時候apache建立StartServers=1個進程
(1)當有一個用戶訪問(通過本機上的ie瀏覽器訪問虛擬主機上apache服務器模式該情景)
可以看到apache的進程增加為2個,為什么呢?當唯一的空閑進程時候完之后,空閑進程小於MinSpareServers,apache就從新建立一個進程。注意查看RSS值(該進程的內存使用量KB)為4424的空閑進程。
再看看訪問完成之后的apache進程數。
可以看到還是只有兩個進程,而且這兩個進程都是空閑的。
(2)當有兩個用戶訪問(通過本機上的兩個ie瀏覽訪問虛擬主機上的apache服務器模擬該情景)
可以看到有兩個用戶訪問的時候apache的進程數增加為3個。為什么呢?當本來空閑2個進程時候完之后,空閑進程小於MinSpareServers,apache就從新建立一個進程。注意查看RSS值(該進程的內存使用量KB)為4424的空閑進程。
再看看訪問完成之后的apache進程數。
可以看到空閑的進程數又減少為2個。為什么呢?當兩個用戶訪問完成之后兩個用戶的進程都會關閉,這時候就會有3個空閑進程,這個值大於MaxSpareServers=2的值。所以apache會自動關掉一個進程滿足MaxSpareServers=2的值。
(3)當有三個用戶同時訪問(通過本機上的三個ie瀏覽訪問虛擬主機上的apache服務器模擬該情景)
可以看到apache的進程有3個,而這三個進程都在處理用戶的請求,沒有多余的空閑進程產生。為什么呢?因為在上面我們設置了MaxClients的值為3。所以apache最多只會生成3個進程。
再看看這三個用戶訪問完成之后的apache進程數。
可以看到空閑的進程數又減少為2個。為什么呢?當三個用戶訪問完成之后三個用戶的進程都會關閉,這時候就會有3個空閑進程,這個值大於MaxSpareServers=2的值。所以apache會自動關掉一個進程滿足MaxSpareServers=2的值。
(4)當有四個用戶同時訪問(通過本機上的四個ie瀏覽訪問虛擬主機上的apache服務器模擬該情景)
可以看到雖然有四個用戶同時訪問,但是apache創建的進程數還是只有3個。就是說apache只對前面的3個用戶請求進行了處理。第4個用戶只能等待。
這個時候查看apache的TCP連接情況。(對於TCP連接不太理解的可以點擊查看)
可以看到這4個用戶都已經建立了連接。但是apache只處理了前面的3個請求。處理完3個請求在處理最后一個請求,這點可能從文件的打印內容看到。四個用戶幾乎是同時訪問的。
可以看到最后一個用戶的請求時間是前面三個用戶訪問完成之后開始的。
依次類推,當有7個用戶同時訪問時候又是什么樣的?只貼幾張圖,看了就明白了。
結論
如果從頭到尾詳細讀過本篇文章,會得出如下的結論:
1,apache是嚴格按照prefork模式的配置參數來進程分配和管理的。不像網上有些文章那樣修改了某個值,apache不起作用。只能說您改的不對,或者說您對上面的內容還不夠理解。
2,MaxClients值就是apache的最大進程數。不像網上有些文章說的這個值越大越好(有的文章既然推薦該值為4000),您可以從上面的進程圖中看到apache的每個進程的%MEM(內存占用百分比)值為0.5%左右。所以這個值的具體設置的最大數位:100/0.5 = 200。而這也只是在這個服務器只有一個apache的情況下。如果服務器有其他程序需要占用內存(比如mysql)這個值要小於200。你總不能把操作系統的所有內存都給apache吧?
3,每個瀏覽器是一個用戶,每個用戶就是一條進程。明白意思了吧?我的這台服務器的並發量只有200。就是說我的這台服務器只能支持同時200個用戶訪問,再多的用戶訪問就只能是等待。或者說我這台服務器只支持200個瀏覽器的訪問。關於服務器的並發我會在下面一片文章中詳細講解。
4,200的並發量很小嗎?要知道apache處理數據的速度是相當快的。一條正常的首頁訪問可能就一秒鍾處理完畢。所以在假想的狀態下,我的這台服務器,每分鍾可以訪問60*200=12000個用戶。每天可以訪問12000*60*24=17280000個用戶的訪問。這當然是在完全飽和的訪問狀態的假想數據。下一篇文章我會詳細講解網站並發,請求,連擊等內容。
5,如果訪問的用戶數大於MaxClients的數,多出的用戶不會立刻斷掉連接,還是會建立TCP連接。只不過會等待前面的用戶處理完在得到相應。在php.ini,http.conf,操作系統設定的超時時間內得不到相應才會斷掉連接。