IO多路復用到底是不是異步的呢?

周興健


題主詳細描述的“IO複用屬於同步IO”大致上是沒問題的。

你的迷惑關鍵在於沒有注意到部分與整體的關係。

首先統一下對同步和異步的看法:同步/異步是協作機制,如果是和線程相關時,線程阻塞(sleep)或者空轉(輪詢)時可以看成是該線程在同步等待事件發生。

對於服務器網絡模塊設計來說,I/O多路複用必定會有一個輪詢線程,這個線程可以看成同步的,它負責了全部的通信數據(請求)的接收。然後一般都是利用線程池的線程開始異步解析應用層協議消息,並進行請求的服務處理(當然考慮請求的性質,可能還會繼續在服務內部進行並行處理)。所以從整體請求處理的角度看,是異步的。

所以,你可以說IO複用是同步的,twisted是異步的。

I/O多路複用

與I/O多路複用(I/O multiplexing)對應的是PPC和TPC模型,這裡不展開。

I/O多路複用目前有幾種模型:select,poll ,pselect,epoll。簡要說下。

select:調用select(),調用線程一直循環阻塞等待消息,調用線程是同步的。

pselect:相比select提供了更精準的超時時間而已,調用線程是同步的。

poll :poll本質上和select沒有區別,只是描述fd集合的方式不同,poll使用pollfd結構而不是select的fd_set結構,調用線程是同步的。

epoll:同樣需要一個線程在無限循環中調用epoll_wait等待註冊的事件,調用線程是同步的。


他們之間的最大的區別,是文件描述符數量限制,文件描述符遍歷、事件反饋機制方面的導致的cpu和內存資源消耗等方面。所以linux的epoll和windows的完成端口都是高併發大量連接的服務器必須考慮的,也催生了libevent和libuv之類優秀的跨平臺異步IO(這裡的異步就是從併發請求處理來看的)庫的產生。這裡就不多說了,有很多詳細的文章可看。


0遷徙的麻雀0


IO多路複用是同步還是異步看你站在哪個角度看的,IO多路複用比較經典的模型有selector,poll,epoll!

IO多路複用的發展背景:一開始C/S的通信,通常是Client端發起一個請求,然後Server端起一個對應的線程(或者進程)來處理,各個請求之間並不影響,隨著用戶越來越多,併發量越來越大,server端創建的線程逐漸的把整個計算機內存全部佔用,導致服務器卡死!

這個時候IO多路複用開始成為主流,因為其理念為使用一個線程不斷輪詢的監聽所有的連接,把活躍連接放入一個處理隊列(selector和epoll有所不同),使用任務線程進行處理,這個時候所有的連接線程使用一個線程代替,併發量提高了很多,例如基於使用epoll模型的nginx,併發量幾萬的時候佔用的線程也不過才幾M!


回到題目本身,服務器在監聽事件的過程中,如果一直沒有請求,那麼監聽的線程就是處於阻塞的,因為是使用的單線程監聽,也沒有異步的可能,但是在監聽到事件放入隊列之後,起多個線程分別去處理這個連接,這肯定又是異步的,所以IO多路複用嚴格上來說是同步監聽,異步處理的!

當然,IO多路複用並不是適用於所有的連接方式(長連接和短連接),如果是短連接,並且活躍事件比較多的情況下,使用IO多路複用,監聽線程會崩潰的,而改為使用基於線程池的多線程連接方式性能更好,如果是長連接的話,IO多路複用才能體現出極大的性能提升。

總的來說,IO多路複用在實際的開發中,用到的場景還是很多的,比如遊戲開發,社交軟件等,也是很多對服務器要求很高的公司招聘時著重強調的,掌握netty框架還是很有必要的,源碼在github上有,可以下載來玩玩,更多的技術分享,敬請關注。。。


謝逅架構


首先明確概念 異步就是說你幹一件事的時候還可以幹另外一件 IO就是指輸入輸出 兩者獨立 ;異步IO的意思是IO的時候可以幹其他的不用等待IO操作;另外 linux裡異步IO只有針對本地文件的 網絡IO都是同步的 epoll也是需要等待epoll_wait後才能繼續操作 只是epoll內部有關內核的實現是異步的(內核不斷監聽事件和把對應的事件通過鏈表返回給你的epollevent傳出參數) 但對於用戶層就是同步的 因為需要等待wait幹完才能繼續 也就是epoll監聽是同步的


分享到:


相關文章: