18 | 單服務(wù)器高性能模式:PPC與TPC

高性能是最復(fù)雜的一環(huán),磁盤紫谷、操作系統(tǒng)齐饮、CPU捐寥、內(nèi)存、緩存祖驱、網(wǎng)絡(luò)握恳、編程語言、架構(gòu)等捺僻,每個都有可能影響系統(tǒng)達(dá)到高性能乡洼,一行不恰當(dāng)?shù)?debug 日志,就可能將服務(wù)器的性能從 TPS 30000 降低到 8000匕坯;一個 tcp_nodelay 參數(shù)束昵,就可能將響應(yīng)時間從 2 毫秒延長到 40 毫秒

高性能架構(gòu)設(shè)計服務(wù)器性能發(fā)揮到極致葛峻;設(shè)計服務(wù)器集群方案锹雏,還和具體實(shí)現(xiàn)及編碼相關(guān)。

服務(wù)器高性能:??并發(fā)模型:如何管理連接术奖、處理請求礁遵,和操作系統(tǒng)?I/O及進(jìn)程模型相關(guān)。

? ??I/O 模型:阻塞采记、非阻塞佣耐、同步、異步唧龄。

? ??進(jìn)程模型:單進(jìn)程晰赞、多進(jìn)程、多線程选侨。

? ??單服務(wù)器高性能:PPC 與 TPC。

PPC

Process Per Connection然走,有新連接就新建進(jìn)程處理援制,傳統(tǒng)的UNIX 網(wǎng)絡(luò)服務(wù)器用

父進(jìn)程接受連接(圖中 accept)。

父進(jìn)程“fork”子進(jìn)程(圖中 fork)芍瑞。

子進(jìn)程處理連接的讀寫請求(圖中子進(jìn)程 read晨仑、業(yè)務(wù)處理、write)拆檬。

子進(jìn)程關(guān)閉連接(圖中子進(jìn)程中的 close)洪己。

注意,圖中有一個小細(xì)節(jié)竟贯,父進(jìn)程“fork”子進(jìn)程后答捕,直接調(diào)用了 close,看起來好像是關(guān)閉了連接屑那,其實(shí)只是將連接的文件描述符引用計數(shù)減一拱镐,真正的關(guān)閉連接是等子進(jìn)程也調(diào)用 close 后艘款,連接對應(yīng)的文件描述符引用計數(shù)變?yōu)?0 后,操作系統(tǒng)才會真正關(guān)閉連接沃琅,更多細(xì)節(jié)請參考《UNIX 網(wǎng)絡(luò)編程:卷一》哗咆。

PPC 模式實(shí)現(xiàn)簡單,比較適合服務(wù)器的連接數(shù)沒那么多的情況益眉,例如數(shù)據(jù)庫服務(wù)器晌柬。對于普通的業(yè)務(wù)服務(wù)器,在互聯(lián)網(wǎng)興起之前郭脂,由于服務(wù)器的訪問量和并發(fā)量并沒有那么大年碘,這種模式其實(shí)運(yùn)作得也挺好,世界上第一個 web 服務(wù)器 CERN httpd 就采用了這種模式(具體你可以參考https://en.wikipedia.org/wiki/CERN_httpd)朱庆∈⑴荩互聯(lián)網(wǎng)興起后,服務(wù)器的并發(fā)和訪問量從幾十劇增到成千上萬娱颊,這種模式的弊端就凸顯出來了傲诵,主要體現(xiàn)在這幾個方面:

fork 代價高:站在操作系統(tǒng)的角度,創(chuàng)建一個進(jìn)程的代價是很高的箱硕,需要分配很多內(nèi)核資源拴竹,需要將內(nèi)存映像從父進(jìn)程復(fù)制到子進(jìn)程。即使現(xiàn)在的操作系統(tǒng)在復(fù)制內(nèi)存映像時用到了 Copy on Write(寫時復(fù)制)技術(shù)剧罩,總體來說創(chuàng)建進(jìn)程的代價還是很大的栓拜。

父子進(jìn)程通信復(fù)雜:父進(jìn)程“fork”子進(jìn)程時,文件描述符可以通過內(nèi)存映像復(fù)制從父進(jìn)程傳到子進(jìn)程惠昔,但“fork”完成后幕与,父子進(jìn)程通信就比較麻煩了杖们,需要采用 IPC(Interprocess Communication)之類的進(jìn)程通信方案嫌佑。例如质和,子進(jìn)程需要在 close 之前告訴父進(jìn)程自己處理了多少個請求以支撐父進(jìn)程進(jìn)行全局的統(tǒng)計寓辱,那么子進(jìn)程和父進(jìn)程必須采用 IPC 方案來傳遞信息岂座。

并發(fā)連接數(shù)量有限:如果每個連接存活時間比較長太示,而且新的連接又源源不斷的進(jìn)來镀钓,則進(jìn)程數(shù)量會越來越多病毡,操作系統(tǒng)進(jìn)程調(diào)度和切換的頻率也越來越高啦扬,系統(tǒng)的壓力也會越來越大中狂。因此,一般情況下扑毡,PPC 方案能處理的并發(fā)連接數(shù)量最大也就幾百胃榕。

prefork

PPC 模式中,當(dāng)連接進(jìn)來時才 fork 新進(jìn)程來處理連接請求瞄摊,由于 fork 進(jìn)程代價高勤晚,用戶訪問時可能感覺比較慢枉层,prefork 模式的出現(xiàn)就是為了解決這個問題。

顧名思義赐写,prefork 就是提前創(chuàng)建進(jìn)程(pre-fork)鸟蜡。系統(tǒng)在啟動的時候就預(yù)先創(chuàng)建好進(jìn)程,然后才開始接受用戶的請求挺邀,當(dāng)有新的連接進(jìn)來的時候揉忘,就可以省去 fork 進(jìn)程的操作,讓用戶訪問更快端铛、體驗(yàn)更好泣矛。prefork 的基本示意圖是:

prefork 的實(shí)現(xiàn)關(guān)鍵就是多個子進(jìn)程都 accept 同一個 socket,當(dāng)有新的連接進(jìn)入時禾蚕,操作系統(tǒng)保證只有一個進(jìn)程能最后 accept 成功您朽。但這里也存在一個小小的問題:“驚群”現(xiàn)象,就是指雖然只有一個子進(jìn)程能 accept 成功换淆,但所有阻塞在 accept 上的子進(jìn)程都會被喚醒哗总,這樣就導(dǎo)致了不必要的進(jìn)程調(diào)度和上下文切換了。幸運(yùn)的是倍试,操作系統(tǒng)可以解決這個問題讯屈,例如 Linux 2.6 版本后內(nèi)核已經(jīng)解決了 accept 驚群問題。

prefork 模式和 PPC 一樣县习,還是存在父子進(jìn)程通信復(fù)雜涮母、支持的并發(fā)連接數(shù)量有限的問題,因此目前實(shí)際應(yīng)用也不多躁愿。Apache 服務(wù)器提供了 MPM prefork 模式叛本,推薦在需要可靠性或者與舊軟件兼容的站點(diǎn)時采用這種模式,默認(rèn)情況下最大支持 256 個并發(fā)連接彤钟。

TPC

Thread Per Connection来候,新連接就建線程處理。更輕量級样勃,創(chuàng)建線程的消耗比進(jìn)程要少得多;同時多線程是共享進(jìn)程內(nèi)存空間的性芬,線程通信相比進(jìn)程通信更簡單峡眶。因此,TPC 實(shí)際上是解決或者弱化了 PPC fork 代價高的問題和父子進(jìn)程通信復(fù)雜的問題植锉。

父進(jìn)程接受連接(圖中 accept)辫樱。

父進(jìn)程創(chuàng)建子線程(圖中 pthread)。

子線程處理連接的讀寫請求(圖中子線程 read俊庇、業(yè)務(wù)處理狮暑、write)鸡挠。

子線程關(guān)閉連接(圖中子線程中的 close)。

注意搬男,和 PPC 相比拣展,主進(jìn)程不用“close”連接了。原因是在于子線程是共享主進(jìn)程的進(jìn)程空間的缔逛,連接的文件描述符并沒有被復(fù)制备埃,因此只需要一次 close 即可。

TPC 雖然解決了 fork 代價高和進(jìn)程通信復(fù)雜的問題褐奴,但是也引入了新的問題按脚,具體表現(xiàn)在:

創(chuàng)建線程雖然比創(chuàng)建進(jìn)程代價低,但并不是沒有代價敦冬,高并發(fā)時(例如每秒上萬連接)還是有性能問題辅搬。

無須進(jìn)程間通信,但是線程間的互斥和共享又引入了復(fù)雜度脖旱,可能一不小心就導(dǎo)致了死鎖問題堪遂。

多線程會出現(xiàn)互相影響的情況,某個線程出現(xiàn)異常時夯缺,可能導(dǎo)致整個進(jìn)程退出(例如內(nèi)存越界)蚤氏。

除了引入了新的問題,TPC 還是存在 CPU 線程調(diào)度和切換代價的問題踊兜。因此竿滨,TPC 方案本質(zhì)上和 PPC 方案基本類似,在并發(fā)幾百連接的場景下捏境,反而更多地是采用 PPC 的方案于游,因?yàn)?PPC 方案不會有死鎖的風(fēng)險,也不會多進(jìn)程互相影響垫言,穩(wěn)定性更高贰剥。

