Apache MPMs Nginx事件驅動

2021-09-17 19:09:24 字數 4585 閱讀 4242

mpm全稱是多道處理模組,我們都知道apache是以模組化方式設計的.那麼mpm用來決定apache如何處理使用者請求的.是通過乙個程序處理乙個請求,還是乙個執行緒處理乙個請求.當前mpm有三種可以選擇的方式:

雖然有以上三種方式,但是要注意在任何時間,必須有乙個,而且只能有乙個mpm被使用.那麼下面就介紹一下這三種處理方式的區別.

在這種工作模型下,apache程序分為master程序跟worker程序.web服務啟動就是啟動master程序,隨之master程序會啟動若干個worker子程序.master程序的工作就是管理worker子程序.而worker子程序的工作就是處理使用者請求.當使用者發起乙個請求,apache就會從空閒的子程序中選擇乙個處理這個使用者請求.

這種處理方式有以下幾點好處:

但是worker子程序的個數限制於apache配置檔案中如下幾個條目的限制

同時, 一般master程序使用root使用者啟動,這樣方便master程序監聽80埠,以及管理程序.而餘下的worker子程序則是以apache配置檔案中user指令指定的使用者啟動.這樣子是為了減少worker子程序的許可權.保證安全.

執行ps可以看出只有乙個master程序以root使用者方式啟動

prefork的缺點很明顯,乙個worker程序處理乙個請求,併發不會高.而且程序占用的資源太多.做的事情卻只是處理乙個請求.worker針對prefork的問題進行了改進.

這樣子,worker模型的併發性高於prefork模型.並且由於執行緒的開銷小於程序,所以worker模型占用的資源反而小於prefork.

但是worker相對於prefork存在乙個問題:非執行緒安全.最典型的乙個問題在於:如果你的apache使用了worker模型工作.但是php卻使用非執行緒安全的版本,那麼這兩者就不能工作了.所以縱然worker有萬般好,但是碰到使用非執行緒安全的歷史**,還是只能乖乖使用prefork模型.

worker模型使用多執行緒響應請求,這樣子存在乙個問題,即乙個執行緒崩潰就會影響整個程序.所以worker使用的是多程序+多執行緒的混合模型.即可以提高併發性,也可以避免乙個執行緒崩潰導致整個整個web站點崩潰.

同prefork一樣,worker中子程序跟執行緒數量也收到apache配置檔案的控制.有如下引數

其web服務調優大抵就是根據伺服器配置調節這些引數.具體引數細節可以參考apache文件

event模型是在apache2.2之後當做試驗特性引入的,在apache2.4之後才正式支援.event模型是為了解決長連線(keep-alive)問題而生的.使用worker模型,乙個執行緒對應乙個請求,當乙個請求為長連線的時候,執行緒就會保持當長連線狀態,等待客戶端的下乙個請求.這樣子當前執行緒就不能處理其他客戶端請求了.

event模型跟worker模型很像,也是多個程序+多個執行緒的混合模式,但是event模型下每個程序會有乙個單獨的執行緒來管理這些keep-alive型別的執行緒.當新的請求過來的時候,管理執行緒會把請求交給其他的空閒執行緒處理.這樣子就避免了每個執行緒都被keep-alive阻塞.

但是event模型並不是所有情況都通用,在https協議下會退化成worker模型.具體原因可以看官方文件.

講到apache,不得不提起現在nginx.相比於apache.nginx於2023年正式發布.而apache在1995就已經出現了.當時的web環境還只是簡單的展示靜態頁面,而且併發量遠沒有現在這麼高.所以當時apache的prefork模型也可以很好的承擔web服務需求.加之其穩定性好,沒有什麼理由不用它.

當時後來網際網路漸漸變大,**的併發量變大,apache就出現了乙個c10k的問題.即乙個物理伺服器達到併發量1w的時候apache就會承受不了.後來2023年nginx很好的解決了c10k問題.nginx為何能優於apache解決c10k問題,我們還是得從其處理請求模型說起.

nginx有三個著名的特性:

正是這三種程式設計方式促使nginx可以有如此高的併發量.下面來分析下nginx到底是如何工作的.

