老樹新花-Java異步服務(wù)開發(fā)

內(nèi)容來源:2017年5月13日篱竭,餓了么資深Java工程師朱杰在“Java開發(fā)者大會 | Java之美【上海站】”進(jìn)行《老樹新花-Java異步服務(wù)開發(fā)》演講分享摄凡。IT大咖說作為獨(dú)家視頻合作方锋谐,經(jīng)主辦方和講者審閱授權(quán)發(fā)布。

閱讀字?jǐn)?shù):1901 用時(shí): 13分鐘

摘要

餓了么資深Java工程師朱杰從同步異步概念介紹盖文、使用Java來開發(fā)異步化服務(wù)、回調(diào)監(jiān)聽模式所遇到的問題和解決這三方面來我們?nèi)娼庾xJava異步服務(wù)開發(fā)淋肾。

嘉賓演講視頻回顧及PPT:http://suo.im/4rwo2Y

同步模型

以前在并發(fā)量很低的情況下,是通過線程去收取數(shù)據(jù)并發(fā)送數(shù)據(jù)給客戶端爸邢。但是當(dāng)并發(fā)量和客戶端連接數(shù)比較高的時(shí)候樊卓,服務(wù)器會出現(xiàn)明顯的瓶頸。

阻塞模型比較符合人的思考邏輯杠河,但它會有線程阻塞的問題碌尔。阻塞模型會讓出CPU,不適用于高并發(fā)券敌。

線程池或連接池只能解決一部分問題唾戚。因?yàn)榫€程池和連接池的本質(zhì)作用并不是能直接提高QPS,而是減少或銷毀線程的連接處以及開銷待诅。

我們平時(shí)調(diào)用阻塞API的一個(gè)問題就在于單機(jī)的線程數(shù)是有限的叹坦。所以如果要提高服務(wù)端性能的話,首先就要去阻塞卑雁。

異步模型

異步阻塞模型處理I/O時(shí)大部分時(shí)間是非阻塞的(監(jiān)聽時(shí)除外)募书,它調(diào)用的API會立即返回,這點(diǎn)是需要注意的测蹲。此外莹捡,處理結(jié)果的程序并不保證調(diào)用API當(dāng)前的線程,這點(diǎn)在處理線程安全的問題上尤其要注意扣甲。

Java中很多API都是基于操作系統(tǒng)底層API的模型篮赢,并沒有做更高層次的封裝。

Java把一層阻塞異部I/O做了封裝文捶,這些就是Java或C語言異步模型的基石荷逞。

少數(shù)線程等待事件發(fā)生媒咳,再根據(jù)對應(yīng)類型處理相關(guān)事件粹排。

最近“協(xié)程”這個(gè)詞比較火,看上去能解決異步模型的大部分問題涩澡。它是一個(gè)輕量級線程顽耳,可以直接當(dāng)作線程來用。還能阻塞I/O API妙同,阻塞的是協(xié)程而非線程射富。

協(xié)程是用戶態(tài)資源,用戶態(tài)調(diào)度粥帚,消耗極低胰耗,可以啟動數(shù)十萬個(gè)協(xié)程。

它的實(shí)現(xiàn)和線程不是1對1 的關(guān)系芒涡,難點(diǎn)在于編程語言的內(nèi)部實(shí)現(xiàn)柴灯。

Python雖然支持協(xié)程卖漫,但是由于全局解釋鎖的關(guān)系,同一時(shí)刻只有單個(gè)CPU在運(yùn)行赠群。所以python選擇多進(jìn)程+協(xié)程的做法羊始。

Go語言完美解決了支持不阻塞線程的I/O操作,并支持多線程查描。

要能像同步I/O一樣編寫代碼突委,不會創(chuàng)造過多數(shù)量的線程。盡量讓CPU處于忙碌狀態(tài)而非等待冬三,并尋找滿足以上條件的Java庫匀油。但是Java由于本身語言的問題,即使是Java協(xié)程三方庫也只能部分支持協(xié)程长豁。

退而求其次钧唐,我們只能使用Java異步工具庫。如果要提高并發(fā)量匠襟,可以使用異步JDBC和異步HTTP CLIENT钝侠,這個(gè)庫基于NETTY。

做到服務(wù)異步化酸舍,要查看接口是否可支持異步帅韧。還可以使用Java的異步工具庫,比如Java的異步數(shù)據(jù)訪問方式和異步HTTP CLIENT啃勉。如果使用的是三方框架忽舟,可以修改調(diào)用方式,有的框架支持異步回調(diào)和事件監(jiān)聽淮阐。最重要的是要注意線程安全問題叮阅。

異步化的優(yōu)勢就是極大提高了I/O密集型業(yè)務(wù)的性能,保守估計(jì)有10~100倍泣特,也就解決了線程數(shù)創(chuàng)建過多的問題浩姥。

而它的缺點(diǎn)是增加了編程難度,包括狀態(tài)保存状您、回調(diào)處理以及線程安全等勒叠。也存在壓垮下游服務(wù)的問題:)

老樹新花-基于Netty的Java模型

Netty是基于原生的異步模型,封裝并優(yōu)化膏孟。它修復(fù)JDK中的一些BUG眯分,提供了多種輔助類方便開發(fā)。編程模型高效簡單柒桑,開發(fā)者只需關(guān)心具體實(shí)現(xiàn)邏輯即可弊决,基本不用花精力做Java網(wǎng)絡(luò)層面的優(yōu)化。此外魁淳,Netty成熟穩(wěn)定飘诗,業(yè)界使用多傅联,我們能夠相信,使用它不會遇到難以解決的大問題疚察。