prethread

TPC 模式中,當(dāng)連接進(jìn)來時才創(chuàng)建新的線程來處理連接請求筷频,雖然創(chuàng)建線程比創(chuàng)建進(jìn)程要更加輕量級蚌成,但還是有一定的代價,而 prethread 模式就是為了解決這個問題凛捏。

和 prefork 類似担忧,prethread 模式會預(yù)先創(chuàng)建線程,然后才開始接受用戶的請求坯癣,當(dāng)有新的連接進(jìn)來的時候瓶盛,就可以省去創(chuàng)建線程的操作,讓用戶感覺更快、體驗(yàn)更好惩猫。

由于多線程之間數(shù)據(jù)共享和通信比較方便芝硬,因此實(shí)際上 prethread 的實(shí)現(xiàn)方式相比 prefork 要靈活一些,常見的實(shí)現(xiàn)方式有下面幾種:

主進(jìn)程 accept轧房,然后將連接交給某個線程處理拌阴。

子線程都嘗試去 accept,最終只有一個線程 accept 成功锯厢,方案的基本示意圖如下:

Apache 服務(wù)器的 MPM worker 模式本質(zhì)上就是一種 prethread 方案皮官,但稍微做了改進(jìn)。Apache 服務(wù)器會首先創(chuàng)建多個進(jìn)程实辑,每個進(jìn)程里面再創(chuàng)建多個線程捺氢,這樣做主要是為了考慮穩(wěn)定性,即:即使某個子進(jìn)程里面的某個線程異常導(dǎo)致整個子進(jìn)程退出剪撬,還會有其他子進(jìn)程繼續(xù)提供服務(wù)摄乒,不會導(dǎo)致整個服務(wù)器全部掛掉

prethread 理論上可以比 prefork 支持更多的并發(fā)連接残黑,Apache 服務(wù)器 MPM worker 模式默認(rèn)支持 16 × 25 = 400 并發(fā)處理線程馍佑。

小結(jié)

什么樣的系統(tǒng)比較適合本期所講的高性能模式?原因是什么梨水?

評論1:

不同并發(fā)模式的選擇拭荤,還要考察三個指標(biāo),分別是響應(yīng)時間(RT)疫诽,并發(fā)數(shù)(Concurrency)舅世,吞吐量(TPS)。三者關(guān)系奇徒,吞吐量=并發(fā)數(shù)/平均響應(yīng)時間雏亚。不同類型的系統(tǒng),對這三個指標(biāo)的要求不一樣摩钙。

三高系統(tǒng)罢低,比如秒殺、即時通信胖笛,不能使用网持。

三低系統(tǒng),比如ToB系統(tǒng)长踊,運(yùn)營類功舀、管理類系統(tǒng),一般可以使用之斯。

高吞吐系統(tǒng)日杈,如果是內(nèi)存計算為主的,一般可以使用佑刷,如果是網(wǎng)絡(luò)IO為主的莉擒,一般不能使用。

評論2:

高并發(fā)需要根據(jù)兩個條件劃分:連接數(shù)量瘫絮,請求數(shù)量涨冀。

1. 海量連接(成千上萬)海量請求:例如搶購,雙十一等

這樣的系統(tǒng)麦萤,我覺得這講所說的模式都不適應(yīng)鹿鳖,面對海量的連接至少要使用IO復(fù)用模型或者異步IO模型,針對海量的請求壮莹,無論使用多進(jìn)程處理還是多線程翅帜,單機(jī)都是無法支撐的,應(yīng)該集群了吧命满。

2. 常量連接(幾十上百)海量請求:例如中間件

3. 海量連接常量請求:例如門戶網(wǎng)站

這種系統(tǒng)我覺得非常適合使用netty這樣的NIO框架來實(shí)現(xiàn)涝滴,IO復(fù)用模型可以處理海量的連接,而每個連接的請求數(shù)據(jù)量會很小胶台,處理會很長快歼疮,如華仔說的門戶網(wǎng)站,只要簡單返回頁面即可诈唬。

4. 常量連接常量請求:例如內(nèi)部運(yùn)營系統(tǒng)韩脏,管理系統(tǒng)

這種系統(tǒng),本講的模式就很適合了铸磅。

評論3:

BIO一個線程處理一個請求赡矢。缺點(diǎn):高并發(fā)量,線程數(shù)多愚屁,浪費(fèi)資源济竹。Tomcat7或以下,在Linux系統(tǒng)中默認(rèn)使用這種方式霎槐∷妥牵可以適用于小到中規(guī)模的客戶端并發(fā)數(shù)場景,無法勝任大規(guī)模并發(fā)業(yè)務(wù)丘跌。如果編程控制不善袭景,可能造成系統(tǒng)資源耗盡。

NIO:多路復(fù)用IO闭树,少量線程處理大量的請求耸棒。Tomcat8在Linux系統(tǒng)中默認(rèn)用。Tomcat7必須修改Connector配置來啟動报辱。適用于“高并發(fā)”

評論3:

如何根據(jù)硬件配置計算可支持的并發(fā)數(shù)呢与殃?一般按照CPU核數(shù)*2來計算

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子幅疼,更是在濱河造成了極大的恐慌米奸,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,907評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件爽篷,死亡現(xiàn)場離奇詭異悴晰,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)逐工,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,987評論 3 395
  • 文/潘曉璐 我一進(jìn)店門铡溪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人泪喊,你說我怎么就攤上這事棕硫。” “怎么了袒啼?”我有些...
    開封第一講書人閱讀 164,298評論 0 354
  • 文/不壞的土叔 我叫張陵饲帅,是天一觀的道長。 經(jīng)常有香客問我瘤泪,道長灶泵,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,586評論 1 293
  • 正文 為了忘掉前任对途,我火速辦了婚禮赦邻,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘实檀。我一直安慰自己惶洲,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,633評論 6 392
  • 文/花漫 我一把揭開白布膳犹。 她就那樣靜靜地躺著恬吕,像睡著了一般。 火紅的嫁衣襯著肌膚如雪须床。 梳的紋絲不亂的頭發(fā)上铐料,一...
    開封第一講書人閱讀 51,488評論 1 302
  • 那天,我揣著相機(jī)與錄音豺旬,去河邊找鬼钠惩。 笑死,一個胖子當(dāng)著我的面吹牛族阅,可吹牛的內(nèi)容都是我干的篓跛。 我是一名探鬼主播,決...
    沈念sama閱讀 40,275評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼坦刀,長吁一口氣:“原來是場噩夢啊……” “哼愧沟!你這毒婦竟也來了蔬咬?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,176評論 0 276
  • 序言:老撾萬榮一對情侶失蹤沐寺,失蹤者是張志新(化名)和其女友劉穎计盒,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體芽丹,經(jīng)...
    沈念sama閱讀 45,619評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,819評論 3 336
  • 正文 我和宋清朗相戀三年卜朗,在試婚紗的時候發(fā)現(xiàn)自己被綠了拔第。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,932評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡场钉,死狀恐怖蚊俺,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情逛万,我是刑警寧澤泳猬,帶...
    沈念sama閱讀 35,655評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站宇植,受9級特大地震影響得封,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜指郁,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,265評論 3 329
  • 文/蒙蒙 一忙上、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧闲坎,春花似錦疫粥、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,871評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至绣溜,卻和暖如春慷彤,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背怖喻。 一陣腳步聲響...
    開封第一講書人閱讀 32,994評論 1 269
  • 我被黑心中介騙來泰國打工瞬欧, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人罢防。 一個月前我還...
    沈念sama閱讀 48,095評論 3 370
  • 正文 我出身青樓艘虎,卻偏偏與公主長得像,于是被迫代替她去往敵國和親咒吐。 傳聞我的和親對象是個殘疾皇子野建,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,884評論 2 354

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