概述:html
httpd 2.2以前(2.2也包含在內),不支持動態切換MPM。且在編譯時候,只能指定使用哪一種MPM。若是,提供了 prefork、worker、event ,要改變MPM,只能在啓動httpd服務器程序的時候,指定使用:linux
/usr/sbin/httpd /usr/sbin/httpd.event /usr/sbin/httpd.worker
中的那一個二進制程序。web
httpd 2.4就支持動態切換MPM,在配置文件中使用【LoadModule】指令就能夠實現MPM的切換了。條件:咱們編譯httpd時,要把:prefork、worker、event都編譯成模塊。apache
1、httpd服務器工做在 prefork 模型是一個進程服務響應一個用戶請求windows
啓動httpd服務緩存
[root@stu13 httpd-2.4]# ./bin/apachectl start [root@stu13 httpd-2.4]# pstree | grep httpd |-httpd---5*[httpd]
查看httpd服務器工做的MPM是什麼?安全
[root@stu13 httpd-2.4]# ./bin/httpd -M | grep mpm mpm_prefork_module (shared)
說明:bash
從【pstree】命令的顯示結果,能夠看到啓動httpd服務器時就啓動5個httpd服務進程用來準備接收web請求。服務器
固然這5個進程都是由會話領導進程(該進程的全部者是root管理員)fork()而來。主進程管理子進程,如:回收子進程、建立子進程等。而響應用戶訪問請求的則是子進程。網絡
當用戶向httpd服務器,發起訪問資源鏈接請求的時候,
httpd服務器會根據<IfModule mpm_prefork_module>指令定義的參數維護進程池中的進程。
當用戶向httpd服務器發起鏈接請求的時候,httpd的主進程就會從進程池中派一個子進程來負責響應用戶的請求,若是該服務器的併發請求量爲100的話,一會兒就使用完,進程池中空閒進程數(咱們定義了進程池中最小空閒進程數爲5),90個用戶的鏈接請求只好等待。這時主進程fork()出子進程,而後才能響應處於等待90個用戶的鏈接請求。雖然是一個進程負責響應一個用戶的請求,當該進程完成了用戶的請求以後,會話領導進程並不會立刻kill掉該進程。而是使用了重用的機制。意思是在進程的生命週期內它響應完負責的用戶請求後,還能夠響應後續的用戶請求。這是爲了減小消耗在建立進程上面的時間。實現快速地響應用戶請求的一種機制。假如過了一會,咱們的httpd服務器已經處理完這100個併發用戶的請求了。根據後續用戶的併發用戶數目有三種狀況:
(1)、後續的併發用戶數小於10的話:
領導會話進程,爲了響應這100個併發請求的用戶,而fork()出的子進程,除了用來響應後面的
用戶鏈接請求的進程以外,其它空閒進程通通被kill掉。只保留必定數目的空閒進程。如最小空 閒進程數爲:5( MinSpareServers 5)、最大空閒進程數爲:10(MaxSpareServers 10)
(2)、後續的併發用戶數大於10而小於150的話:
響應100個併發用戶鏈接請求的進程都獲得了重用,但因爲在處理過程當中進程要不斷申請和釋放 內存,次數(處理用戶的請求次數)多了就會形成一些內存垃圾,就會影響系統的穩定性且影響了
系統的有效利用,因此會話進程的生命週期是有限的,會話管理進程要kill掉一些進程。而在進
程的生命週期內,可以處理的用戶請求數量是能夠
設置的。httpd 2.2 版本和httpd 2.4版本的設置以下:
httpd 2.2 MaxRequestsPerChild 4000 httpd 2.4 MaxConnectionsPerChild 0
因此,領導進程fork()子進程是不免的。意思是說:消耗在建立進程和銷燬進程中的時間是不免的。
若是,咱們的服務器性能很好的話,能夠增長進程能夠處理的用戶請求的數量,可是可能會影響
系統的穩定,產生一些內存垃圾。可是減小了fork()進程和kill進程的時間。在必定的程序上,
提升了響應用戶鏈接請求的速度。
若是,不調整進程的生命週期內能夠處理多少個用戶的鏈接請求數的話,就要花費大量的時間
(若是咱們的服務器比較繁忙的話)fork()進程,kill進程.會在必定程度上影響響應用戶請求的
速度的。
(3)、後續的併發用戶請求數大於150的話;
有可能會出現,有可能會出現鏈接請求超時的狀況。若是咱們的接收鏈接的緩存不夠大的話,
有些用戶的請求鏈接都沒法接收下來。無論服務器是否可以處理,都應該把請求接收下來再說。咱們能夠調大該緩存:
[root@stu13 ~]# cat /proc/sys/net/ipv4/tcp_mem 46368 61824 92736 [root@stu13 ~]# cat /proc/sys/net/ipv4/tcp_rmem 4096 87380 1978368 [root@stu13 ~]# cat /proc/sys/net/ipv4/tcp_wmem 4096 16384 1978368
固然,若是服務器的性能很好的話,咱們能夠調大處理的併發用戶數量,httpd 2.2 與 httpd 2.4中定義以下:
httpd 2.2 MaxClients 300 httpd 2.4 MaxRequestWorkers 150
可是,若是調大了併發用戶數(服務器的性能條件下),雖然一次性能夠處理的用戶請求數增長了,可是在服務器上進程的切換的次數也增長了。由於進程的切換是浪費CPU時間週期的。因此,咱們要爲服務器定作一個黃金比例。既能處理更多的用戶併發請求,浪費在進程間切換的時間又很合理。
prefork模型的配置以下:
<IfModule mpm_prefork_module> StartServers 5 服務器啓動時就fork()出5個進程,等待用戶鏈接請求 MinSpareServers 5 服務器在等待客戶端鏈接請求的最小空閒進程數。 MaxSpareServers 10 服務器在等待客戶端鏈接請求的最大空閒進程數。 MaxRequestWorkers 150 容許最大的用戶併發請求數。 MaxConnectionsPerChild 0 在進程的生命週期內,它能夠服務多少個請求。 </IfModule>
httpd服務器剛啓動沒有接收客戶端鏈接請求時候,所佔據常駐物理內存大小爲
[root@stu13 ~]./test/test.sh Date: 2014/08/10_16:30:05 user pid vsz rss comm root 19506 5252 2196 httpd daemon 19507 5252 1684 httpd daemon 19508 5252 1684 httpd daemon 19509 5252 1684 httpd daemon 19510 5252 1684 httpd daemon 19511 5252 1684 httpd --------------------total_Rss--------------------- 10616
說明:
httpd服務器全部進程佔據的常駐物理內存集約爲:10M.
二、對該httpd進行壓力測試,併發用戶數爲:100,共發起3000個請求。暫停2秒。共測試40次。
[root@stu13 httpd-2.4]# declare -i num=40 [root@stu13 httpd-2.4]# while [ "$num" -gt 0 ]; do ab -c 100 -n 3000 http://192.168.60.99/index.html; sleep 2 ; let num--; done ..... Date: 2014/08/10_16:33:02 user pid vsz rss comm root 19506 5252 2216 httpd daemon 19509 5384 2264 httpd daemon 20311 5384 2244 httpd daemon 20459 5384 2244 httpd daemon 20519 5384 2244 httpd daemon 20555 5384 2244 httpd daemon 20615 5384 2244 httpd daemon 20856 5384 2244 httpd daemon 20944 5384 2244 httpd daemon 21036 5384 2244 httpd daemon 21089 5384 2244 httpd --------------------total_Rss--------------------- 24676 Date: 2014/08/10_16:33:03 user pid vsz rss comm root 19506 5252 2216 httpd daemon 19509 5384 2264 httpd daemon 20311 5384 2244 httpd daemon 20459 5384 2244 httpd daemon 20519 5384 2244 httpd daemon 20555 5384 2244 httpd daemon 20615 5384 2244 httpd daemon 20856 5384 2244 httpd daemon 20944 5384 2244 httpd daemon 21036 5384 2244 httpd daemon 21089 5384 2244 httpd --------------------total_Rss--------------------- 24676
說明:
進行壓力測試後,httpd服務器常駐內存集大小爲:24675,約爲:24M.
prefork模式,使用一個進程服務一個用戶請求。因爲進程打開的資源是獨享,若是,用戶訪問的資源相同也要打開屢次的。可是,比較穩定的。
因爲prefork模型的,服務用戶請求的會話進程要不斷建立、銷燬。也就是進程號PID不斷髮生變化,因此很難作到把會話進程綁定在CPU上(使用進程號作綁定)。若是咱們的服務器,有多顆CUP的話,可使用指定的CPU處理中斷請求。
prefork 工做模式,負責監聽/響應的是主進程(屬主爲root的httpd會話領導進程)是基於 select/poll 實現網絡IO利復的。這樣服務器就能夠實現併發了。但因爲 select/poll自己的侷限性,理論上併發能力上限爲:1024。
2、worker 工做模型是:
一個線程服務一個用戶的鏈接請求。線程比進程更輕量級,建立和消耗的速度比進程的建立和消耗要快得多。線程之間還能夠共享資源,如:打開的文件描述符等。這樣若是:兩個客戶端請求的是同一個文件,就不須要從磁盤上加載兩次了,速度要比基於進程的響應速度快。但線程的管理要比進程複雜得多。線程之間不少資源是共享的,因此它沒有prefork模型,一個進程服務一個服務請求那麼安全穩定。何況,linux不是真線程的操做系統,worker 與 prefork 這兩種模型,在linux上的表現幾乎都同樣。一般使用prefork模型。windows 是真線程的操做系統,它對線程的支持就很好。
啓動httpd服務器
[root@stu13 httpd-2.4]# ./bin/apachectl start [root@stu13 httpd-2.4]# pstree | grep httpd |-httpd---2*[httpd---26*[{httpd}]]
查看當前httpd服務器使用的MPM是什麼?
[root@stu13 httpd-2.4]# ./bin/httpd -M | grep mpm mpm_worker_module (shared)
說明:
從【pstree】的顯示結果能夠看出,httpd服務器剛起動就建立了2個子進程,且這2個子進程又建立了25個線程用來等待服務客戶端的鏈接請求的。剛啓動httpd服務器時(沒有接收客戶端鏈接請求),
worker 的模型以下:分析評估應用,能夠調節下述的參數來調節httpd服務器的併發能力的。
<IfModule mpm_worker_module> StartServers 2 服務器剛啓動的時候就啓動兩個進程,這兩個進程共生 成25個線程用來等待客戶端的鏈接請求的。 MinSpareThreads 25 最少保持25個線程處於空閒狀態 MaxSpareThreads 75 最多保持75個純程處於空閒狀態 ThreadsPerChild 25 每一個進程最多容許生成25個線程 MaxRequestWorkers 150 併發數爲150 MaxConnectionsPerChild 0 在線程的生命週期內, 線程容許服務的客戶端鏈接的個數。 </IfModule>
一、httpd服務器剛啓動沒有接收客戶端鏈接請求時候,所佔據常駐物理內存大小爲
[root@stu13 ~]./test/test.sh Date: 2014/08/10_16:40:34 user pid vsz rss comm root 23955 5428 2372 httpd daemon 23956 283160 2092 httpd daemon 23957 283160 2096 httpd --------------------total_Rss--------------------- 6560
二、對該httpd進行壓力測試,
[root@stu13 httpd-2.4]# declare -i num=40 [root@stu13 httpd-2.4]# while [ "$num" -gt 0 ]; do ab -c 100 -n 3000 http://192.168.60.99/index.html; sleep 2 ; let num--; done ..... Date: 2014/08/10_16:59:37 user pid vsz rss comm root 28920 5428 2384 httpd daemon 28921 285476 3740 httpd daemon 28922 285476 3752 httpd daemon 29110 285476 3720 httpd daemon 30774 285476 3712 httpd --------------------total_Rss--------------------- 17308 Date: 2014/08/10_16:59:38 user pid vsz rss comm root 28920 5428 2384 httpd daemon 28921 285476 3740 httpd daemon 28922 285476 3752 httpd daemon 29110 285476 3720 httpd --------------------total_Rss--------------------- 13596
說明:
由於,線程池中定義了,每一個進程最多能夠生成25個線程, 假如:此時,httpd服務器共有4個進程,每一個進程都產生了25個線程,4個進程都滿負荷運轉了,
可是,仍是有不少用戶在等待,這時候主進程(會話領導進程),又會fork()出進程,子進程又生成線程來服務客戶端的鏈接請求的。進程的線程在不斷服務鏈接請求,會不斷申請內存釋放內存,次數多了,不免會產生內存垃圾的。影響系統的穩定。因此,httpd服務器要不斷使用新的進程替換老的進程。、
3、event:
是基於信號驅動I/O 通知機制。工做方式是:使用每線程服務N個用戶請求。event的工做模型要優於prefork和worker.
啓動httpd服務
[root@stu13 httpd-2.4]# ./bin/apachectl start [root@stu13 httpd-2.4]# pstree | grep httpd |-httpd---2*[httpd---26*[{httpd}]]
一、查看 httpd服務器的工用模型
[root@stu13 httpd-2.4]# ./bin/httpd -M | grep mpm mpm_event_module (shared)
httpd服務器工做在event模式下線程池的控制。也worker的線程池很類似,但event的工做方式是:一個線程服務N個用戶請求。
<IfModule mpm_event_module> StartServers 2 服務器啓動的時候就生成2個子進程, 該子進程共生成25個線程等待客戶端的鏈接請求 MinSpareThreads 25 線程池中保持最少25個空閒線程。 MaxSpareThreads 75 線程池中保持最多75個空閒線程。 ThreadsPerChild 25 每一個進程最多能夠生成25個線程。 MaxRequestWorkers 150 最大併發用戶數爲:150 MaxConnectionsPerChild 0 線程可以服務的用戶請求數據。 0 表示不作限定。 </IfModule>
httpd服務器沒有服務用戶請求時,所佔據常駐物理集大小爲
[root@stu13 ~]# test/test.sh Date: 2014/08/10_17:04:58 user pid vsz rss comm root 30948 5436 2352 httpd daemon 30949 283168 2084 httpd daemon 30950 283168 2088 httpd --------------------total_Rss--------------------- 6524
二、對該httpd進行壓力測試,
[root@stu13 httpd-2.4]# declare -i num=40 [root@stu13 httpd-2.4]# while [ "$num" -gt 0 ]; do ab -c 100 -n 3000 http://192.168.60.99/index.html; sleep 2 ; let num--; done ..... Date: 2014/08/10_17:08:26 user pid vsz rss comm root 30948 5436 2352 httpd daemon 30949 287172 6076 httpd daemon 30950 288372 6704 httpd --------------------total_Rss--------------------- 15132 Date: 2014/08/10_17:08:27 user pid vsz rss comm root 30948 5436 2352 httpd daemon 30949 287172 6076 httpd daemon 30950 288372 6704 httpd --------------------total_Rss--------------------- 15132
說明:
經過併發測試後,進程的進程號並無改變。則工做在 worker模型下的,壓力測試後,進程號已經發生了改變。
event 和 worker的線程池的配置都同樣,因爲 event 是基於信號驅動I/O 通知機制,每一個進程能夠服務N個用戶請求。
而worker是一個線程服務一個請求。在請求沒有完成以前,該線程是與它服務的請求綁定的。
worker須要大量的建立進程生成線程,銷燬線程,殺死進程的過程。而event則不須要頻繁的建立銷燬。