IO模式

服務(wù)器端編程經(jīng)常需要構(gòu)造高性能的IO模型,IO模型有五種:

1. 同步阻塞IO(Blocking IO):即傳統(tǒng)的IO模型熄驼。
2. 同步非阻塞IO(Non-blocking IO):默認(rèn)創(chuàng)建的socket都是阻塞的像寒,非阻塞IO要求socket被設(shè)置為NONBLOCK。此NIO非Java的NIO瓜贾。
3. IO多路復(fù)用(IO Multiplexing):Reactor設(shè)計(jì)模式诺祸,也稱為異步阻塞IO,Java中的 Selector(NIO)和 Linux 中的 epoll 都是這種模型祭芦。(redis多路復(fù)用)
4. 異步IO(Asynchronous IO):即經(jīng)典的Proactor設(shè)計(jì)模式筷笨,也稱為異步非阻塞IO。
5. 信號(hào)驅(qū)動(dòng)IO。(不常見)

明確一個(gè)概念胃夏,如果只有一個(gè)線程轴或,一個(gè)任務(wù),那肯定是BIO快仰禀,沒有多余的動(dòng)作照雁。優(yōu)化是基于并發(fā)的,多個(gè)任務(wù)怎么辦答恶?多個(gè)線程怎么辦饺蚊?

1. 同步阻塞IO

image.png
//偽代碼
{
    read(socket, buffer);
    process(buffer);
}

2. 同步非阻塞IO

  • 同步非阻塞IO是在同步阻塞IO的基礎(chǔ)上,將socket設(shè)置為NONBLOCK悬嗓。這樣做用戶線程可以在發(fā)起IO請(qǐng)求后可以立即返回污呼。
  • 由于socket是非阻塞的方式,因此用戶線程發(fā)起IO請(qǐng)求時(shí)立即返回包竹。但并未讀取到任何數(shù)據(jù)曙求,用戶線程需要不斷地發(fā)起IO請(qǐng)求,直到數(shù)據(jù)到達(dá)后映企,才真正讀取到數(shù)據(jù),繼續(xù)執(zhí)行静浴。
  • 雖然用戶線程每次發(fā)起IO請(qǐng)求后可以立即返回堰氓,但是為了等到數(shù)據(jù),仍需要不斷地輪詢苹享、消耗了大量的CPU的資源双絮。一般很少直接使用這種模型。
  • 輪詢有什么用得问?反正還是等囤攀。我說了,如果只有一個(gè)任務(wù)宫纬,就是阻塞IO最好焚挠,但如果開十個(gè)線程,同時(shí)處理一百個(gè)任務(wù)漓骚,主線程可以將先獲取到的結(jié)果進(jìn)行其他處理蝌衔,同時(shí)輪詢socket,不香嗎蝌蹂?
//偽代碼
{
        while(read(socket, buffer) != SUCCESS)
        process(buffer);
}

IO多路復(fù)用

單線程下的IO多路復(fù)用毫無意義噩斟,就是平白無故的多了個(gè)select過程,又要socket監(jiān)聽孤个,又要select來輪詢事件剃允,那為什么用呢?多線程。

3. Reactor模式下的IO多路復(fù)用
  • Reactor:非阻塞同步IO模型斥废,可以理解為:來了事件我通知你椒楣,你來處理。用戶提供事件营袜,reactor提供數(shù)據(jù)撒顿,然后用戶自己讀。
  • Proactor:異步IO模型荚板,可以理解為:來了事件我來處理凤壁,處理完了我通知你。用戶提供事件和buffer跪另,Proactor將事件處理拧抖,并把輸入放入buffer,再通知用戶免绿。
  • a. 單Reactor單線程(redis多路復(fù)用)
  • 缺點(diǎn):這個(gè)模式reactor和handler在一個(gè)線程中唧席,如果某個(gè)handler阻塞,會(huì)導(dǎo)致其他的handler無法執(zhí)行嘲驾。
