国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發(fā)設計 > 正文

淺析I/O模型及其設計模式

2019-11-08 02:13:34
字體:
供稿:網(wǎng)友

http://www.cnblogs.com/wxisme/p/5299130.html

前言

  I/O在軟件開發(fā)中的重要性無需多言,無論是在操作系統(tǒng)、網(wǎng)絡協(xié)議、DBMS這種底層支撐軟件還是在移動APP,大型網(wǎng)站服務器等應用軟件的開發(fā)中都是最核心最重要的部分。特別是現(xiàn)在軟件服務使用量和數(shù)據(jù)量爆炸增長的時代,大數(shù)據(jù)背景下的高可用分布式系統(tǒng)都離不開高效穩(wěn)定的I/O。本文就簡要分析各類I/O模型的演進、基本原理、應用方法、優(yōu)缺點及其使用場景。文章最后會簡要分析兩種常用的I/O設計模式。需要說明的是,對于I/O中的許多問題是沒有統(tǒng)一、確切的答案的,因此在分析一些問題的時候會根據(jù)自己的理解來說明,很有可能和其他書籍或者文章的觀點有出入,至于哪種理解更好歡迎交流。

文章大綱:

1. 阻塞/非阻塞 同步/異步

2. I/O中的阻塞/非阻塞 同步/異步

3. BIO、偽異步I/O、NIO、AIO四種常用I/O模型及其對比

4. Reactor、PRoactor兩種I/O設計模式及其對比

5. 總結(jié)

使用各種I/O模型實現(xiàn)的時間服務器源代碼僅供參考:https://git.oschina.net/wangxu/TimeServer

參考《Neety權(quán)威指南》

阻塞/非阻塞 & 同步/異步

  在介紹I/O模型之前需要先理解幾個概念,理解了阻塞/非阻塞 & 同步/異步的聯(lián)系和區(qū)別才能理解I/O模型。關(guān)于阻塞/非阻塞 & 同步/異步有很多資料的說法不一致,但是也沒必要咬文嚼字,只要能夠結(jié)合實際的例子來理解每種模型的基本原理就可以了。下面就我自己的理解來說一下這個問題。

阻塞/非阻塞:首先需要知道阻塞/非阻塞是針對某一個事件(線程/進程)來說的。對于阻塞,如果一個事件在觸發(fā)一個請求后,由于條件不滿足,那么這個事件就會停在這個請求上。拿一個線程來說,一個線程在請求了一個系統(tǒng)調(diào)用之后,由于當前不滿足執(zhí)行這個請求的條件,那么這個線程就會停在這個請求上,直到請求執(zhí)行完畢或者出現(xiàn)異常返回,這個線程阻塞的時候操作系統(tǒng)不會分配CPU時間。對于非阻塞,如果一個事件在觸發(fā)一個請求后,無論當前是否滿足執(zhí)行請求的條件,都會把結(jié)果或者異常返回給請求事件,這個事件不會被阻塞。

舉個栗子:你想去ATM機取錢,但是前面有人排隊,那么這時候你必須要排在后面。在輪到你取錢之前你哪也不能去什么也不能干,只能排隊等待。那這就是阻塞式的。那如果你閑ATM人太多,你去了銀行大廳到柜臺取錢。那么你到了之后,大堂經(jīng)理會提示你去一張排隊號,在你取完排隊號之后,你不必非要站在柜臺前面等著,你可以坐著玩手機,如果時間夠的話你可以上個廁所,吃個飯都是可以的。如果輪到你了,叫號系統(tǒng)就會廣播:請xxx號顧客到xxx號窗口辦理業(yè)務。這時候你聽見就可以去取錢了。這就是非阻塞式的。

同步/異步:首先需要強調(diào)一點,同步/異步是針對多個事件(線程/進程)來說的。拿單個的事件來談同步/異步是沒有意義的。有點類似于操作系統(tǒng)中進程調(diào)度中狹義的同步(和資源互斥相對)。如果事件A需要等待事件B的完成才能完成,這種就可以說是同步的。如果事件A的完成需要事件B的執(zhí)行結(jié)果,但是在B完成之前A不會因為B沒有完成而等待,而是繼續(xù)執(zhí)行,等待B完成之后自動補全A的任務。類似這種的就是異步的。

舉個栗子:還是取錢的例子,如果你像上面說的那兩種方法取錢的話,你還是得自己出馬,排隊/取號,辦理取錢業(yè)務然后回家,這種都是同步的。但是如果你辦了一張銀行的Vip金卡,那好了,給銀行打個電話說需要多少錢什么時候需要,然后你可以接著干你的事情,就當這件事情不存在一樣。銀行的業(yè)務員會把你需要的錢自動在合適的時間給你送來。那么萬一業(yè)務員在路上被搶劫了,銀行也會給你打電話通知你。像這種就類似異步的操作。

區(qū)分阻塞/同步和非阻塞/異步:只要理解了阻塞/非阻塞式針對單一事件,同步/異步是針對多個事件這個核心就能夠區(qū)分阻塞/同步和非阻塞/異步這兩組完全不同的概念。

