非同步 非阻塞和IO多路復用總結

2022-09-08 07:12:10 字數 3109 閱讀 1539

nginx是併發處理框架的代表者,很多後台業務都會放在nginx容器中執行,以實現高吞吐,而nginx能夠支援高併發也是由於使用了非同步非阻塞處理模型,本文將用通俗的話講解非同步、同步、阻塞、非阻塞的區別,以及io多路復用。

一、同步和非同步

同步與非同步的重點是在訊息通知的方式上,也就是呼叫後結果通知的方式不同。

同步與非同步的區別

同步:當乙個同步呼叫發出去後,呼叫者要一直等待呼叫結果的通知後,才能執行後續的操作。

非同步:當乙個非同步呼叫發出去後,呼叫者不用一直死等呼叫結果的通知,可以立即返回,執行後續的操作。

那麼,非同步呼叫獲取結果的方式有兩種:一是通過主動輪訓非同步呼叫的結果。二是被呼叫方通過callback**來通知呼叫者結果。

生活中的例子:

同步買奶茶:小明下單交錢,站在吧檯等著拿奶茶。

非同步買奶茶:小明下單交錢,老闆給他一張小票,等奶茶做好了再來取。

那麼,非同步買奶茶時,小明怎麼知道奶茶做好了:一是小明主動不斷問老闆:我的奶茶好了嗎?二是老闆吧奶茶做好了,大喊一聲:奶茶好了,請小明取用,然後小明跑過去取回奶茶,這種方式叫做**。

二、阻塞與非阻塞

阻塞與非阻塞的重點在於進/執行緒等待訊息時候的行為,也就是等待訊息的時候,當前程序or執行緒是掛起還是非掛起狀態。

阻塞與非阻塞的區別

阻塞呼叫:呼叫發出去後,在訊息返回前,當前程序or執行緒會被掛起,直到有訊息返回時,才會被再次啟用,期間不能處理其他的事務。

非阻塞呼叫:呼叫發出去後,不會阻塞當前的程序or執行緒,而會立即返回。

生活中的例子:

阻塞買奶茶:小明下單交錢,幹等著拿奶茶,期間什麼事情都不做。

非阻塞買奶茶,小明下單交錢,等待拿奶茶,等的過程中,時不時看微博刷新聞。

三、總結

通過以上可以總結:

1. 同步與非同步,重點在於訊息的通知方式。

2.阻塞與非阻塞,重點在於等訊息時候的行為。

因此,共同組成4種方式:

1.同步阻塞:小明在吧檯幹等著拿奶茶

2.同步非阻塞:小明在吧檯邊刷微博邊等著拿奶茶。

3.非同步阻塞:小明拿著小票什麼都不幹,等著老闆通知他拿奶茶。

4.非同步非阻塞:小明拿著小票,刷著微博,等著老闆通知他拿奶茶。

四、io多路復用

io多路復用英文名叫io multiplexing,這個multiplexing是指單個執行緒記錄跟蹤每乙個sock的狀態,盡可能提高伺服器的吞吐能力。

最初的io復用

所謂的io復用是多個io可以復用乙個程序。

採用非阻塞模式,當乙個連線過來時,我們不阻塞住,這樣的乙個程序可以同時處理多個連線。

比如乙個程序接受了1000個連線請求,這個程序每次都從頭到尾問一遍,「有io事件沒,有的話請給我來處理,沒有的話我一會兒再來問下」。然後程序就不斷重複詢問這1000個連線的狀態。這樣會造成cpu的空轉浪費,效率也很低。

公升級版的io復用

上面的古老io復用邏輯效率很感人,於是引入了乙個**,這個agent可以同時觀察多個io流事件。

產生了兩個**:select和poll。

select和poll**原理:

poll是基於select的優化產生的,原理上其實一樣:

當連線有io流事件產生時,就會主動喚醒程序處理。不過程序不清楚究竟是哪乙個連線產生的io流事件,於是挨個問,最終得出結果。

select是第乙個實現版本(2023年在bsd裡面實現)

2023年實現poll版本

select和poll原理是一樣的,不過poll將select只能觀察1024個連線優化成可觀察無限個連線。

總之,select和poll實現還不夠好,因為會產生cpu浪費的情況,如果有乙個agent可以知道哪個連線有了io流事件,就可以迅速定位到該連線,並且能夠確定是讀操作還是寫操作豈不是更加美好了。因此,產生了epool 多路復用。

epoll io多路復用

epoll**原理

當連線有io流事件產生時候,epool會告訴程序哪個連線產生了io流事件,然後程序就會去處理該連線。

epoll是io多路復用中很優秀的實現,修復了poll和select的缺陷:

1.epoll是執行緒安全的。select是執行緒不安全的,如果將乙個sock加入select,然後另外乙個執行緒發現此sock不可用,需要**。select是不支援的,如果你強制關掉此sock會導致未知後果。poll優化了1024的鏈結限制,並且poll不用傳入陣列,介面設計更加優雅。

2.epoll不僅會告訴sock組裡面有陣列,還會告訴具體的sock組,不用去想法設法尋找了,提高cpu利用率。

缺點:epoll只有linux支援。

epoll與select/poll的最大區別

1.epoll內部使用了mmap共享了使用者和核心的部分空間,避免資料來回拷貝。

2.epoll基於事件驅動,epoll_ctl註冊事件並註冊callback**函式,epoll_wait返回發生的事件,解決了select/poll的大量輪訓。

非同步非阻塞和io多路復用的應用

nginx非同步非阻塞模型

nginx優秀的地方是因為採用了非同步非阻塞和io多路復用機制

nginx程序由1個master程序和多個work程序組成,每當到了來乙個request,會有worker程序去處理,但是不是全程處理,如果處理過程中有出現阻塞的地方,比如**request並等待請求返回,它會首先註冊乙個事件:如果upstream返回後,請告訴我,我會接手繼續之前的工作,這叫做非同步。舉個例子,使用uwsgi和nginx部署python web後台時候,nginx只會講request**給uwsgi,並且非同步等待請求返回,如果這個時刻有新的request到來,此work程序會馬上處理新的request,這就是非阻塞和io多路復用。一旦上游伺服器返回了,worker程序繼續接手,這個**過程叫做非同步**

參考資料

IO多路復用 非阻塞式IO

目錄 三 多路復用實現 伺服器核心要做的事情是等資料到了我再做事情。伺服器的執行緒處理時間裡面只需要包含資料到了後續部分。這樣最大限度的利用了珍貴的伺服器執行緒資源,並且由於執行緒的處理時間中沒有包含等待資料的時間,可以使得執行緒快速釋放。現實生活中的例子,餐廳,阻塞io類似於每來乙個客人我馬上分配...

多路復用及同步 非同步和阻塞 非阻塞

今天查詢了很多關於多路復用之類的資料,特淺陋整理一下,有助於記憶。其實這些概念都僅僅是實踐中的概念而已,沒必要理論是的加以定義,但也要是自己弄清楚,才能明確這些術語的應用場景。1 同步和非同步i o 弄清這些概念,先從reactor和proactor這兩個模式說起,網上的介紹很多,自己也沒有什麼時間...

非阻塞套接字與IO多路復用

我們了解了socket之後已經知道,普通套接字實現的服務端的缺陷 一次只能服務乙個客戶端!並且,為了使乙個客戶端能夠不斷收發訊息,我們還要使用while迴圈來輪詢,這極大地降低了我們的效率 accept阻塞!在沒有新的套接字來之前,不能處理已經建立連線的套接字的請求 recv 阻塞!在沒有接受到客戶...