10月19日,云+社區(qū)開發(fā)者大會(huì)(北京站)圓滿落幕。本次開發(fā)者大會(huì)的主題為“5G探索:核心技術(shù)與挑戰(zhàn)”,邀請(qǐng)了騰訊內(nèi)部及業(yè)內(nèi)行業(yè)大咖就5G場(chǎng)景下應(yīng)該如何面對(duì)新業(yè)務(wù)與挑戰(zhàn)?大型網(wǎng)站的技術(shù)應(yīng)該如何進(jìn)化?如何真正理解萬物互聯(lián)?5G有哪些值得探索與實(shí)踐的方向?5G對(duì)應(yīng)用發(fā)展的影響有哪些?等問題進(jìn)行了深度探討。同時(shí),在圓桌論壇環(huán)節(jié),各位技術(shù)專家也與到場(chǎng)的開發(fā)者們展開了開放式對(duì)話,精彩不斷。下邊是李智慧老師關(guān)于反應(yīng)式框架 Flower 的架構(gòu)設(shè)計(jì)原理與思想及落地實(shí)踐與效果的分享。
講師介紹:李智慧,騰訊云TVP,同程藝龍交通首席架構(gòu)師。長(zhǎng)期從事大數(shù)據(jù)、大型網(wǎng)站架構(gòu)的研發(fā)工作,曾擔(dān)任阿里技術(shù)專家、Intel亞太研發(fā)中心架構(gòu)師、宅米和WiFi萬能鑰匙CTO。Apache Spark源代碼貢獻(xiàn)者,著有暢銷書《大型網(wǎng)站技術(shù)架構(gòu):核心原理與案例分析》,極客時(shí)間《從零開始學(xué)大數(shù)據(jù)》專欄作者。現(xiàn)擔(dān)任同程藝龍交通首席架構(gòu)師。
我分享的題目叫“反應(yīng)式編程在同程藝龍的實(shí)踐?!边@個(gè)話題跟5G也有關(guān)系,當(dāng)5G的速度越來越快,終端跟服務(wù)器之間的通訊變得越來越密集,計(jì)算量越來越大的時(shí)候,我們的編程是什么樣子?我不知道今天各位同學(xué)來聽5G,有多少是做后臺(tái)技術(shù)開發(fā)的?5G時(shí)代對(duì)編程的影響是什么樣子?會(huì)使用什么樣的技術(shù)解決這些問題?我大概分享這些東西。
我個(gè)人的背景,現(xiàn)在在同程藝龍交通做首席架構(gòu)師,以前在阿里巴巴任技術(shù)專家,在Intel亞太研發(fā)中心做大數(shù)據(jù)架構(gòu)師,主要參與Apache Spark和Hive開發(fā),后來做過創(chuàng)業(yè),寫過一本書。接下來我們進(jìn)入正題,高并發(fā)是如何導(dǎo)致程序崩潰的?互聯(lián)網(wǎng)應(yīng)用包括將來的物聯(lián)網(wǎng),物聯(lián)網(wǎng)其實(shí)比互聯(lián)網(wǎng)大數(shù)據(jù)更大。典型的特征高并發(fā)大數(shù)據(jù)請(qǐng)求量特別大,數(shù)據(jù)量特別大,這種情況下開發(fā)一個(gè)單人應(yīng)用的系統(tǒng),比如說開發(fā)一個(gè)新浪微博可能幾天就開發(fā)出來,如果給幾億人使用,這個(gè)系統(tǒng)跟幾個(gè)人使用完全不一樣,這個(gè)大家可以理解。
新浪微博每一次技術(shù)進(jìn)步出來后他們做分享的時(shí)候,總是說現(xiàn)在新浪微博技術(shù)架構(gòu)的改進(jìn),可以支撐多少個(gè)人半夜發(fā)布他的信息,這樣去宣傳他的技術(shù)。就是因?yàn)橐坏┝看罅酥?,整個(gè)技術(shù)體系完全不一樣,造成的影響就是典型新浪微博這樣子的。當(dāng)明星們發(fā)布發(fā)一條爆炸性消息的時(shí)候,新浪微博的服務(wù)器就掛掉了,為什么會(huì)掛掉?因?yàn)閹浊f人在轉(zhuǎn)發(fā)這條消息,這些數(shù)據(jù)會(huì)對(duì)服務(wù)器造成很大的壓力,系統(tǒng)會(huì)崩潰。像剛才提到的數(shù)據(jù)量會(huì)呈現(xiàn)幾倍、幾十倍的增加,用戶的應(yīng)用場(chǎng)景也會(huì)更加的復(fù)雜,這個(gè)時(shí)候服務(wù)器如何應(yīng)對(duì)?編程方式是不是也有革命性的變化。
未來究竟什么樣子?連5G本身還在探索的過程中,這個(gè)編程怎么樣?為時(shí)尚早。今天更多分享一下我的看法和實(shí)踐。
高并發(fā)是如何導(dǎo)致程序崩潰的?程序怎么就崩潰了?高并發(fā)的時(shí)候到底發(fā)生了什么?我們看一下后端服務(wù)器的具體架構(gòu)大概這樣子,用戶并發(fā)請(qǐng)求進(jìn)入到服務(wù)器,前面要經(jīng)過負(fù)載均衡,負(fù)載均衡之后進(jìn)入到服務(wù)器,在服務(wù)器里面運(yùn)行著一個(gè)Web容器,Java開發(fā)的話可能就是一個(gè)Tomcat。當(dāng)一個(gè)用戶請(qǐng)求進(jìn)來以后,容器如何去處理這個(gè)請(qǐng)求?寫的程序如何去處理請(qǐng)求?這個(gè)里面有一個(gè)關(guān)鍵點(diǎn)會(huì)被經(jīng)常忽略掉,這個(gè)工作是由Web容器去做的,Web容器去監(jiān)聽80端口,監(jiān)聽80端口以后收到一個(gè)用戶請(qǐng)求,容器就會(huì)為這個(gè)用戶請(qǐng)求創(chuàng)建一個(gè)計(jì)算線程,這個(gè)線程負(fù)責(zé)用戶請(qǐng)求的操作處理,一直到處理完之后返回響應(yīng),每一個(gè)請(qǐng)求進(jìn)來以后都創(chuàng)建一個(gè)線程,里面的線程數(shù)是有限的,現(xiàn)在是200個(gè)線程,創(chuàng)建200個(gè)線程以后如果有更多的用戶請(qǐng)求進(jìn)來怎么辦?就拒絕的,用戶這個(gè)時(shí)候就看到自己的請(qǐng)求失敗了。如果不拒絕,請(qǐng)求繼續(xù)進(jìn)來。進(jìn)入等待隊(duì)列會(huì)消耗資源,服務(wù)器的壓力非常大。如果更多用戶的請(qǐng)求都接受進(jìn)來,服務(wù)器的壓力會(huì)逐漸的增大,超過系統(tǒng)可用資源就會(huì)崩潰。為每一個(gè)用戶獨(dú)占一個(gè)線程造成資源的消耗,這個(gè)線程如果處理結(jié)束都好辦,如果處理來不及,這個(gè)時(shí)候有可能會(huì)導(dǎo)致系統(tǒng)巨大的負(fù)載增加,最后導(dǎo)致系統(tǒng)崩潰,這是一個(gè)點(diǎn)。為什么會(huì)特別慢呢?如果快速處理完釋放了線程,下一個(gè)用戶的請(qǐng)求可以繼續(xù)處理,如果不釋放的話就會(huì)堆積在這里,為什么會(huì)堆積在這里?因?yàn)榫€程被阻塞了,線程為什么被阻塞了?線程不僅僅在當(dāng)?shù)刈鲆恍〤PU處理的計(jì)算,還會(huì)跟外部服務(wù)資源進(jìn)行通信,還要調(diào)用一些其他的微服務(wù),還要訪問數(shù)據(jù)庫,還有其他的東西,這個(gè)時(shí)候線程請(qǐng)求微服務(wù)進(jìn)行遠(yuǎn)程調(diào)用或者是訪問數(shù)據(jù)庫都有可能,當(dāng)請(qǐng)求遠(yuǎn)程操作的時(shí)候,請(qǐng)求是被阻塞了的,如果遠(yuǎn)程這些資源訪問的話快速響應(yīng)過來,也都還好。如果這個(gè)時(shí)候數(shù)據(jù)庫里面有個(gè)表,因?yàn)槭裁丛蝽憫?yīng)特別的慢,這個(gè)時(shí)候線程遲遲不能釋放,它不能釋放別的請(qǐng)求就沒有線程可用,就回到剛才所說的場(chǎng)景系統(tǒng)就崩潰了。這還是現(xiàn)在,就經(jīng)常會(huì)遇到這種崩潰的情況。如果到5G時(shí)代,請(qǐng)求會(huì)更加的頻繁和密集,計(jì)算量會(huì)越來越大。這種情況下,我們的系統(tǒng)崩潰的會(huì)更加頻繁,我認(rèn)為就是要面對(duì)這種問題。
解決方案,反應(yīng)式編程大家都知道,有一些比較主流的解決方案。我們這邊自己搞了一個(gè)編程框架叫Flower,我們看一下Flower怎么解決這些問題的?請(qǐng)求還是并發(fā)進(jìn)入容器,容器就要監(jiān)聽那個(gè)端口,這個(gè)時(shí)候我們看看Flower是怎么解決這個(gè)問題的?Flower又是如何實(shí)現(xiàn)的?分為兩步:
第一步,請(qǐng)求進(jìn)入容器以后,每一個(gè)請(qǐng)求不再占據(jù)一個(gè)線程,把它異步化。每一個(gè)請(qǐng)求進(jìn)來以后,容器還會(huì)啟動(dòng)一個(gè)線程,啟動(dòng)線程之后把傳輸過來的二進(jìn)制流轉(zhuǎn)換成對(duì)象,轉(zhuǎn)換成對(duì)象以后,容器的工作就結(jié)束了,這個(gè)容器線程工作就結(jié)束了,把這個(gè)請(qǐng)求交給后面,想象一下容器只要啟動(dòng)一個(gè)線程。做這件事情可以是亞毫秒級(jí)的,1毫秒以內(nèi)就可以完成這個(gè)協(xié)議的處理,因?yàn)樗蛔鲇?jì)算,只是把協(xié)議處理完就可以,這個(gè)時(shí)候如果還是200個(gè),300個(gè)、500個(gè)都沒有關(guān)系,幾百個(gè)并發(fā)請(qǐng)求一秒鐘過來,它的處理是亞毫秒級(jí)的,一秒鐘可以處理1000以上的請(qǐng)求,一個(gè)線程處理幾百個(gè)請(qǐng)求都是綽綽有余的,因?yàn)樗]有做太多的事情,只是把請(qǐng)求分發(fā)出去,一個(gè)線程就可以做這么多的事情,處理所有的請(qǐng)求。請(qǐng)求進(jìn)來之后,這個(gè)時(shí)候就不會(huì)被拒絕,以前200個(gè)線程300個(gè)線程就沒有了,現(xiàn)在2000個(gè)請(qǐng)求進(jìn)來之后,一個(gè)線程全部處理了,所有數(shù)據(jù)全都處理了。然后這個(gè)請(qǐng)求就交給后面的處理,我們有一個(gè)Flower自己的運(yùn)行環(huán)境,理論上講也可以是只用一個(gè)線程。200個(gè)請(qǐng)求進(jìn)來以后,變成200個(gè)請(qǐng)求對(duì)象,或者更多個(gè)請(qǐng)求,2000個(gè)請(qǐng)求對(duì)象,2000個(gè)請(qǐng)求對(duì)象交給我們的Service去處理,2000個(gè)請(qǐng)求進(jìn)來可以迅速的把2000個(gè)請(qǐng)求都算完,計(jì)算只有零點(diǎn)零幾毫秒,幾毫秒可能就有2000個(gè)請(qǐng)求,而且只有一個(gè)線程。大家可以想象一個(gè)線程可以同時(shí)處理2000個(gè)請(qǐng)求,它處理完之后再交給下一個(gè)Service處理,這個(gè)里面是做一些預(yù)處理、參數(shù)校驗(yàn),后面真正的做邏輯計(jì)算,把它的處理交給下一個(gè)Service,下一個(gè)Service也可以復(fù)用剛才的線程,因?yàn)閯偛诺木€程算了ServiceA,也可以繼續(xù)算ServiceB,只需要一個(gè)線程就可以把所有的請(qǐng)求整個(gè)處理邏輯全部處理完。理論上可以這樣做到,處理完以后訪問數(shù)據(jù)庫,訪問數(shù)據(jù)庫的時(shí)候給數(shù)據(jù)庫發(fā)一個(gè)請(qǐng)求,同步數(shù)據(jù)庫處理的時(shí)候線程會(huì)處于阻塞狀態(tài),等到數(shù)據(jù)庫有了返回以后,線程就會(huì)被喚醒,喚醒以后它去執(zhí)行。從異步的方式來講,把這個(gè)請(qǐng)求發(fā)過去以后,查數(shù)據(jù)庫的SQL發(fā)出去以后,線程就沒事了,可以繼續(xù)處理Service,不用等。等到數(shù)據(jù)庫真正有響應(yīng)結(jié)果以后,我們想象以下有個(gè)ServiceC,有了結(jié)果以后變成消息了,都是消息啟動(dòng),返回來的消息就是數(shù)據(jù)庫返回來的結(jié)果集,交給ServiceC,ServiceC又有消息等著處理,它也是獨(dú)立的。ServiceC有消息處理的時(shí)候,這個(gè)線程還可以回到ServiceC,處理完之后返回到結(jié)果,就可以把ServiceC拿到的結(jié)果返回回去。通過這樣的方式,利用一個(gè)線程就把整個(gè)業(yè)務(wù)全部處理了。這個(gè)里面有一個(gè)線程專門做業(yè)務(wù)邏輯的處理,有一個(gè)線程專門做請(qǐng)求的接入,阻塞式編程200個(gè)線程就是200個(gè)請(qǐng)求,任何一種打破平衡都會(huì)導(dǎo)致系統(tǒng)失效宕機(jī)了。但是Flower利用這種方式只用幾個(gè)線程可以解決2000個(gè)請(qǐng)求。解決方案核心點(diǎn)是這樣的,如果處理的速度足夠快,資源比較平衡的話,可能處理更多的并發(fā)請(qǐng)求,系統(tǒng)算力會(huì)變得更加的強(qiáng)大。當(dāng)5G來臨用戶請(qǐng)求更多的時(shí)候,可以支持更大的算力。
這是Flower,它的工作原理是這樣子去提高性能。這是真實(shí)在同程藝龍做的一個(gè)重構(gòu),紅色是重構(gòu)后的,綠色是重構(gòu)前的,做了一次Flower重構(gòu)。左側(cè)是吞吐量TPS,綠色是重構(gòu)前的,紅色是重構(gòu)后的,重構(gòu)前是200TPS,重構(gòu)以后是450TPS,現(xiàn)在提升了1倍多。右邊是響應(yīng)時(shí)間,紅色是重構(gòu)后的,綠色是重構(gòu)前的。經(jīng)過重構(gòu)以后發(fā)現(xiàn)響應(yīng)時(shí)間特性表現(xiàn)的更好一點(diǎn),特別是在高并發(fā)情況下。
Flower究竟怎么實(shí)現(xiàn)的?剛才提到一個(gè)消息驅(qū)動(dòng)。Flower自己沒有運(yùn)行時(shí)環(huán)境,剛才這樣一套都有自己的運(yùn)行時(shí)環(huán)境。Flower底層利用Akka的Actor,我們看一下在Actor進(jìn)行通訊的時(shí)候怎么做的?為什么理想情況下,用一個(gè)線程就完成所有的服務(wù)計(jì)算?在傳統(tǒng)的編程里面服務(wù)調(diào)用、方法調(diào)用,當(dāng)A方法調(diào)B方法的時(shí)候,A方法的代碼行里面加了一行調(diào)用B方法的代碼,B方法執(zhí)行的時(shí)候,A方法下一行代碼一定是不執(zhí)行,傳統(tǒng)的方法調(diào)用是這樣子,都是阻塞式的編程,所謂阻塞似的編程當(dāng)你調(diào)用別的計(jì)算時(shí),當(dāng)前執(zhí)行一定是阻塞的,調(diào)用其他的方法執(zhí)行,執(zhí)行完了再返回,所有的執(zhí)行都是在由一個(gè)線程串起來,我們的代碼可以寫A方法,團(tuán)隊(duì)合作的時(shí)候那個(gè)團(tuán)隊(duì)實(shí)現(xiàn)A方法,另外一個(gè)團(tuán)隊(duì)實(shí)現(xiàn)B方法,但是我們可以在A里面調(diào)B。但是運(yùn)行期都是由一個(gè)線程執(zhí)行的,A執(zhí)行進(jìn)入B方法以后由B方法去執(zhí)行,執(zhí)行完了返回繼續(xù)執(zhí)行A方法,這是阻塞式編程。
在Actor模型里面,所有的計(jì)算都是以Actor為單位進(jìn)行,Actor之間的調(diào)用沒有延時(shí)和阻塞,由Actor調(diào)用另外一個(gè)Actor,是直接給另外一個(gè)Actor發(fā)個(gè)消息,發(fā)完消息可以繼續(xù)做別的,如果有消息的話可以繼續(xù)處理,Actor是通過消息傳輸進(jìn)行計(jì)算調(diào)用的,而不是直接的方法依賴調(diào)用的。
這個(gè)里面不同點(diǎn)有兩點(diǎn),他們之間沒有依賴和耦合,前面我們說一個(gè)公司有兩個(gè)團(tuán)隊(duì)在工作,一個(gè)團(tuán)隊(duì)寫了A方法,一個(gè)團(tuán)隊(duì)寫了B方法。A團(tuán)隊(duì)用A方法調(diào)B方法的時(shí)候,一定要依賴B方法的代碼,一定要知道B方法的簽名是什么樣子,即使通過接口定義的話,一定要依賴這個(gè)接口,方法簽名必須要知道,要知道它才能去調(diào)用,這是一種耦合。
第二,他們之間調(diào)用是阻塞的,我去調(diào)用B方法的時(shí)候,一旦調(diào)用B方法,B方法返回之前一定不能執(zhí)行下一行代碼,這是強(qiáng)耦合的阻塞。Actor將這兩點(diǎn)都解決了,當(dāng)兩個(gè)Actor進(jìn)行通信的時(shí)候,不需要去阻塞,也不需要依賴你,我就是把我的消息發(fā)送給你就可以,你能夠去處理我的消息就可以,大家基于中間消息協(xié)議進(jìn)行編程,不是基于方法依賴進(jìn)行編程。發(fā)送者也是Actor,發(fā)送者要給另外一個(gè)Actor發(fā)個(gè)消息讓他進(jìn)行處理的時(shí)候,和A方法調(diào)B方法一回事,我調(diào)一個(gè)B方法,其實(shí)是讓B方法幫忙我去處理,這跟我給他發(fā)一個(gè)消息處理也是一樣子,邏輯上是一回事。當(dāng)Actor給另外一個(gè)Actor發(fā)消息的時(shí)候,這個(gè)過程其實(shí)是持有另外一個(gè)Actor的Ref,這個(gè)Ref就是一個(gè)路徑,只要找到Actor就可以。知道Actor以后,就通過ActorRef發(fā)消息,ActorRef把消息推到郵箱里面,然后Actor立刻返回,你什么時(shí)候處理我不管,發(fā)送完之后自己可以做別的。另外一個(gè)Actor檢查郵箱里面是否有消息,如果有消息取出消息進(jìn)行處理,處理完之后要調(diào)別的Actor消息發(fā)出去,自己也結(jié)束了。在這個(gè)里面一方面Actor之間沒有依賴和耦合,我不需要知道你在哪里,這個(gè)Actor可能在一個(gè)機(jī)器里,也可能在天邊,都沒有關(guān)系,只要能把這個(gè)消息投遞進(jìn)去就可以,可以遠(yuǎn)程投遞。另外沒有阻塞,發(fā)給你以后你什么時(shí)候處理不管你,發(fā)給你以后我就結(jié)束了,可以繼續(xù)做我的事情。
最終產(chǎn)生的效果,由一個(gè)線程去掃描所有的Actor郵箱里有沒有消息,有消息就把消息拿出來讓另外一個(gè)Actor處理,處理完以后看其他的Actor是否也有消息,一個(gè)線程可以掃描所有Actor。線程是很重的,但是Actor可以創(chuàng)建幾百萬個(gè)都沒有關(guān)系,可以輕量的創(chuàng)建,如果沒有消息大家都很安靜,如果有了消息就取消息進(jìn)行處理。理想情況下,一個(gè)線程可以掃描幾百萬,只用一個(gè)線程就可以做到,資源更省,調(diào)用更加的低耦合,操作更加的異步,無需阻塞。剛才提到的一些特性都是Actor提供給我們的。如果大家自己寫Actor發(fā)送這些消息,去找這些消息或者是處理消息之類,這些是很痛苦的一件事情,我自己在英特爾時(shí)用Actor做過大數(shù)據(jù)的程序,有點(diǎn)小亂。如果日常用Actor進(jìn)行開發(fā)還是有點(diǎn)痛苦,我們要做的Flower把Actor分裝成Service,像傳統(tǒng)的編程Service一樣,只需要寫Service代碼后編排一下流程,這個(gè)Service結(jié)束以后下一個(gè)Service怎么樣處理?在編程應(yīng)用流程做一個(gè)包裝。
使用這個(gè)框架做異步開發(fā)非常的簡(jiǎn)單,5分鐘就開發(fā)完。第一步寫個(gè)Service,進(jìn)來以后總是一個(gè)個(gè)操作,比如說我們利用一個(gè)Service調(diào)用一個(gè)Service,寫Service服務(wù)就好了,寫服務(wù)用框架提供的Service接口,做的就是輸入一個(gè)消息輸出一個(gè)消息,這個(gè)Service要處理的消息是什么樣?拿到消息以后在里面進(jìn)行處理,這個(gè)時(shí)候Service就完成。要用多個(gè)Service去完成的話,我們其實(shí)提倡Service的粒度越小、功能越單一,越能夠復(fù)用。整個(gè)的處理過程拆分成很小的Service,把這些Service串聯(lián)起來就好,串聯(lián)成一個(gè)流程在系統(tǒng)里自動(dòng)的完成,串聯(lián)成流程也非常的簡(jiǎn)單,可以編輯流程。Service寫的時(shí)候并不知道下一個(gè)Service如何處理,但是寫完以后變成流程,上手5分鐘就可以。
這是Flower的可視化,可以通過編程的方式把ServiceABC編成一個(gè)流程,也可以用更復(fù)雜一點(diǎn)的,最好用可視化的脫拽方式進(jìn)行編程,同時(shí)調(diào)用Service2和Service3,處理完以后交給Service5處理,Service交給Service4處理,Service4再返回Service3,最后匯總計(jì)算,用這樣的方式完成編排,提供可視化。當(dāng)然現(xiàn)在可以用文本編寫進(jìn)行編輯,要實(shí)現(xiàn)什么功能拖進(jìn)來就好,當(dāng)你要修改編碼的時(shí)候,中間處理的時(shí)候請(qǐng)用戶驗(yàn)證,加一個(gè)驗(yàn)證,也不需要去修改代碼,需要加一個(gè)Service拖到流程里面多一個(gè)驗(yàn)證,代碼完全不用修改。
如果用Spring編程的話,這個(gè)里是Spring調(diào)用的框架。
這是異步數(shù)據(jù)庫的訪問,系統(tǒng)會(huì)自動(dòng)把結(jié)果拿回來交給下一個(gè)Service處理,中間不會(huì)等待數(shù)據(jù)庫返回,不會(huì)停在那里。這個(gè)我們?cè)?jīng)遇到過一個(gè)案例,其中數(shù)據(jù)庫里面一張表特別慢,也不是系統(tǒng)崩潰,系統(tǒng)崩潰還好,系統(tǒng)崩潰一旦連接失敗后就失效,失效就返回。這個(gè)時(shí)候沒有崩潰,發(fā)一個(gè)請(qǐng)求過去還能響應(yīng),響應(yīng)5s、10s、20s這個(gè)時(shí)候就痛苦了,APP連接就超時(shí)了,這個(gè)時(shí)候一直給你一種慢查詢,占據(jù)線程,線程一直不能釋放。我們通過網(wǎng)關(guān)調(diào)用微服務(wù),微服務(wù)訪問數(shù)據(jù)庫然后調(diào)用其他第三方服務(wù)。微服務(wù)訪問這一張表里面就是特別慢,用了幾十秒,微服務(wù)全部被阻塞。因?yàn)榫W(wǎng)關(guān)也是調(diào)的微服務(wù),網(wǎng)關(guān)跟微服務(wù)之間也是同樣,因?yàn)樗鼪]有響應(yīng),所以網(wǎng)關(guān)跟微服務(wù)之間的消息全都是延遲,導(dǎo)致網(wǎng)關(guān)的線程全部被微服務(wù)阻塞。網(wǎng)關(guān)被微服務(wù)阻塞以后,線程都被微服務(wù)占滿,一張表導(dǎo)致所有的網(wǎng)關(guān)線程全部被鎖死,所有請(qǐng)求都進(jìn)不來,最后整個(gè)系統(tǒng)宕機(jī)了。這個(gè)微服務(wù)失效,對(duì)系統(tǒng)僅僅影響一些不太重要的業(yè)務(wù)場(chǎng)景,但是最后導(dǎo)致全部的服務(wù)停止。如果用Flower異步架構(gòu)的話,不會(huì)出現(xiàn)這種問題,不占用任何線程,你失效以后失去響應(yīng)了,頂多延遲的話用戶通訊延遲,不會(huì)阻塞整個(gè)線程,導(dǎo)致整個(gè)系統(tǒng)崩潰。
遠(yuǎn)程怎么辦?剛才提到遠(yuǎn)程通訊的異步微服務(wù)解決方案,服務(wù)是可編排的,這些Service可以跟網(wǎng)關(guān)應(yīng)用程序放在一起,也可以分布式編排。分布式編排微服務(wù)有一個(gè)注冊(cè)中心,在注冊(cè)中心進(jìn)行流程編排,第一個(gè)服務(wù)處理完之后下一個(gè)服務(wù)進(jìn)行處理,然后進(jìn)行可視化的編排。編排完以后,我要使用哪個(gè)流程進(jìn)行請(qǐng)求數(shù)據(jù)?這是根據(jù)URL綁定的請(qǐng)求,請(qǐng)求進(jìn)來以后就知道我通過哪個(gè)流程處理請(qǐng)求,到注冊(cè)中心把請(qǐng)求拉下來,看看哪個(gè)服務(wù)需要,把請(qǐng)求發(fā)送給它,底層是Actor通訊,底層給到它之后,自己自動(dòng)結(jié)束,處理下一個(gè)請(qǐng)求,我就發(fā)給它,然后到下一個(gè)Service,也會(huì)很好的異步化處理,處理完之后交給下一個(gè)Service,也可能是個(gè)遠(yuǎn)程的,可以通過Actor遠(yuǎn)程通信發(fā)送過去。一旦完成這個(gè)消息的投遞本身就結(jié)束了,結(jié)束之后就可以繼續(xù)處理。
這種情況下的遠(yuǎn)程編排變得更加的簡(jiǎn)單,因?yàn)檎{(diào)用之間沒有任何的依賴?,F(xiàn)在的編程依賴還是一個(gè)比較大的問題,一旦有了依賴,如果接口變化整個(gè)編程會(huì)非常的痛苦。而如果沒有任何的依賴你,這個(gè)里面前一個(gè)請(qǐng)求是下一個(gè)流程,下一個(gè)請(qǐng)求又走到另外一個(gè)Actor的Service去了,非常輕松。場(chǎng)景就算比較復(fù)雜,有這樣開發(fā)的功能,真正靈活用起來,我個(gè)人覺得還是比較憧憬。
為什么選擇Flower?現(xiàn)在已經(jīng)有一些反應(yīng)式編程框架,總的來說Flower是反應(yīng)式編程框架,Actor本身的編程有點(diǎn)不友好,對(duì)人們的編程習(xí)慣有些挑戰(zhàn),所以我們的技術(shù)用Flower這樣的編程框架。它為什么不用Web Flux和RxJava,如果我不想要函數(shù)式編程,用反應(yīng)式編程是被綁架的。其實(shí)你可以不用,反應(yīng)式編程無阻塞的及時(shí)響應(yīng)就可以了,我們可以很好的及時(shí)響應(yīng)。還有個(gè)消息驅(qū)動(dòng),沒有消息緩存,如果有大量的請(qǐng)求進(jìn)來系統(tǒng)崩潰怎么辦?MailBox是有溢出機(jī)制的,MailBox接收10個(gè)消息和20個(gè)消息,系統(tǒng)不會(huì)崩潰的。以前系統(tǒng)架構(gòu)一個(gè)解決方案處理不了那么多的請(qǐng)求怎么辦?那就限流,限流在請(qǐng)求的時(shí)候拒絕,到底什么時(shí)候拒絕我不知道,現(xiàn)在來說我們用MailBox任何一個(gè)Service處理不過來的時(shí)候,它自動(dòng)就溢出了,溢出就把消息丟棄了,也可以不丟棄,放在一個(gè)什么地方,重新走一個(gè)通道繼續(xù)處理也可以,而且非常的靈活,消息驅(qū)動(dòng)。更好的性能和更低的成本,更高的可能性。成本非常低,如果用的話幾分鐘能搞定,用起來好用,不需要自己搞一套比較痛苦的東西。