服務(wù)器兩種高效的并發(fā)模式

一、并發(fā)編程與并發(fā)模式

并發(fā)編程主要是為了讓程序同時(shí)執(zhí)行多個(gè)任務(wù),并發(fā)編程對(duì)計(jì)算精密型沒有優(yōu)勢(shì)吧史,反而由于任務(wù)的切換使得效率變低鼓鲁。如果程序是IO精密型的蕴轨,則由于IO操作遠(yuǎn)沒有CPU的計(jì)算速度快,所以讓程序阻塞于IO操作將浪費(fèi)大量的CPU時(shí)間骇吭。如果程序有多個(gè)線程橙弱,則當(dāng)前被IO操作阻塞的線程可主動(dòng)放棄CPU,將執(zhí)行權(quán)轉(zhuǎn)給其它線程。

IO精密型和cpu精密型可以參考此文:CPU-bound(計(jì)算密集型) 和I/O bound(I/O密集型)

并發(fā)編程主要有多線程和多進(jìn)程燥狰,這里我們先討論并發(fā)模式棘脐,并發(fā)模式指:IO處理單元和多個(gè)邏輯直接協(xié)調(diào)完成任務(wù)的方法。服務(wù)器主要有兩種并發(fā)編程模式:

  • 半同步/半異步模式(half-sync/half-async)
  • 領(lǐng)導(dǎo)者/追隨者模式(Leader/Followers)

