一:apache的工模式有三種: prefork、woker 與event.
preforkMPM
使用多個(gè)子進(jìn)程,每個(gè)子進(jìn)程只有一個(gè)線程。每個(gè)進(jìn)程在某個(gè)確定的時(shí)間只能維持一個(gè)連接。在大多數(shù)平臺(tái)上,PreforkMPM在效率上要比Worker MPM要高,但是內(nèi)存使用大得多。prefork的無線程設(shè)計(jì)在某些情況下將比worker更有優(yōu)勢(shì):它可以使用那些沒有處理好線程安全的第三方模塊,并且對(duì)于那些線程調(diào)試?yán)щy的平臺(tái)而言,它也更容易調(diào)試一些。
? workerMPM 使用多個(gè)子進(jìn)程,每個(gè)子進(jìn)程有多個(gè)線程。每個(gè)線程在某個(gè)確定的時(shí)間只能維持一個(gè)連接。通常來說,在一個(gè)高流量的HTTP服務(wù)器上,Worker MPM是個(gè)比較好的選擇,因?yàn)閃orker MPM的內(nèi)存使用比PreforkMPM要低得多。但worker MPM也由不完善的地方,如果一個(gè)線程崩潰,整個(gè)進(jìn)程就會(huì)連同其所有線程一起"死掉".由于線程共享內(nèi)存空間,所以一個(gè)程序在運(yùn)行時(shí)必須被系統(tǒng)識(shí)別為"每個(gè)線程都是安全的"。
一般來說我們的ApacheHttp Server都是裝在Unix/Linux下的,而且是采用源碼編譯的方式來安裝的,我們能夠指定在編譯時(shí)Apache就采用哪種模式,為了明確我們目前的Apache采用的是哪種模式在工作,我們還可以使用httpd –l命令即在Apache的bin目錄下執(zhí)行httpd –l,來確認(rèn)我們使用的是哪種模式。
這邊,我們使用Apache配置語言中的” IfModule”來自動(dòng)選擇模式的配置。
1.Prefork MPM實(shí)現(xiàn)了一個(gè)非線程的、預(yù)派生的web服務(wù)器。它在Apache啟動(dòng)之初,就先預(yù)派生一些子進(jìn)程,然后等待連接;可以減少頻繁創(chuàng)建和銷毀進(jìn)程的開銷,每個(gè)子進(jìn)程只有一個(gè)線程,在一個(gè)時(shí)間點(diǎn)內(nèi),只能處理一個(gè)請(qǐng)求。這是一個(gè)成熟穩(wěn)定,可以兼容新老模塊,也不需要擔(dān)心線程安全問題,但是一個(gè)進(jìn)程相對(duì)占用資源,消耗大量?jī)?nèi)存,不擅長(zhǎng)處理高并發(fā)的場(chǎng)景。(如圖-1)