//偽代碼
{
     select(socket);
     while(1) {
         sockets = select();
         for(socket in sockets) {
               if(can_read(socket)) {
                      read(socket, buffer);
                      process(buffer);
               }
          }
     }
}
while前將socket添加到select監(jiān)視中淌哟,然后在while內(nèi)一直調(diào)用select獲取被激活的socket,
一旦socket可讀辽故,便調(diào)用read函數(shù)將socket中的數(shù)據(jù)讀取出來徒仓。
  • b. 單reactor多線程
  • 由于decode、compute誊垢、encode的操作并非IO的操作掉弛,多線程Reactor的思路就是充分發(fā)揮多核的特性,同時(shí)把非IO的操作剝離開喂走。
  • 但是殃饿,單個(gè)Reactor承擔(dān)了所有的事件監(jiān)聽、響應(yīng)工作芋肠,如果連接過多乎芳,還是可能存在性能問題。
  • c. 主從Reactor多線程
  • 優(yōu)點(diǎn):【1】父線程與子線程的數(shù)據(jù)交互簡單職責(zé)明確帖池,父線程只需要接收新連接秒咐,子線程完成后續(xù)的業(yè)務(wù)處理〉庠#【2】且父線程與子線程的數(shù)據(jù)交互簡單携取,Reactor主線程只需要把新連接傳給子線程,子線程無需返回?cái)?shù)據(jù)
  • mainReactor建立連接帮孔,多個(gè)subReactor負(fù)責(zé)數(shù)據(jù)讀寫雷滋。 缺點(diǎn):編程復(fù)雜度較高
  • 4. Proactor模式下的IO多路復(fù)用(異步IO)
  • 在IO多路復(fù)用模型中不撑,事件循環(huán)將文件句柄的狀態(tài)事件(是否可讀、可寫)通知給用戶線程晤斩,由用戶線程自行讀取焕檬、處理數(shù)據(jù)。而在異步IO模型中澳泵,當(dāng)用戶線程收到通知時(shí)实愚,數(shù)據(jù)已經(jīng)被內(nèi)核讀取完畢,并放在了用戶線程指定的buffer內(nèi)兔辅,內(nèi)核在IO完成后通知用戶線程直接使用buffer的內(nèi)容即可腊敲。
  • 異步IO模型使用了Proactor設(shè)計(jì)模式實(shí)現(xiàn)了這一機(jī)制。
  • Proactor模式和Reactor模式在結(jié)構(gòu)上比較相似维苔,不過在用戶(Client)使用方式上差別較大碰辅。
    Reactor模式中,用戶線程通過向Reactor對(duì)象注冊(cè)感興趣的事件監(jiān)聽介时,然后事件觸發(fā)時(shí)調(diào)用事件處理函數(shù)没宾。
    Proactor模式中,用戶線程將AsynchronousOperation(讀/寫等)沸柔、Proactor以及操作完成時(shí)的CompletionHandler注冊(cè)到AsynchronousOperationProcessor循衰。AsynchronousOperationProcessor使用Facade模式提供了一組異步操作API(讀/寫等)供用戶使用,當(dāng)用戶線程調(diào)用異步API后褐澎,便繼續(xù)執(zhí)行自己的任務(wù)羹蚣。AsynchronousOperationProcessor 會(huì)開啟獨(dú)立的內(nèi)核線程執(zhí)行異步操作,實(shí)現(xiàn)真正的異步乱凿。當(dāng)異步IO操作完成時(shí),AsynchronousOperationProcessor將用戶線程與AsynchronousOperation一起注冊(cè)的Proactor和CompletionHandler取出咽弦,然后將CompletionHandler與IO操作的結(jié)果數(shù)據(jù)一起轉(zhuǎn)發(fā)給Proactor徒蟆,Proactor負(fù)責(zé)回調(diào)每一個(gè)異步操作的事件完成處理函數(shù)handle_event。雖然Proactor模式中每個(gè)異步操作都可以綁定一個(gè)Proactor對(duì)象型型,但是一般在操作系統(tǒng)中段审,Proactor被實(shí)現(xiàn)為Singleton模式,以便于集中化分發(fā)操作完成事件闹蒜。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末寺枉,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子绷落,更是在濱河造成了極大的恐慌姥闪,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,826評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件砌烁,死亡現(xiàn)場離奇詭異筐喳,居然都是意外死亡催式,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門避归,熙熙樓的掌柜王于貴愁眉苦臉地迎上來荣月,“玉大人,你說我怎么就攤上這事梳毙〔刚” “怎么了?”我有些...
    開封第一講書人閱讀 164,234評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵账锹,是天一觀的道長萌业。 經(jīng)常有香客問我,道長牌废,這世上最難降的妖魔是什么咽白? 我笑而不...
    開封第一講書人閱讀 58,562評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮鸟缕,結(jié)果婚禮上晶框,老公的妹妹穿的比我還像新娘。我一直安慰自己懂从,他們只是感情好授段,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,611評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著番甩,像睡著了一般侵贵。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上缘薛,一...
    開封第一講書人閱讀 51,482評(píng)論 1 302
  • 那天窍育,我揣著相機(jī)與錄音,去河邊找鬼宴胧。 笑死漱抓,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的恕齐。 我是一名探鬼主播乞娄,決...
    沈念sama閱讀 40,271評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼显歧!你這毒婦竟也來了仪或?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,166評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤士骤,失蹤者是張志新(化名)和其女友劉穎范删,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體拷肌,經(jīng)...
    沈念sama閱讀 45,608評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡瓶逃,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,814評(píng)論 3 336
  • 正文 我和宋清朗相戀三年束铭,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片厢绝。...
    茶點(diǎn)故事閱讀 39,926評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡契沫,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出昔汉,到底是詐尸還是另有隱情懈万,我是刑警寧澤,帶...
    沈念sama閱讀 35,644評(píng)論 5 346
  • 正文 年R本政府宣布靶病,位于F島的核電站会通,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏娄周。R本人自食惡果不足惜涕侈,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,249評(píng)論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望煤辨。 院中可真熱鬧裳涛,春花似錦、人聲如沸众辨。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,866評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽鹃彻。三九已至郊闯,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間蛛株,已是汗流浹背团赁。 一陣腳步聲響...
    開封第一講書人閱讀 32,991評(píng)論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留谨履,地道東北人欢摄。 一個(gè)月前我還...
    沈念sama閱讀 48,063評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像屉符,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子锹引,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,871評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容