二龙致、半同步/半異步模式(half-sync/half-async

這里的“同步”和“異步”和“IO”的“同步”“異步”是完全不同的概念蛀缝。在IO模型中,“同步”和“異步”區(qū)分的是內(nèi)核向應(yīng)用程序通知的是何種IO事件(是就緒事件還是完成事件)目代,以及該由誰來完成IO讀寫(是應(yīng)用程序還是內(nèi)核)屈梁。在并發(fā)模式中,“同步”指的是程序完全按照代碼序列的順序執(zhí)行榛了;“異步”指的是程序的執(zhí)行需要由系統(tǒng)事件來驅(qū)動(dòng)在讶。常見的系統(tǒng)事件包括中斷、信號(hào)等霜大。

下圖1描述了并發(fā)模式同步讀操作(圖1a)和異步讀操作(圖1b)

圖1并發(fā)模式同步讀(a)和異步讀(b)

已同步方式運(yùn)行的線程為同步線程真朗,異步方式運(yùn)行的為異步線性,異步線程的執(zhí)行效率高僧诚,實(shí)時(shí)性強(qiáng)遮婶,但編寫異步方式執(zhí)行的程序相對(duì)復(fù)雜蝗碎,難于調(diào)試和擴(kuò)展,而且不適合于大量的并發(fā)旗扑。同步線程則相反蹦骑,它雖然效率相對(duì)較低,實(shí)時(shí)性較差臀防,但邏輯簡(jiǎn)單眠菇。

因此對(duì)應(yīng)服務(wù)器要求實(shí)時(shí)性及同時(shí)處理多個(gè)請(qǐng)求的程序,可以同時(shí)使用同步線程和異步線程即采用半同步/半異步模式袱衷。同步線程用于處理客戶邏輯捎废,異步線程用于處理IO事件。異步線程監(jiān)聽到客戶請(qǐng)求后致燥,就將其封裝成請(qǐng)求對(duì)象并插入到請(qǐng)求隊(duì)列中登疗。請(qǐng)求隊(duì)列將通知某個(gè)工作在同步模式的工作線程來讀取并處理該請(qǐng)求對(duì)象。具體哪個(gè)線性處理取決于請(qǐng)求隊(duì)列的設(shè)計(jì)嫌蚤。下圖2為半同步/半異步的工作流程


圖2半同步/半異步的工作流程

在半同步/半異步模式可以變體成為半同步/半反應(yīng)堆(half-sync/half-reactive)辐益,如下圖3

圖3半同步/半反應(yīng)堆模式

半同步/半反應(yīng)堆中,異步線程只有一個(gè)脱吱,即主線程智政,他負(fù)責(zé)監(jiān)聽所有事件,有事件發(fā)生則將事件插入請(qǐng)求隊(duì)列中箱蝠。工作線程休眠在請(qǐng)求隊(duì)列中续捂,當(dāng)任務(wù)到來時(shí),通過競(jìng)爭(zhēng)獲取任務(wù)處理權(quán)宦搬。

在上圖3半同步/半反應(yīng)堆中牙瓢,主線程插入工作隊(duì)列的為就緒的連接socket,他要求工作線程自己socket讀取數(shù)據(jù)和往socket寫入服務(wù)器應(yīng)答床三,所有可以看作Reactor模式。實(shí)際也可以模擬為Proactor模式杨幼,即主線程完成數(shù)據(jù)的讀寫撇簿,將數(shù)據(jù)封裝成任務(wù)對(duì)象插入請(qǐng)求隊(duì)列,工作線程從請(qǐng)求隊(duì)列取出任務(wù)對(duì)象處理差购。(Reactor模式和Reactor模式可以參考此文:服務(wù)器兩種高效的事件處理模式

半同步半反應(yīng)堆模式存在如下缺點(diǎn):

  1. 主線程和工作線程共享請(qǐng)求隊(duì)列四瘫,對(duì)請(qǐng)求隊(duì)列的操作需求加鎖,耗費(fèi)CPU時(shí)間欲逃。
  2. 每一個(gè)工作線程在同一時(shí)間只能處理一個(gè)客戶請(qǐng)求找蜜。客戶數(shù)量多稳析,工作線程少洗做,請(qǐng)求隊(duì)列任務(wù)堆積弓叛,響應(yīng)滿,如果添加試圖通過增加線程則诚纸,由于線程切換導(dǎo)致的CPU時(shí)間消耗撰筷。
    這里我們?cè)俳榻B一種高效的半同步/半異步模式:每個(gè)工作線程都能同時(shí)處理多個(gè)客戶連接。
圖4 高效半同步/半異步模式

主線程只管理監(jiān)聽socket畦徘,連接socket由工作線程來管理毕籽。當(dāng)有新的連接到來時(shí),主線程就接受之并將新返回的連接socket派發(fā)給某個(gè)工作線程井辆,此后該socket上的任何IO操作都由被選中的工作線程來處理关筒,直到客戶端關(guān)閉連接。主線程向工作線程派發(fā)socket的最簡(jiǎn)單的方式杯缺,是往它和工作線程之間的管道里寫數(shù)據(jù)蒸播。工作線程檢測(cè)到管道里有數(shù)據(jù)可讀時(shí),就分析是否是一個(gè)新的客戶連接請(qǐng)求到來夺谁。如果是廉赔,則把該新socket上的讀寫事件注冊(cè)到自己的epoll內(nèi)核事件表中。每個(gè)線程(主線程和工作線程)都維持自己的事件循環(huán)匾鸥,它們各自獨(dú)立的監(jiān)聽不同的事件蜡塌。因此在這種模式中,每個(gè)線程都工作在異步模式勿负,所以它并非嚴(yán)格意義上的半同步半異步模式馏艾。

三、領(lǐng)導(dǎo)者/追隨者模式(Leader/Followers

領(lǐng)導(dǎo)者/追隨者模式是多個(gè)工作線程輪流獲得事件源集合奴愉,輪流監(jiān)聽琅摩、分發(fā)并處理事件的一種模式。在任意時(shí)間點(diǎn)锭硼,程序都僅有一個(gè)領(lǐng)導(dǎo)者線程房资,它負(fù)責(zé)監(jiān)聽I(yíng)O事件。而其他線程都是追隨者檀头,它們休眠在線程池中等待成為新的領(lǐng)導(dǎo)者轰异。當(dāng)前的領(lǐng)導(dǎo)者如果檢測(cè)到IO事件,首先要從線程池中推選出新的領(lǐng)導(dǎo)者線程暑始,然后處理IO事件搭独。此時(shí),新的領(lǐng)導(dǎo)者等待新的IO事件廊镜,而原來的領(lǐng)導(dǎo)者則處理IO事件牙肝,二者實(shí)現(xiàn)了并發(fā)。包含如下幾個(gè)組件:

  • 句柄集(HandleSet)
  • 線程集(ThreadSet)
  • 事件處理器(EventHandler)
  • 具體的事件處理器(ConcreteEventHandler)。

關(guān)系如下圖5


圖5 領(lǐng)導(dǎo)者/追隨者模式的組件

1配椭、句柄集
句柄表示IO資源虫溜,linux下通常是文件描述符。句柄集使用wait_for_event方法監(jiān)聽這些句柄上的IO事件颂郎,并將其中的就緒事件通知給領(lǐng)導(dǎo)者線程吼渡。領(lǐng)導(dǎo)者調(diào)用綁定到Handle上的事件處理器來處理事件。綁定是通過句柄集的register_handle方法實(shí)現(xiàn)的乓序。

2寺酪、線程集
所有工作線程的管理者,負(fù)責(zé)線程同步替劈、推選新領(lǐng)導(dǎo)寄雀。線程在任一時(shí)間必處于以下三種狀態(tài)之一:

  • Leader:領(lǐng)導(dǎo)者線程,負(fù)責(zé)等待句柄集上的IO事件陨献。
  • Processing:線程正在處理事件盒犹。領(lǐng)導(dǎo)者檢測(cè)到IO事件后可以轉(zhuǎn)移至Processing狀態(tài)處理該事件,并調(diào)用promote_new_leader方法推選新領(lǐng)導(dǎo)者眨业;也可以指定其他追隨者來處理事件急膀,此時(shí)領(lǐng)導(dǎo)者地位不變。當(dāng)處于Processing狀態(tài)的線程處理完事件后龄捡,如果當(dāng)前線程集中沒有領(lǐng)導(dǎo)者卓嫂,則它將成為新領(lǐng)導(dǎo)者,否則它直接轉(zhuǎn)為追隨者聘殖。
  • Follower:線程處于追隨者身份晨雳,通過調(diào)用線程集的join方法等待成為新領(lǐng)導(dǎo)者,也可能被領(lǐng)導(dǎo)者指定來處理新的事件奸腺。

這三種狀態(tài)之間的轉(zhuǎn)換關(guān)系圖如下圖6:

圖6 領(lǐng)導(dǎo)者/追隨者模式的狀態(tài)轉(zhuǎn)移

(注意餐禁,領(lǐng)導(dǎo)者推選新領(lǐng)導(dǎo)和追隨者等待成為新領(lǐng)導(dǎo)這兩個(gè)操作都會(huì)修改線程集,因此線程集提供一個(gè)Synchronizer來同步突照。)

3帮非、事件處理器和具體的事件處理器
事件處理器通常包含一個(gè)或多個(gè)回調(diào)函數(shù)handle_event。這些回調(diào)函數(shù)用于處理事件對(duì)應(yīng)的業(yè)務(wù)邏輯讹蘑。事件處理器在使用前需要被綁定到某個(gè)句柄上末盔,當(dāng)該句柄有事件發(fā)生時(shí),領(lǐng)導(dǎo)者就執(zhí)行綁定的事件處理器的回調(diào)函數(shù)衔肢。具體的事件處理器是事件處理器的派生類庄岖。它們重新實(shí)現(xiàn)基類的handle_event方法豁翎,以處理特定的任務(wù)角骤。

由于領(lǐng)導(dǎo)者自己監(jiān)聽I(yíng)O事件并處理客戶請(qǐng)求,該模式不需要在線程間傳遞額外數(shù)據(jù),也無需像半同步/半反應(yīng)堆模式那樣在線程間同步對(duì)請(qǐng)求隊(duì)列的訪問邦尊。但是背桐,該模式的明顯缺點(diǎn)是僅支持一個(gè)事件源集合,因此也無法讓每個(gè)工作線程獨(dú)立管理多個(gè)客戶連接蝉揍。
我們將領(lǐng)導(dǎo)者/追隨者模式的工作流程總結(jié)如下圖7

圖7 領(lǐng)導(dǎo)者/追隨者模式的工作流程

注(本文內(nèi)容參考 Linux高性能服務(wù)器編程——第八章 游雙著)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末链峭,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子又沾,更是在濱河造成了極大的恐慌弊仪,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,816評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件杖刷,死亡現(xiàn)場(chǎng)離奇詭異励饵,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)滑燃,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,729評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門役听,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人表窘,你說我怎么就攤上這事典予。” “怎么了乐严?”我有些...
    開封第一講書人閱讀 158,300評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵瘤袖,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我麦备,道長(zhǎng)孽椰,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,780評(píng)論 1 285
  • 正文 為了忘掉前任凛篙,我火速辦了婚禮黍匾,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘呛梆。我一直安慰自己锐涯,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,890評(píng)論 6 385
  • 文/花漫 我一把揭開白布填物。 她就那樣靜靜地躺著纹腌,像睡著了一般。 火紅的嫁衣襯著肌膚如雪滞磺。 梳的紋絲不亂的頭發(fā)上升薯,一...
    開封第一講書人閱讀 50,084評(píng)論 1 291
  • 那天,我揣著相機(jī)與錄音击困,去河邊找鬼涎劈。 笑死广凸,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的蛛枚。 我是一名探鬼主播谅海,決...
    沈念sama閱讀 39,151評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼蹦浦!你這毒婦竟也來了扭吁?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,912評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤盲镶,失蹤者是張志新(化名)和其女友劉穎侥袜,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體溉贿,經(jīng)...
    沈念sama閱讀 44,355評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡系馆,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,666評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了顽照。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片由蘑。...
    茶點(diǎn)故事閱讀 38,809評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖代兵,靈堂內(nèi)的尸體忽然破棺而出尼酿,到底是詐尸還是另有隱情,我是刑警寧澤植影,帶...
    沈念sama閱讀 34,504評(píng)論 4 334
  • 正文 年R本政府宣布裳擎,位于F島的核電站,受9級(jí)特大地震影響思币,放射性物質(zhì)發(fā)生泄漏鹿响。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,150評(píng)論 3 317
  • 文/蒙蒙 一谷饿、第九天 我趴在偏房一處隱蔽的房頂上張望惶我。 院中可真熱鬧,春花似錦博投、人聲如沸绸贡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽听怕。三九已至,卻和暖如春虑绵,著一層夾襖步出監(jiān)牢的瞬間尿瞭,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,121評(píng)論 1 267
  • 我被黑心中介騙來泰國(guó)打工翅睛, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留声搁,地道東北人鸣峭。 一個(gè)月前我還...
    沈念sama閱讀 46,628評(píng)論 2 362
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像酥艳,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子爬骤,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,724評(píng)論 2 351

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

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,867評(píng)論 25 707
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理充石,服務(wù)發(fā)現(xiàn),斷路器霞玄,智...
    卡卡羅2017閱讀 134,638評(píng)論 18 139
  • 接上一篇《那些山坷剧,那些水【Part I】》惰爬,依然是六月份西藏旅拍的照片,每周發(fā)布9張惫企,大部分后期是由@山里囤 完成...
    不許瞎搞閱讀 485評(píng)論 0 0
  • 要如何才能將記憶里那些過去生活的片段拿出來狞尔,湊成生活本來的樣子丛版?或許永遠(yuǎn)都不可能!我們一路走著偏序,今天比明天聰明一點(diǎn)...
    走魚閱讀 225評(píng)論 0 3
  • 賈寶玉林黛玉薛寶釵名字的同與異 在《紅樓夢(mèng)》中页畦,寫了許許多多的人物,寫了大大小小的事情研儒,描寫了四大家族由盛轉(zhuǎn)哀的...
    舟?閱讀 1,136評(píng)論 7 13