[root@redis sbin]# httpd -V
Server version: Apache/2.4.6 (CentOS)
Server built:? Nov 14 2016 18:04:44
Server's Module Magic Number: 20120211:24
Server loaded:? APR 1.4.8, APR-UTIL 1.5.2
Compiled using: APR 1.4.8, APR-UTIL 1.5.2
Architecture:? 64-bit
Server MPM:? ? prefork
threaded:? ? no
forked:? ? yes (variable process count)
Server compiled with....
-D APR_HAS_SENDFILE
-D APR_HAS_MMAP
-D APR_HAVE_IPV6 (IPv4-mapped addresses enabled)
-D APR_USE_SYSVSEM_SERIALIZE
-D APR_USE_PTHREAD_SERIALIZE
-D SINGLE_LISTEN_UNSERIALIZED_ACCEPT
-D APR_HAS_OTHER_CHILD
-D AP_HAVE_RELIABLE_PIPED_LOGS
-D DYNAMIC_MODULE_LIMIT=256
-D HTTPD_ROOT="/etc/httpd"
-D SUEXEC_BIN="/usr/sbin/suexec"
-D DEFAULT_PIDLOG="/run/httpd/httpd.pid"
-D DEFAULT_SCOREBOARD="logs/apache_runtime_status"
-D DEFAULT_ERRORLOG="logs/error_log"
-D AP_TYPES_CONFIG_FILE="conf/mime.types"
-D SERVER_CONFIG_FILE="conf/httpd.conf"
目前使用的是prefork的模式,這種模式比較穩(wěn)定。
[root@redis sbin]# ps -ef | grep httpd
root? ? ? 1045? ? 1? 0 Aug22 ?? ? ? ? 00:00:27 /usr/sbin/httpd -DFOREGROUND
apache? 11412? 1045? 0 Aug27 ?? ? ? ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
apache? 11413? 1045? 0 Aug27 ?? ? ? ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
apache? 11414? 1045? 0 Aug27 ?? ? ? ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
apache? 11415? 1045? 0 Aug27 ?? ? ? ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
apache? 11416? 1045? 0 Aug27 ?? ? ? ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
apache? 14476? 1045? 0 Aug27 ?? ? ? ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
apache? 14477? 1045? 0 Aug27 ?? ? ? ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
apache? 14478? 1045? 0 Aug27 ?? ? ? ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
apache? 14524? 1045? 0 Aug27 ?? ? ? ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
apache? 18911? 1045? 0 Aug29 ?? ? ? ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
其中 kill 掉1045 這個(gè)master進(jìn)程 還是可以對(duì)外提供服務(wù)的。
如何配置在Apache的配置文件httpd.conf的配置方式:
StartServers?????????????5
MinSpareServers??????????5
MaxSpareServers?????????10
MaxRequestWorkers??????250
MaxConnectionsPerChild???1000
StartServers
# 服務(wù)器啟動(dòng)時(shí)建立的子進(jìn)程數(shù)量,prefork默認(rèn)是5,
MinSpareServers
# 空閑子進(jìn)程的最小數(shù)量,默認(rèn)5;如果當(dāng)前空閑子進(jìn)程數(shù)少于MinSpareServers ,那么Apache將以最大每秒一個(gè)的速度產(chǎn)生新的子進(jìn)程。此參數(shù)不要設(shè)的太大。
MaxSpareServers
#空閑子進(jìn)程的最大數(shù)量,默認(rèn)10;如果當(dāng)前有超過MaxSpareServers數(shù)量的空閑子進(jìn)程,那么父進(jìn)程會(huì)殺死多余的子進(jìn)程。次參數(shù)也不需要設(shè)置太大,如果你將其設(shè)置比MinSpareServers 小,Apache會(huì)自動(dòng)將其修改為MinSpareServers +1的數(shù)量。
MaxRequestWorkers
#限定服務(wù)器同一時(shí)間內(nèi)客戶端最大接入的請(qǐng)求數(shù)量,默認(rèn)是256;任何超過了MaxRequestWorkers限制的請(qǐng)求都要進(jìn)入等待隊(duì)列,一旦一個(gè)個(gè)連接被釋放,隊(duì)列中的請(qǐng)求才將得到服務(wù),如果要增大這個(gè)數(shù)值,必須先增大ServerLimit。在Apache2.3.1版本之前這參數(shù)MaxRequestWorkers被稱為MaxClients。
MaxConnectionsPerChild
#每個(gè)子進(jìn)程在其生命周期內(nèi)允許最大的請(qǐng)求數(shù)量,如果請(qǐng)求總數(shù)已經(jīng)達(dá)到這個(gè)數(shù)值,子進(jìn)程將會(huì)結(jié)束,如果設(shè)置為0,子進(jìn)程將永遠(yuǎn)不會(huì)結(jié)束。在Apache2.3.9之前稱之為MaxRequestsPerChild。
這里建議設(shè)置為非零,注意原因:
1).能夠防止(偶然的)內(nèi)存泄漏無限進(jìn)行,從而耗盡內(nèi)存。
2).給進(jìn)程一個(gè)有限壽命,從而有助于當(dāng)服務(wù)器負(fù)載減輕的時(shí)候減少活動(dòng)進(jìn)程的數(shù)量(重生的機(jī)會(huì))。
##########################################################################################
2、Worker MPM(支持web高并發(fā)的需求)
和prefork模式相比,worker使用了多進(jìn)程和多線程的混合模式,worker模式也同樣會(huì)先預(yù)派生一些子進(jìn)程,然后每個(gè)子進(jìn)程創(chuàng)建一些線程,同時(shí)包括一個(gè)監(jiān)聽線程,每個(gè)請(qǐng)求過來會(huì)被分配到一個(gè)線程來服務(wù)。線程比起進(jìn)程會(huì)更輕量,因?yàn)榫€程是通過共享父進(jìn)程的內(nèi)存空間,因此,內(nèi)存的占用會(huì)減少一些,在高并發(fā)的場(chǎng)景下會(huì)比prefork有更多可用的線程,表現(xiàn)會(huì)更優(yōu)秀一些;另外,如果一個(gè)線程出現(xiàn)了問題也會(huì)導(dǎo)致同一進(jìn)程下的線程出現(xiàn)問題,如果是多個(gè)線程出現(xiàn)問題,也只是影響Apache的一部分,而不是全部。由于用到多進(jìn)程多線程,需要考慮到線程的安全了,在使用keep-alive長(zhǎng)連接的時(shí)候,某個(gè)線程會(huì)一直被占用,即使中間沒有請(qǐng)求,需要等待到超時(shí)才會(huì)被釋放(該問題在prefork模式下也存在)。(如圖-2)

