apache和nginx那點事兒--阻塞和異步

先明白的事兒:當一個程序在執行的時候,通常會建立一個進程,也能夠有多個進程。一個進程至少會建立一個線程,多個線程共享一個程序進程的內存。程序的運行最終是靠線程來完成操做的。線程的數量跟CPU核數有關,一個核最多能發出兩個線程。線程的操做主要分爲:一:給CPU進行程序命令的執行。二:IO的操做(讀取或輸出數據)或者請求網絡數據。nginx

什麼是阻塞:就是線程在執行IO操做獲取數據時,這個IO可能會須要必定的時間才能等到數據返回,而後才能接着執行下面的命令。那麼,此時,這個線程的等待狀態咱們就把它稱爲阻塞。沒有充分利用起cpu的資源。apache

什麼是非阻塞:仍是這個線程在進行 IO操做時,無需等待數據的返回,能夠接着往下執行代碼命令。cpu資源一直在充分利用。服務器

可是總要知道數據何時返回吧,常見的兩個解決方案:網絡

第一:若是程序是單線程的狀況下,在接着執行下面的代碼過程當中,須要額外不斷的輪詢查看這個IO請求的數據是否返回。多線程

第二:使用多線程,一個進程繼續等待數據返回,另外一個線程繼續操做執行下面的代碼。cpu資源一直在充分利用。併發

什麼是同步和異步:同步指的當線程進行IO操做請求數據時,是你主動"關心"數據的返回。異步是當前線程無需主動關心數據是否返回,當數據返回時,會有相關的事件通知你。異步


舉個通俗的例子:
你打電話問書店老闆有沒有《分佈式系統》這本書,若是是同步通訊機制,書店老闆會說,你稍等,」我查一下",而後開始查啊查,等查好了(多是5秒,也多是一天)告訴你結果(返回結果)。
而異步通訊機制,書店老闆直接告訴你我查一下啊,查好了打電話給你,而後直接掛電話了(不返回結果)。而後查好了,他會主動打電話給你。在這裏老闆經過「回電」這種方式來回調。分佈式

因而可知:阻塞並不等於同步,非阻塞也不等於異步。阻塞不阻塞的區別點在於:線程當遇到IO操做,須要等待IO返回數據時,是否能繼續往下執行代碼。而同步與異步的區別點在於:IO要返回的數據是須要線程主動等待,仍是被動的等待數據處理完以後主動通知你。網站

最好的理想方案就是:異步非阻塞。而nginx就使用的非阻塞+異步。apache使用的是同步阻塞。這也就是爲何nginx能比apache處理更多的請求更高的併發的緣由。spa


apache與nginx的工做原理:

假以下面是相似apache和nginx的僞代碼:

listen  //監聽端口

while(true){

$conn = accept() //一直循環接收鏈接

$read_content = read(conn)//讀取請求的文件

$esponse = process(conn) # 執行業務邏輯

echo $espnse //返回客戶端內容

}

apache:

每個鏈接,apache就會建立一個進程,每一個進程內單線程,apache最多能建立256個進程。對於一個負載相對較高的網站來講,256的進程,也就是256個線程,由於線程處理請求時,是同步阻塞模式,接收請求以後,會一直等待該請求讀取程序文件(IO)(同步),執行業務邏輯,返回客戶端,全部操做完成以後才能處理下一個請求(阻塞)若是服務器已經達到256的極限,那麼接下去的訪問就須要排隊這也就是爲何某些服務器負載不高的緣由了。

nginx:

nginx接收一個請求後,不會等待這個請求的文件讀取操做完成以後才接收下一個請求,它不會等待這個請求的後續的處理結果。而是會立刻循環處理下一個請求(不阻塞)。請求的程序文件執行完成以後,會主動通知該線程,不用你主動去等待或者輪詢查看(異步)。最後返回給客戶端。這樣作,每一個請求過來就不須要等待很長的時間排隊,而是立刻就能接收,開始進行處理了。等處理完成以後,會主動通知回調這個線程進行數據返回。

相關文章
相關標籤/搜索