I/O中的阻塞/非阻塞 & 同步/異步

  理解了這幾種不同的概念,下面來具體的看一下這幾種概念組合起來在I/O中的應用。

同步阻塞I/O:最常用的一個模型是同步阻塞 I/O 模型。在這個模型中,用戶空間的應用程序執(zhí)行一個系統(tǒng)調(diào)用,這會導致應用程序阻塞。這意味著應用程序會一直阻塞,直到系統(tǒng)調(diào)用完成為止(數(shù)據(jù)傳輸完成或發(fā)生錯誤)。調(diào)用應用程序處于一種不再消費 CPU 而只是簡單等待響應的狀態(tài),因此從處理的角度來看,這是非常有效的。在調(diào)用 read 系統(tǒng)調(diào)用時,應用程序會阻塞并對內(nèi)核進行上下文切換。然后會觸發(fā)讀操作,當響應返回時(從我們正在從中讀取的設備中返回),數(shù)據(jù)就被移動到用戶空間的緩沖區(qū)中。然后應用程序就會解除阻塞(read 調(diào)用返回)。從應用程序的角度來說,read 調(diào)用會延續(xù)很長時間。實際上,在內(nèi)核執(zhí)行讀操作和其他工作時,應用程序的確會被阻塞。

 

阻塞I/O模型

