Linux Nginx(master-slave)、Apache(woker、prefork) Working Mode Research

Andrew.Hann發表於2015-10-22

catalog

1. Apache工作模式
2. Nginx工作模式

 

1. Apache工作模式

Apache伺服器支援三種工作模式(Apache稱之為MPM,簡寫為Multi-Processing Module,譯為 多處理模組),分別為

1. prefork模式
2. worker模式
3. event模式
//在舊的版本只支援profork和worker模式, 只有較新的版本才支援event模式
4. WinNT MPM模式

不同的工作模式有不同的優缺點,會影響到Apache的效能和可伸縮性。檢視Apache伺服器的工作模式,可以使用命令httpd -l

[root@iZ23er0navtZ html]# httpd -l
Compiled in modules:
  core.c
  prefork.c
  http_core.c
  mod_so.c

0x1: prefork MPM(prefork模式)

profork採用了程式處理請求的模式。它適合在沒有執行緒安全庫和需要避免執行緒相容性的系統中執行。由於程式間互不受影響,因此它可獲得很高的穩定性。 但由於程式比較消耗資源,因此在大量請求的伺服器中不能獲得較高的效能
一個單獨的控制程式(父程式)負責產生子程式,這些子程式用於監聽請求並作出應答。Apache總是試圖保持一些備用的(spare)或是空閒的子程式用於迎接即將到來的請求。這樣客戶端就無需在得到服務前等候子程式的產生
在Unix系統中,父程式通常以root身份執行以便邦定80埠(注意這裡是先繫結再fork的,所以意味著所有的子程式都監聽了80埠),而 Apache產生的子程式通常以一個低特權的使用者執行。User和Group指令用於配置子程式的低特權使用者。執行子程式的使用者必須要對他所服務的內容有讀取的許可權,但是對服務內容之外的其他資源必須擁有儘可能少的許可權。
子程式的個數會隨著請求量的大小動態調整。調整的策略與perfork的配置息息相關,httpd.conf的配置檔案有以下配置:

<IfModule prefork.c>
/*
1. StartServers為Apache預設啟動的程式數(至少要大於等於1,小於1時強制設定為1)
這個連線數預設為5,不宜設定過大,可以由Apache根據請求逐漸增加程式數,但是啟動程式時會增加耗時
這個引數設定不宜過大還有一個好處: 跟Tomcat進行叢集時,可以根絕請求逐漸增加Apache跟Tomcat的連線。所以這個引數不宜設定過大,無謂增加Apache跟Tomcat的連線(Apache一旦跟Tomcat建立連線後,就不會釋放,直到Timeout)
*/
StartServers      50

/*
2. MinSpareServers: 最小空閒程式
MinSpareServers指令設定空閒子程式的最小數量。所謂空閒子程式是指沒有正在處理請求的子程式。如果當前空閒子程式數少於MinSpareServers ,那麼Apache將以第一秒一個,第二秒兩個,第三秒四個,按指數遞增個數的速度產生新的子程式 
*/
MinSpareServers   100

/*
3. MaxSpareServers: 最大空閒程式
MaxSpareServers指令設定空閒子程式的最大數量。所謂空閒子程式是指沒有正在處理請求的子程式。如果當前有超過MaxSpareServers數量的空閒子程式,那麼父程式將殺死多餘的子程式 
可以調整這兩個引數,但是這兩個引數的值不能設得太大,否則apache程式太多,會導致效能急劇下降,因為CPU頻繁地在進行程式上下文切換排程
*/
MaxSpareServers   200

/*
4. ServerLimit: 在Apache的生命週期內,限制MaxClients的最大值
*/
ServerLimit      1024

/*
5. MaxClients: 最大的併發請求數
*/
MaxClients       1024

/*
6. MaxRequestsPerChild:每個程式處理的最大請求數
"MaxRequestsPerChild指令設定每個子程式在其生存期內允許伺服的最大請求數量。到達MaxRequestsPerChild的限制後,子程式將會結束。如果MaxRequestsPerChild為"0",子程式將永遠不會結束
將MaxRequestsPerChild設定成非零值有兩個好處:
    1) 可以防止(偶然的)記憶體洩漏無限進行,從而耗盡記憶體 
    2) 給程式一個有限壽命,從而有助於當伺服器負載減輕的時候減少活動程式的數量  
*/
MaxRequestsPerChild  16
</IfModule>

配置檔案對apache行為的影響如下

1. 控制程式(以root許可權啟動的主程式)先建立"StartServers"個子程式
2. 當空閒程式數小於MinSpareServers時,繼續建立子程式,直到滿足空閒程式數大於等於MinSpareServers
3. 當併發請求高時而空閒程式數小於MaxSpareServers時會繼續建立子程式,最多可以建立MaxClients個 
4. 當併發高峰過去時,空閒程式的數量大於MaxSpareServers時會刪除多餘的子程式,直到剩MaxSpareServers為止 
5. 當子程式處理的連線數超過MaxRequestsPerChild時,自動關閉,當MaxRequestsPerChild為0時這沒有這個限制 

0x2: worker模式