圖-2
如何配置在Apache的配置文件httpd.conf的配置方式:
StartServers?????????????3
ServerLimit?16
MinSpareThreads?????????75
MaxSpareThreads????????250
ThreadsPerChild?????????25
MaxRequestWorkers??????400
MaxConnectionsPerChild???1000
StartServers
#服務(wù)器啟動(dòng)時(shí)建立的子進(jìn)程數(shù)量,在workers模式下默認(rèn)是3.
ServerLimit
#系統(tǒng)配置的最大進(jìn)程數(shù)量
MinSpareThreads
#空閑子進(jìn)程的最小數(shù)量,默認(rèn)75
MaxSpareThreads
#空閑子進(jìn)程的最大數(shù)量,默認(rèn)250
ThreadsPerChild
#每個(gè)子進(jìn)程產(chǎn)生的線程數(shù)量,默認(rèn)是64
MaxRequestWorkers /MaxClients
#限定服務(wù)器同一時(shí)間內(nèi)客戶端最大接入的請(qǐng)求數(shù)量.
MaxConnectionsPerChild
#每個(gè)子進(jìn)程在其生命周期內(nèi)允許最大的請(qǐng)求數(shù)量,如果請(qǐng)求總數(shù)已經(jīng)達(dá)到這個(gè)數(shù)值,子進(jìn)程將會(huì)結(jié)束,如果設(shè)置為0,子進(jìn)程將永遠(yuǎn)不會(huì)結(jié)束。在Apache2.3.9之前稱之為MaxRequestsPerChild。
這里建議設(shè)置為非零,注意原因:
1).能夠防止(偶然的)內(nèi)存泄漏無限進(jìn)行,從而耗盡內(nèi)存。
2).給進(jìn)程一個(gè)有限壽命,從而有助于當(dāng)服務(wù)器負(fù)載減輕的時(shí)候減少活動(dòng)進(jìn)程的數(shù)量(重生的機(jī)會(huì))。
Worker模式下所能同時(shí)處理的請(qǐng)求總數(shù)是由子進(jìn)程總數(shù)乘以ThreadsPerChild 值決定的,應(yīng)該大于等于MaxRequestWorkers。如果負(fù)載很大,現(xiàn)有的子進(jìn)程數(shù)不能滿足時(shí),控制進(jìn)程會(huì)派生新的子進(jìn)程。默認(rèn)最大的子進(jìn)程總數(shù)是16,加大時(shí) 也需要顯式聲明ServerLimit(最大值是20000)。需要注意的是,如果顯式聲明了ServerLimit,那么它乘以 ThreadsPerChild的值必須大于等于MaxRequestWorkers,而且MaxRequestWorkers必須是ThreadsPerChild的整數(shù)倍,否則 Apache將會(huì)自動(dòng)調(diào)節(jié)到一個(gè)相應(yīng)值。
##########################################################################################
3、Event MPM
這是Apache最新的工作模式,它和worker模式很像,不同的是在于它解決了keep-alive長(zhǎng)連接的時(shí)候占用線程資源被浪費(fèi)的問題,在event工作模式中,會(huì)有一些專門的線程用來管理這些keep-alive類型的線程,當(dāng)有真實(shí)請(qǐng)求過來的時(shí)候,將請(qǐng)求傳遞給服務(wù)器的線程,執(zhí)行完畢后,又允許它釋放。這增強(qiáng)了在高并發(fā)場(chǎng)景下的請(qǐng)求處理。

圖-3
如何配置在Apache的配置文件httpd.conf的配置方式:
StartServers?????????????3
ServerLimit?16
MinSpareThreads?????????75
MaxSpareThreads????????250
ThreadsPerChild?????????25
MaxRequestWorkers??????400
MaxConnectionsPerChild???1000
Apache httpd 能更好的為有特殊要求的站點(diǎn)定制。例如,要求 更高伸縮性的站點(diǎn)可以選擇使用線程的 MPM,即 worker 或 event; 需要可靠性或者與舊軟件兼容的站點(diǎn)可以使用 prefork。