同步非阻塞I/O:在這種模型中,設備是以非阻塞的形式打開的。這意味著 I/O 操作不會立即完成,read 操作可能會返回一個錯誤代碼,說明read請求不能立即滿足。需要應用程序調(diào)用許多次來等待操作完成。這可能效率不高,因為在很多情況下,當內(nèi)核執(zhí)行這個命令時,應用程序必須要進行忙碌等待,直到數(shù)據(jù)可用為止,或者試圖執(zhí)行其他工作。這個方法可以引入 I/O 操作的延時,因為數(shù)據(jù)在內(nèi)核中變?yōu)榭捎玫接脩粽{(diào)用read 返回數(shù)據(jù)之間存在一定的間隔,這會導致整體數(shù)據(jù)吞吐量的降低。

 

非阻塞I/O模型

異步阻塞I/O:個人覺得談這種模型的意義不大,以為請求線程已經(jīng)阻塞,那么異步的作用就不大了。但還有一種理解就是這里的阻塞是通知的阻塞,而不是請求線程的阻塞,也就是一種帶有阻塞通知的非阻塞 I/O。在這種模型中,配置的是非阻塞 I/O,然后使用阻塞select 系統(tǒng)調(diào)用來確定一個 I/O 描述符何時有操作。使 select 調(diào)用非常有趣的是它可以用來為多個描述符提供通知,而不僅僅為一個描述符提供通知。對于每個提示符來說,我們可以請求這個描述符可以寫數(shù)據(jù)、有讀數(shù)據(jù)可用以及是否發(fā)生錯誤的通知。

 

復用I/O模型

 

異步非阻塞I/O:異步非阻塞 I/O 模型是一種處理與 I/O 重疊進行的模型。讀請求會立即返回,說明 read 請求已經(jīng)成功發(fā)起了。在后臺完成讀操作時,應用程序然后會執(zhí)行其他處理操作。當 read 的響應到達時,就會產(chǎn)生一個信號或執(zhí)行一個基于線程的回調(diào)函數(shù)來完成這次 I/O 處理過程。在一個進程中為了執(zhí)行多個 I/O 請求而對計算操作和 I/O 處理進行重疊處理的能力利用了處理速度與 I/O 速度之間的差異。當一個或多個 I/O 請求掛起時,CPU 可以執(zhí)行其他任務;或者更為常見的是,在發(fā)起其他 I/O 的同時對已經(jīng)完成的 I/O 進行操作。

 

異步I/O模型

BIO、偽異步I/O、NIO、AIO四種常用I/O模型及其對比

BIO/偽異步IO:BIO是阻塞(block)I/O同時也是同步的,就是說BIO是一種同步阻塞I/O模型,在基于傳統(tǒng)的同步阻塞I/O模型的開發(fā)中,需要服務端監(jiān)聽端口號,然后客戶端通過IP和端口號來和服務端建立TCP連接,以同步阻塞的方法進行數(shù)據(jù)傳輸。一般使用BIO的服務端設計中是一客戶一線程模型的。

 

BIO模型

 

這種模型是有問題的,如果連接客戶端較多會大大消耗服務端的資源,如果線程數(shù)量超過服務端能承受的最大數(shù)量,那么服務器可能會出現(xiàn)很嚴重的后果。所以出現(xiàn)了偽異步I/O模型,偽異步I/O模型對BIO模型進行了改進,采用了線程池來處理客戶連接線程。這樣就可以靈活的設置線程池的大小,可以避免服務端資源耗盡的問題。

 

偽異步I/O模型

但是偽異步I/O模型并沒有從根本上解決客戶連接線程的阻塞問題,只是對BIO模型進行了簡單的優(yōu)化。面對巨大的連接客戶線程還是存在客戶線程阻塞時間較長反應較慢的問題。

NIO:NIO是一種非阻塞(non-block)的,同時又是同步的I/O模型。這里只談一種帶有Selector多路復用器的NIO。NIO是使用一個Selector復用器線程來輪詢每一個客戶端連接,這樣就不用阻塞用戶線程,同時也不用每個用戶線程忙等待。只使用一個線程來輪詢I/O事件,這樣一來就可以從根本上解決用戶線程阻塞的問題。所以NIO模型比較適合高負載、高并發(fā)的網(wǎng)絡應用。能夠充分利用系統(tǒng)資源快速處理請求返回響應消息。NIO適合連接數(shù)較多連接時間I/O任務較短的場景,例如即時消息服務器。如果連接數(shù)不多而且比較固定,I/O任務較長使用NIO模型就會得不償失,不僅增加了編程的復雜度而且達不到預期的效果。

AIO:AIO是一種異步(Asyncronous)非阻塞的I/O模型,它需要操作系統(tǒng)內(nèi)核線程的支持,一個用戶線程發(fā)起一個系統(tǒng)調(diào)用請求后就可以繼續(xù)執(zhí)行,內(nèi)核線程執(zhí)行完系統(tǒng)調(diào)用會根據(jù)回調(diào)函數(shù)來完成處理工作。所以AIO模型應該是一種比較理想的模型,因為操作系統(tǒng)內(nèi)核線程做了一些工作,所以在編程復雜度上AIO要比NIO要簡單一些。AIO比較適合連接數(shù)較多其I/O任務比較長的場景。

借助《Netty權(quán)威指南》上的一張表對比一下各個I/O模型的特點:

 

Reactor、Proactor兩種I/O設計模式及其對比

Reactor:Reactor模式是基于NIO多路復用I/O模型實現(xiàn)的一種常用的模式。在Reactor模式中每個客戶連接會注冊自己感興趣的事件,然后Selector多路復用器會輪詢每個就緒事件,每到一個事件執(zhí)行一個事件。Reactor實現(xiàn)了一個被動的事件分離和分發(fā)模型,服務等待請求事件的到來,再通過不受間斷的同步處理事件,從而做出反應。Reactor比較適合連接數(shù)較多但是任務量較小的場景。Reactor實現(xiàn)相對簡單,對于耗時短的處理場景處理高效;操作系統(tǒng)可以在多個事件源上等待,并且避免了多線程編程相關(guān)的性能開銷和編程復雜性;事件的串行化對應用是透明的,可以順序的同步執(zhí)行而不需要加鎖;事務分離,將與應用無關(guān)的多路分解和分配機制和與應用相關(guān)的回調(diào)函數(shù)分離開來。Reactor同時接收多個服務請求,并且依次同步的處理它們的事件驅(qū)動程序;但是Reactor不適合執(zhí)行耗時較長的操作,處理耗時長的操作會造成事件分發(fā)的阻塞,影響到后續(xù)事件的處理。Proactor:Proactor模式是基于AIO實現(xiàn)的一種高效的I/O設計模式。在Proactor中用戶連接請求I/O操作,這時操作系統(tǒng)內(nèi)核就會調(diào)用相應的系統(tǒng)調(diào)用來完成請求,內(nèi)核線程在完成用戶的I/O請求后把執(zhí)行結(jié)果放在完成事件隊列中,Proactor從完成事件隊列中取出結(jié)果根據(jù)相應的回調(diào)處理器來完成對操作結(jié)果的相應處理。Proactor實現(xiàn)了一個主動的事件分離和分發(fā)模型;這種設計允許多個任務并發(fā)的執(zhí)行,從而提高吞吐量;并可執(zhí)行耗時長的任務(各個任務間互不影響)。相對Reactor來說,Proactor性能更高,能夠處理耗時長的并發(fā)場景;可以異步接收和同時處理多個服務請求的事件驅(qū)動程序;但是Proactor依賴操作系統(tǒng)對異步操作的支持,各類操作系統(tǒng)對異步I/O支持的實現(xiàn)細節(jié)有差異,沒有形成統(tǒng)一的標準。

總結(jié)

  沒有最好的I/O模型,只有最適合的I/O模型。

 

參考資料:

《Unix網(wǎng)絡編程》

《Netty權(quán)威指南》李林峰

  IO設計模式:Reactor和Proactor對比:http://www.2cto.com/kf/201504/395318.html

  java NIO淺析IO模型:http://www.cnblogs.com/dolphin0520/p/3916526.html

  使用異步I/O大大提高應用程序的性能:https://www.ibm.com/developerworks/cn/linux/l-async/

  TimeServer源代碼:https://git.oschina.net/wangxu/TimeServer


發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 民乐县| 虞城县| 公安县| 武夷山市| 咸宁市| 乾安县| 连江县| 南江县| 蕲春县| 和静县| 龙川县| 辛集市| 永昌县| 扎兰屯市| 永定县| 卢氏县| 光山县| 兴海县| 修水县| 体育| 惠东县| 新沂市| 武定县| 仙桃市| 芜湖县| 如皋市| 深圳市| 阳山县| 策勒县| 安丘市| 神农架林区| 万安县| 凤阳县| 安国市| 临沧市| 蒲城县| 宝应县| 甘德县| 大冶市| 海淀区| 新蔡县|