worker模式採用了多程式多執行緒的處理方式。使用執行緒來處理請求(一個執行緒處理一個請求),因此它可以佔用更少的資源而處理比prefork模式更多的請求。 由於它採取N個程式派生N*M個執行緒的模式,仍然獲得了較高的穩定性(一個程式出問題,或導致其子執行緒出問題)
每個程式能夠擁有的執行緒數量是固定的。伺服器會根據負載情況增加或減少程式數量。一個單獨的控制程式(父程式)負責子程式的建立
每個子程式能夠建立ThreadsPerChild數量的服務執行緒和一個監聽執行緒,該監聽執行緒監聽接入請求並將其傳遞給服務執行緒處理和應答
Apache總是試圖維持一個備用(spare)或是空閒的服務執行緒池。這樣,客戶端無須等待新執行緒或新程式的建立即可得到處理
在Unix中,為了能夠繫結80埠,父程式一般都是以root身份啟動,隨後,Apache以較低許可權的使用者建立子程式和執行緒。User和Group指令用於配置Apache子程式的許可權。雖然子程式必須對其提供的內容擁有讀許可權,但應該儘可能給予他較少的特權。另外,除非使用了suexec ,否則,這些指令配置的許可權將被CGI指令碼所繼承
相對於prefork,worker是2.0版中全新的支援多執行緒和多程式混合模型的MPM。由於使用執行緒來處理,所以可以處理相對海量的請求,而系統資源的開銷要小於基於程式的伺服器。但是,worker也使用了多程式,每個程式又生成多個執行緒,以獲得基於程式伺服器的穩定性。這種MPM的工作方式將是Apache 2.0的發展趨勢

<IfModule worker.c>
//1. StartServers: 伺服器啟動時開啟的程式數
StartServers        20

//2. ServerLimit: Apache的生命週期內,限制MaxClients的最大值
ServerLimit         40

//3. MaxClients: 最大的併發請求數
MaxClients          1280

//4. MinSpareThreads: 最小的執行緒空閒數
MinSpareThreads     128

//5. MaxSpareThreads: 最大的執行緒空閒數
MaxSpareThreads     256

//6. ThreadsPerChild: 每一個程式可以產生的執行緒數
ThreadsPerChild     64

//7. MaxRequestsPerChild: 一個執行緒可以處理的最多的請求數(執行緒複用),如請求超過該設定則殺死執行緒,0表示永不過期
MaxRequestsPerChild  128000
</IfModule>

0x3: event模式

The event Multi-Processing Module (MPM) is designed to allow more requests to be served simultaneously by passing off some processing work to supporting threads, freeing up the main threads to work on new requests. It is based on the worker MPM, which implements a hybrid multi-process multi-threaded server. Run-time configuration directives are identical to those provided by worker.

0x4: WinNT MPM

Apache httpd 的 Windows 版本現在更有效率了,因為 mpm_winnt 能使用原生網路特性取代在 Apache httpd 1.3 中使用的 POSIX 層。它也可以擴充套件到其它平臺 來使用專用的 MPM

# WinNT MPM
# ThreadsPerChild: constant number of worker threads in the server process
# MaxRequestsPerChild: maximum  number of requests a server process serves
<IfModule mpm_winnt_module>
ThreadsPerChild      150  //修改這個值即可
MaxRequestsPerChild    0
</IfModule>

0x5: apache"驚群"現象與解決方案

無論是上面那個MPM被選擇,都有一問題就是主程式先監聽80埠,然後又fork出子程式。所以可以知道,fork出來的每個子程式都在監聽80埠,如果這時候有請求過來就會出現所有的空閒程式都回來搶這個fd,也就是這些程式都被喚醒了,但是最終只有一個程式能夠拿到這個fd進行處理,其他程式因為拿不到程式而再次進入休眠狀態,這就是"驚群"現象
apache的prefork模型下的處理方式如下如所示

apache通過在每個accept()函式上 增加互斥鎖和條件變數 來解決這個驚群問題。保證每個請求只會被一個執行緒剛好拿到,不會影響其他執行緒

1. 條件變數與互斥鎖不同,條件變數是用來等待而不是用來上鎖的。條件變數用來自動阻塞一個執行緒,直到某特殊情況發生為止。通常條件變數和互斥鎖同時使用
2. 互斥鎖提供互斥機制(CPU排程),條件變數提供訊號機制 
3. 每次一個新的客戶請求過來,正在監聽的執行緒與該請求建立連線,並變為worker工作者執行緒。讓出監聽者角色時它同時傳送訊號到條件變數,並釋放鎖。這樣在空閒(idle)狀態的一個執行緒將被喚醒並獲得鎖 
4. 也就是說:條件變數保證了其他執行緒在等待條件變化期間處於睡眠;互斥鎖保證一次只有一個執行緒被喚醒

Relevant Link:

http://httpd.apache.org/docs/2.4/mod/worker.html
http://httpd.apache.org/docs/2.2/mod/worker.html
http://httpd.apache.org/docs/2.4/mod/event.html
http://httpd.apache.org/docs/2.4/mpm.html
http://www.phpernote.com/php-template/1119.html
http://hao.jser.com/archive/8381/
http://oohcode.com/2015/10/09/apache-and-nginx/
http://www.ccvita.com/299.html
http://wwdhks.blog.51cto.com/839773/871694

 

2. Nginx工作模式

關於nginx的工作模式請參閱另一篇文章

Relevant Link:

http://www.cnblogs.com/LittleHann/p/4893028.html

 

Copyright (c) 2015 LittleHann All rights reserved

 

相關文章