Netty基于事件連接蒸走,如果有數(shù)據(jù)傳入以及連接上有異常事件或自定義事件,只需復(fù)寫它的回調(diào)函數(shù)就能做相應(yīng)的處理貌嫡。

Netty所有I/O API全都是消除阻塞異步化比驻。線程模式也非常好,它單個(gè)連接上的所有I/O事件都由同一個(gè)線程執(zhí)行岛抄,避免了線程安全問題别惦。

Netty的單個(gè)鏈接綁定一個(gè)線程,EVENTLOOP即一個(gè)線程夫椭,EVENTLOOPGROUP是一個(gè)線程組掸掸。

Netty任何的I/O API都是產(chǎn)生一個(gè)任務(wù),放入該連接對應(yīng)的線程里執(zhí)行蹭秋,做到局部串行化扰付。

Netty一切操作都是以事件驅(qū)動來執(zhí)行,所有I/O API都是用異步+回調(diào)監(jiān)聽的方式來處理消息仁讨。單一的連接處理都在一個(gè)線程里羽莺,來避免線程安全問題。

案例-餓了么數(shù)據(jù)庫中間件

我們是一個(gè)實(shí)現(xiàn)了MYSQL協(xié)議的中間代理服務(wù)洞豁。上游至少要支持上萬客戶端的連接盐固,下游要支持上千數(shù)據(jù)庫連接。

為了快速實(shí)現(xiàn)功能丈挟,我們最早是找了一個(gè)基于GITHUB阻塞I/O開源庫刁卜,首要任務(wù)是把同步改為了異步。

線程模型的上下游各有Netty的一個(gè)線程組曙咽,中間件內(nèi)部還有一個(gè)處理業(yè)務(wù)的線程組蛔趴。

但有一個(gè)最本質(zhì)的問題在于這三個(gè)線程組之間的線程安全得不到保證。

因?yàn)檫@個(gè)中間件前后端都是異步的桐绒,所以按正常流程是由協(xié)議來保證順序執(zhí)行夺脾,而異常中斷是并發(fā)執(zhí)行的之拨。

參考Netty茉继,我們把每一個(gè)連接綁定到一個(gè)單線程池,保證Task串行執(zhí)行蚀乔。

前后端異步的好處在于模型簡單烁竭,便于后續(xù)修改。

我個(gè)人認(rèn)為吉挣,在程序里過多的使用WAIT/NOTIFY/LOCK不一定代表良好的多線程編程能力宣决,卻可能代表這是不夠優(yōu)雅的設(shè)計(jì)蚁孔。

除了前后端異步和信號量控制異步列林,在中間件中我們還用到了日志異步、心跳異步镀赌、JOB異步和配置變更異步。

在餓了么數(shù)據(jù)庫中間件開發(fā)過程中际跪,異步化所有API以去除阻塞商佛,局部串行化解決線程安全問題,模型簡單姆打,易于修改和理解良姆。

今天的分享就到這里,謝謝大家幔戏!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末玛追,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子闲延,更是在濱河造成了極大的恐慌痊剖,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,490評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件垒玲,死亡現(xiàn)場離奇詭異邢笙,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)侍匙,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評論 3 395
  • 文/潘曉璐 我一進(jìn)店門氮惯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人想暗,你說我怎么就攤上這事妇汗。” “怎么了说莫?”我有些...
    開封第一講書人閱讀 165,830評論 0 356
  • 文/不壞的土叔 我叫張陵杨箭,是天一觀的道長。 經(jīng)常有香客問我储狭,道長互婿,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,957評論 1 295
  • 正文 為了忘掉前任辽狈,我火速辦了婚禮慈参,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘刮萌。我一直安慰自己驮配,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,974評論 6 393
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著壮锻,像睡著了一般琐旁。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上猜绣,一...
    開封第一講書人閱讀 51,754評論 1 307
  • 那天灰殴,我揣著相機(jī)與錄音,去河邊找鬼掰邢。 笑死验懊,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的尸变。 我是一名探鬼主播义图,決...
    沈念sama閱讀 40,464評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼召烂!你這毒婦竟也來了碱工?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤奏夫,失蹤者是張志新(化名)和其女友劉穎怕篷,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體酗昼,經(jīng)...
    沈念sama閱讀 45,847評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡廊谓,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,995評論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了麻削。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蒸痹。...
    茶點(diǎn)故事閱讀 40,137評論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖呛哟,靈堂內(nèi)的尸體忽然破棺而出叠荠,到底是詐尸還是另有隱情,我是刑警寧澤扫责,帶...
    沈念sama閱讀 35,819評論 5 346
  • 正文 年R本政府宣布榛鼎,位于F島的核電站,受9級特大地震影響鳖孤,放射性物質(zhì)發(fā)生泄漏者娱。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,482評論 3 331
  • 文/蒙蒙 一苏揣、第九天 我趴在偏房一處隱蔽的房頂上張望黄鳍。 院中可真熱鬧,春花似錦腿准、人聲如沸际起。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽街望。三九已至,卻和暖如春弟跑,著一層夾襖步出監(jiān)牢的瞬間灾前,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評論 1 272
  • 我被黑心中介騙來泰國打工孟辑, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留哎甲,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,409評論 3 373
  • 正文 我出身青樓饲嗽,卻偏偏與公主長得像炭玫,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子貌虾,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,086評論 2 355

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