同樣,nginx的程序也分為master程序跟worker子程序.(其實還有兩個cache有關的程序, 這裡略過).在啟動nginx之後,master程序就會隨即建立一定數量的worker子程序,並且之後worker子程序數量保持不變.並且這些worker子程序都是單執行緒的.當乙個請求到來時,worker程序中某乙個空閒程序就會去處理這個請求.乍一看到這裡nginx的工作模式跟apache沒有什麼區別.關鍵就在於nginx如何處理使用者請求.

worker子程序開始處理請求.這個請求可能是訪問某個**的靜態頁面.而html頁面都是儲存在硬碟上的.站在作業系統角度來看,nginx是沒有辦法直接讀取硬碟上的檔案,必須由nginx告訴作業系統需要讀取哪個檔案,然後又作業系統去讀取這個檔案,讀取完畢作業系統再交給nginx.也就是說,在作業系統讀取檔案的時候,nginx是空閒的.如果是apache,那這個時候apache的worker程序/執行緒就阻塞在這裡等待作業系統把檔案讀取好再交個自己,這種就稱之為io阻塞.

但是nginx不一樣, nginx的worker程序在這個時候就會註冊乙個事件,相當於告訴作業系統:你檔案讀好了跟我說一下,我先去處理其他事情.然後這個worker就可以去處理新的使用者請求了.這裡nginx的worker程序並沒有由於作業系統讀取檔案而阻塞等待,這種即稱之為非io阻塞

當作業系統讀取好檔案之後,就會通知ngixn:我檔案幫你讀取好了,你過來拿走."作業系統讀取好檔案"這個事件被觸發了,於是nginx就跑回去把檔案拿走,然後返回響應.這種由於某個事件出現觸發nginx執行操作的方式就稱為事件驅動程式設計.

我們回顧上面過程,乙個使用者請求讀取檔案,nginx把讀取檔案這個事情通知作業系統之後就去處理下乙個使用者請求,直到作業系統讀取好檔案之後再返回響應.這種乙個請求還沒有處理完畢就去處理下乙個請求的程式設計方式即非同步程式設計

正是由於nginx這種工作模型,使得nginx在保持一定量的worker程序下,也可以得到相當大的併發量.這點正是nginx優於apache的地方.同樣,nginx的這種請求處理模型在處理長連線的時候也可以使用.

那麼是不是說nginx一定就優於apache.apache就藥丸了呢.也不是.一定要記住,乙個後來者的出現, 沒有在它的前輩所擅長的領域打敗它,那麼後來者是不可能完全取代前者.很有可能的情況是兩者並存.nginx本身並不能處理php,python等指令碼語言,只能把這些動態請求通過cgi**給其他程式處理.所以現在通常的架構是前台ngixn負責處理靜態檔案諸如js,css,image檔案.而碰到請求php等動態內容.就在後端多個apache伺服器中選擇乙個比較空閒的伺服器,把這請求**給這個伺服器處理.等apache處理好之後把返回交給nginx.nginx再返回給使用者.這是目前典型的一種設計方案.上面的流程中nginx負責兩個功能:反向**,負載均衡.這也是nginx所擅長的兩個功能.而apache豐富的模組可以很好的滿足乙個站點的各種需求.並且經過了20+年的考驗,apache的穩定性也是可以保證的.

Gridview,Formview的事件驅動

最近發現一件怪事 執行formview的insert的時候,girdview自動重新整理了一次。奇怪啊。我沒有寫這個重新繫結的方法啊 name id birthday name birthday name id birthday 新增 用 10仔細分析了一下事件的執行順序。問題 為什麼以前的用gv的...

SpringCloud Stream訊息驅動概述

簡介 如果系統裡同時存在多種mq,可以使用使用cloud stream,只需要和stream互動就可以進行管理。一句話,遮蔽底層訊息中介軟體的差異,降低切換成本,統一訊息的程式設計模型 官網 中文手冊 官方定義springcloud stream是乙個構建訊息驅動微服務的框架 應用程式通過input...

SpringCloud Stream訊息驅動

遮蔽底層訊息中介軟體的差異,降低切換成本,統一訊息的程式設計模型。在沒有binder這個概念的情況下,springboot應用要直接與訊息中介軟體進行資訊互動的時候,由於各訊息中介軟體構建的初衷不同,他們的實現細節上有較大差異,通過定義binder作為中間層,完美實現了應用程式與訊息中介軟體細節之間...