本次分享基于微服務(wù)的應(yīng)用架構(gòu)設(shè)計(jì)煞檩,內(nèi)容涉及如何構(gòu)建一個(gè)微服務(wù)應(yīng)用,服務(wù)注冊(cè)與發(fā)現(xiàn)栅贴,微服務(wù)測(cè)試和典型的微服務(wù)架構(gòu)設(shè)計(jì)模式斟湃,以及微服務(wù)架構(gòu)在七牛的實(shí)踐案例。
目錄
構(gòu)建一個(gè)微服務(wù)應(yīng)用
服務(wù)注冊(cè)與發(fā)現(xiàn)
微服務(wù)測(cè)試
典型微服務(wù)架構(gòu)設(shè)計(jì)模式
七牛微服務(wù)架構(gòu)實(shí)踐
構(gòu)建一個(gè)微服務(wù)應(yīng)用
首先我們通過(guò)一個(gè)最簡(jiǎn)單的例子來(lái)看下如何構(gòu)建一個(gè)微服務(wù)應(yīng)用檐薯。
圖 1 是一個(gè)完整服務(wù)的代碼凝赛,它和普通的應(yīng)用程序沒(méi)什么區(qū)別,只是功能非常少坛缕,業(yè)務(wù)非常簡(jiǎn)單墓猎。把它編譯之后部署在服務(wù)端就能跑起來(lái),我們從上往下解釋一下這段代碼干了什么事情:
在第 6 行我們引入一個(gè)包 “github.com/koding/kite”赚楚,這是一個(gè)開源的微服務(wù)框架包毙沾,使用它可以快速方便的構(gòu)建一個(gè)微服務(wù)應(yīng)用;
第 11 和 12 行我們定義一個(gè)微服務(wù)宠页,并將其取名為 first左胞;
第 15 行開始我們?yōu)檫@個(gè)微服務(wù)添加了一個(gè) square 操作指令供外部調(diào)用,這是負(fù)責(zé)完成具體功能的業(yè)務(wù)單元举户,在這里它負(fù)責(zé)將外部傳入過(guò)來(lái)的值進(jìn)行求平方計(jì)算后返回給調(diào)用方罩句;
最后在第 21 行我們把它注冊(cè)到框架提供的某個(gè)地方,并聲明了它的訪問(wèn)地址和協(xié)議敛摘。
圖 1. 服務(wù)端代碼
這個(gè)服務(wù)實(shí)現(xiàn)了一個(gè)供外部調(diào)用的功能门烂,我們把它稱之為 server 端。接下來(lái)我們?cè)賹?shí)現(xiàn)一個(gè)調(diào)用這個(gè)它的客戶端兄淫,我們稱之為 client 端屯远。在真實(shí)的微服務(wù)環(huán)境中,并沒(méi)有嚴(yán)格區(qū)分 server 端和 client 端捕虽,只要有需要慨丐,它們都可能會(huì)相互調(diào)用。
同樣的泄私,我們從上往下看看圖 2 這段代碼干了什么事情:
圖 2. 客戶端的代碼
除了第 6 行引入的 “github.com/koding/kite” 包之外房揭,我們還引入了另外一個(gè) “github.com/koding/kite/protocol” 包备闲,它用于做環(huán)境中的微服務(wù)發(fā)現(xiàn);
第 15 行開始我們通過(guò)配置環(huán)境中的信息在環(huán)境中查找所有名字為 “first” 的微服務(wù)捅暴。之所以說(shuō)「查找所有」恬砂,是因?yàn)樵诟鼜?fù)雜的生產(chǎn)環(huán)境中,一個(gè)微服務(wù)往往可能包含多個(gè)副本蓬痒,并且這個(gè)副本數(shù)是動(dòng)態(tài)伸縮的泻骤,因此需要專門的服務(wù)注冊(cè)和發(fā)現(xiàn)過(guò)程來(lái)動(dòng)態(tài)注冊(cè)和動(dòng)態(tài)查找,我們后面會(huì)講到更具體的模式梧奢;
在第 22 行中我們選擇第 1 個(gè)結(jié)果狱掂,也就是第一個(gè)微服務(wù)進(jìn)行訪問(wèn);
在第 26 行中傳入?yún)?shù) 4亲轨,調(diào)用指令 “square” 求平方趋惨,得到結(jié)果;
這是一個(gè)服務(wù)調(diào)用另一個(gè)服務(wù)的演示過(guò)程惦蚊,從中可以看出它涉及到服務(wù)的構(gòu)建希柿、注冊(cè)和發(fā)現(xiàn)。后面這個(gè) client 端例子在演示中雖然沒(méi)有監(jiān)聽端口养筒,只是訪問(wèn)別的微服務(wù),但是它也能監(jiān)聽端口對(duì)外提供服務(wù)端姚,本質(zhì)上 server 和 client 兩端從微服務(wù)架構(gòu)角度說(shuō)并沒(méi)有嚴(yán)格區(qū)分晕粪,只是在不同時(shí)候扮演不同的角色履行不同的職責(zé)。
上面兩個(gè)示例中我們提到服務(wù)注冊(cè)和發(fā)現(xiàn)渐裸。實(shí)際生產(chǎn)環(huán)境中巫湘,微服務(wù)的種類和每個(gè)微服務(wù)副本數(shù)可能都非常多,特別是在相互調(diào)用之后昏鹃,它們雜糅在一起的業(yè)務(wù)可能非常復(fù)雜尚氛。同時(shí),復(fù)雜多變的環(huán)境決定了系統(tǒng)中運(yùn)行的微服務(wù)隨時(shí)可能被啟停洞渤,這也是擁抱微服務(wù)的價(jià)值點(diǎn)之一:主動(dòng)擁抱系統(tǒng)的不穩(wěn)定性阅嘶,通過(guò)消除這種不穩(wěn)定性帶來(lái)的影響來(lái)達(dá)到高可用的目的。為此载迄,需要引入服務(wù)注冊(cè)和發(fā)現(xiàn)機(jī)制來(lái)幫助系統(tǒng)治理這些服務(wù)讯柔。
服務(wù)注冊(cè)與發(fā)現(xiàn)
我們?cè)賮?lái)看一下,為什么這么簡(jiǎn)單的代碼中還需要多一個(gè)服務(wù)注冊(cè)的步驟护昧?
一個(gè)微服務(wù)起來(lái)之后魂迄,要對(duì)外提供服務(wù),必須讓別人知道它的存在惋耙,因此需要有一個(gè)地方讓它「注冊(cè)」捣炬,我們把它稱為「注冊(cè)中心」熊昌。由于微服務(wù)的啟停是隨時(shí)都可能發(fā)生的,和啟停對(duì)應(yīng)的是服務(wù)的注冊(cè)和解除注冊(cè)湿酸,因此在這里我們說(shuō)到注冊(cè)的時(shí)候默認(rèn)也隱含解除注冊(cè)婿屹,后續(xù)不再贅述。解除注冊(cè)是為了保證下線的服務(wù)不會(huì)被調(diào)用方訪問(wèn)到稿械。
假如這兩個(gè)服務(wù)都有多個(gè)實(shí)例副本选泻,它部署起來(lái)如圖 3 所示。在實(shí)際生產(chǎn)環(huán)境中美莫,每個(gè)服務(wù)實(shí)例 A页眯、B 和 C 都是動(dòng)態(tài)變化的,整個(gè)服務(wù)的過(guò)程中可能一直有多個(gè)副本在那里跑著厢呵,但不一定都是相同的實(shí)例窝撵,它們的 IP 在服務(wù)動(dòng)態(tài)伸縮過(guò)程中會(huì)發(fā)生變化。那么如何讓客戶端及時(shí)的知道這種變化呢襟铭?我們知道碌奉,微服務(wù)提倡多個(gè)服務(wù)解耦比較干凈,因此讓一個(gè)服務(wù)主動(dòng)通知另外一個(gè)服務(wù)它的變化是不太現(xiàn)實(shí)的寒砖,這樣侵入對(duì)方業(yè)務(wù)太深了赐劣,耦合太緊。同時(shí)哩都,在后端有多個(gè)服務(wù)實(shí)例的情況下魁兼,如何將客戶端的請(qǐng)求負(fù)載均衡的分發(fā)到各個(gè)實(shí)例中呢?
圖 3. 沒(méi)有服務(wù)發(fā)現(xiàn)的問(wèn)題
在這些問(wèn)題面前漠嵌,和傳統(tǒng)的單體架構(gòu)相比咐汞,微服務(wù)中服務(wù)的注冊(cè)和發(fā)現(xiàn)能力非常重要,甚至有些微服務(wù)框架自帶了服務(wù)的注冊(cè)和發(fā)現(xiàn)功能(比如我們給的例子中用到的 kite 這個(gè)框架就自帶了這樣的功能)儒鹿。
一個(gè)服務(wù)起來(lái)之后化撕,它的注冊(cè)和解除注冊(cè)過(guò)程可以由自己去完成,也可以由第三方工具去完成约炎。比如在客戶端和微服務(wù)端之間的負(fù)載均衡器可能會(huì)幫助微服務(wù)完成服務(wù)的注冊(cè)和解除注冊(cè)等操作植阴,客戶端和微服務(wù)自身都不需要關(guān)心,也即不需要他們各自的業(yè)務(wù)邏輯里面實(shí)現(xiàn)這些操作圾浅。還有一些情況是在客戶端自帶服務(wù)查詢模塊墙贱,它先從服務(wù)注冊(cè)中心查詢可用的服務(wù),然后再按照這個(gè)查詢結(jié)果去請(qǐng)求后端服務(wù)實(shí)例贱傀。下面我們分別解釋這兩種模式惨撇。
圖 3. 沒(méi)有服務(wù)發(fā)現(xiàn)的問(wèn)題
圖 4 中給出的是以客戶端查詢?yōu)橹鞯姆?wù)注冊(cè)和發(fā)現(xiàn)機(jī)制,后端服務(wù)實(shí)例起來(lái)之后府寒,會(huì)以主動(dòng)或者被動(dòng)的形式注冊(cè)到「注冊(cè)中心」魁衙”ㄇ唬客戶端自帶的「查詢模塊」會(huì)從「注冊(cè)中心」查詢可用的服務(wù),然后按照查詢結(jié)果去請(qǐng)求后端服務(wù)實(shí)例剖淀。
這樣做的好處是:
「注冊(cè)中心」在服務(wù)之外維護(hù)纯蛾,使用簡(jiǎn)單,對(duì)已有的微服務(wù)架構(gòu)侵入凶莞簟翻诉;
客戶端直接請(qǐng)求后端實(shí)例,查詢完成后請(qǐng)求鏈路不需要經(jīng)過(guò)其它中間環(huán)節(jié)捌刮。
其缺點(diǎn)在于:
客戶端和「注冊(cè)中心」綁定碰煌;
客戶端的實(shí)現(xiàn)取決于具體語(yǔ)言或者框架,每個(gè)客戶端都得自己去實(shí)現(xiàn)绅作。
圖 5. 服務(wù)端服務(wù)發(fā)現(xiàn)
我們?cè)賮?lái)看下服務(wù)端實(shí)現(xiàn)的服務(wù)注冊(cè)和發(fā)現(xiàn)機(jī)制芦圾,如圖 5 所示。同樣的俄认,后端服務(wù)實(shí)例起來(lái)之后个少,會(huì)通過(guò)主動(dòng)或者被動(dòng)的方式注冊(cè)到「注冊(cè)中心」,但是客戶端不需要實(shí)現(xiàn)查詢模塊去查詢服務(wù)了眯杏,取而代之的是我們?cè)诜?wù)端添加一個(gè)「路由」環(huán)節(jié)夜焦,它負(fù)責(zé)代理客戶端的所有請(qǐng)求,從后端實(shí)例獲取結(jié)果之后返回給客戶端岂贩。與客戶端服務(wù)發(fā)現(xiàn)機(jī)制相比茫经,它具有以下優(yōu)點(diǎn):
客戶端不需要做額外的變更;
有些云服務(wù)公司已經(jīng)提供類似產(chǎn)品可以滿足需求了河闰,可以直接接入。
但它也有它的缺點(diǎn):
除非是托管在云服務(wù)提供商那里褥紫,否則還需要額外的服務(wù)端來(lái)部署「路由」或者「負(fù)載均衡器」部分姜性,這也就意味著需要保證這個(gè)部分的可靠性和可用性,需要額外的系統(tǒng)設(shè)計(jì)和運(yùn)維工作髓考;
請(qǐng)求多了一個(gè)路由代理的步驟部念,增加系統(tǒng)總體耗時(shí)。
在這里給大家提供一個(gè)交流氨菇,討論的平臺(tái)儡炼,JAVA微服務(wù)討論群:671017482 ,
微服務(wù)測(cè)試
圖 6. 測(cè)試金字塔
我們今天介紹微服務(wù)查蓉,首先假設(shè)系統(tǒng)到了一定的復(fù)雜度乌询,使用傳統(tǒng)的單體架構(gòu)已經(jīng)不能滿足需求了,必須將單體架構(gòu)上的功能拆分成職責(zé)和功能單一的微服務(wù)才能更好的跟上業(yè)務(wù)的發(fā)展豌研。因此妹田,由微服務(wù)構(gòu)建的系統(tǒng)往往是一個(gè)復(fù)雜的分布式系統(tǒng)唬党,它的測(cè)試涉及到從里到外的各個(gè)環(huán)節(jié)。
接下來(lái)我們分三部分來(lái)介紹分布式系統(tǒng)中涉及到的測(cè)試:常規(guī)測(cè)試鬼佣、混沌測(cè)試和流量重現(xiàn)驶拱。
我們先來(lái)看一個(gè)測(cè)試金字塔,如圖 6 所示晶衷,它包含:?jiǎn)卧獪y(cè)試蓝纲、集成測(cè)試、組件測(cè)試晌纫、端到端測(cè)試和探索性測(cè)試税迷。接下來(lái)我們要介紹的「常規(guī)測(cè)試」包含金字塔地下的四部分,它還包含另外一種不太常見類型的測(cè)試缸匪,也即契約測(cè)試翁狐,下面會(huì)介紹到。而混沌測(cè)試或者猴子測(cè)試則屬于探索性測(cè)試凌蔬。
常規(guī)測(cè)試
1. 單元測(cè)試
單元測(cè)試是幾乎所有系統(tǒng)開發(fā)都會(huì)涉及到的環(huán)節(jié)露懒,它覆蓋最細(xì)粒度的測(cè)試范圍,一般基于類甚至是方法來(lái)進(jìn)行自動(dòng)化測(cè)試砂心。它測(cè)試的范疇一般不涉及跨網(wǎng)絡(luò)的調(diào)用懈词,因此相對(duì)簡(jiǎn)單。在傳統(tǒng)的 Web 開發(fā)中辩诞,非常流行的測(cè)試驅(qū)動(dòng)開發(fā) TDD 里面講的測(cè)試一般基于單元測(cè)試坎弯,單元測(cè)試用例不僅定義了業(yè)務(wù)邊界,還將業(yè)務(wù)模塊進(jìn)行了細(xì)分译暂。
2. 集成測(cè)試
集成測(cè)試將相關(guān)模塊組合在一起抠忘,在業(yè)務(wù)上構(gòu)成一個(gè)子系統(tǒng)進(jìn)行測(cè)試,它的主要目的在于驗(yàn)證構(gòu)成一個(gè)子系統(tǒng)的所有路勁上的調(diào)用是否正確外永,模塊組合在一起后調(diào)用產(chǎn)生的結(jié)果是否符合預(yù)期崎脉。比如兩個(gè)服務(wù)之間的調(diào)用,或者服務(wù)和數(shù)據(jù)庫(kù)之間的通信伯顶,一般都屬于集成測(cè)試的范疇囚灼。
3. 組件測(cè)試
與集成測(cè)試相反,組件測(cè)試關(guān)注的是組件內(nèi)部功能的完備性祭衩。對(duì)于微服務(wù)應(yīng)用來(lái)說(shuō)灶体,一個(gè)微服務(wù)即一個(gè)組件,為了測(cè)試這個(gè)組件內(nèi)部功能的完備性掐暮,需要盡量減少外部環(huán)境對(duì)其造成的影響蝎抽。當(dāng)該微服務(wù)依賴于一些外部服務(wù)或者數(shù)據(jù)庫(kù)調(diào)用的時(shí)候,我們可以 mock 一些外部服務(wù)路克,同時(shí)使用內(nèi)存數(shù)據(jù)來(lái)代替數(shù)據(jù)庫(kù)數(shù)據(jù)织中,這樣可以盡量減少外部服務(wù)調(diào)用對(duì)它產(chǎn)生的影響锥涕,只關(guān)注單個(gè)微服務(wù)自身的測(cè)試。
4. 契約測(cè)試
契約測(cè)試和組件測(cè)試的所需的邊界非常像狭吼,對(duì)于微服務(wù)來(lái)說(shuō)层坠,它們的所涉及的邊界都是微服務(wù)本身。但和組件測(cè)試不同的是刁笙,契約測(cè)試更關(guān)注輸入?yún)?shù)和輸出結(jié)果的合法性破花,一定的合法輸入必須得到一定的合法輸出,也即測(cè)試一個(gè)服務(wù)是否滿足一定的契約疲吸;另外座每,契約測(cè)試還關(guān)注相應(yīng)的結(jié)果是在多長(zhǎng)時(shí)間內(nèi)得到的,也即服務(wù)響應(yīng)的性能摘悴。這時(shí)候?qū)σ粋€(gè)服務(wù)的測(cè)試峭梳,其所依賴的服務(wù)不能通過(guò) mock 或者內(nèi)存數(shù)據(jù)來(lái)代替。
5. 端到端測(cè)試
為了驗(yàn)證一個(gè)系統(tǒng)是否符合客戶需求和商業(yè)目標(biāo)蹂喻,需要一個(gè)覆蓋產(chǎn)品完整鏈路的測(cè)試葱椭。對(duì)于有用戶 UI 界面的產(chǎn)品,端到端的測(cè)試意味著包括 UI 界面的測(cè)試和后端服務(wù)的測(cè)試口四。由于涉及到的環(huán)節(jié)最多麸俘,因此這樣的測(cè)試運(yùn)行起來(lái)也比較慢得问,出現(xiàn)故障的時(shí)候排查問(wèn)題也比較麻煩。為了加快這個(gè)測(cè)試環(huán)節(jié)鳖链,通常建議:
將盡可能多的測(cè)試需求自動(dòng)化到千。
不必每個(gè)組件的修改都觸發(fā)端到端測(cè)試若河,可以在所有更小粒度的測(cè)試完成之后再做一遍端到端測(cè)試催烘。
之所以把上面所有的測(cè)試稱為「常規(guī)測(cè)試」辅髓,是因?yàn)檫@些測(cè)試基本上在所有類型的現(xiàn)代化軟件開發(fā)中都可能涉及到,它其實(shí)不是微服務(wù)架構(gòu)都有的更卒,微服務(wù)架構(gòu)下的這些測(cè)試只是邊界不太一樣等孵。統(tǒng)計(jì)對(duì)比表明,上線之前完整的測(cè)試可以避免 90% 以上的錯(cuò)誤導(dǎo)致的故障逞壁。
關(guān)于常規(guī)的測(cè)試流济,我們只在這里做簡(jiǎn)單的介紹锐锣,想詳細(xì)了解每種測(cè)試覆蓋的范疇或者最佳實(shí)踐的同學(xué)可以參考這個(gè) Martin Fowler 網(wǎng)站上 Toby Clemson 關(guān)于微服務(wù)測(cè)試的分享:http://martinfowler.com/articles/microservice-testing/
混沌測(cè)試
在分布式系統(tǒng)領(lǐng)域腌闯,Netflix 發(fā)明了一種更為古怪的測(cè)試,叫混沌測(cè)試雕憔,Netflix 稱之為猴子測(cè)試姿骏。什么意思呢?它假設(shè)斤彼,如果你的系統(tǒng)足夠健壯分瘦,那么隨便啟停某些服務(wù)并不會(huì)影響系統(tǒng)的整體運(yùn)行蘸泻,用戶并不會(huì)感知到服務(wù)的故障。我們經(jīng)常講要構(gòu)建容忍故障的高可用服務(wù)嘲玫,但是如果故障沒(méi)有來(lái)悦施,就沒(méi)法驗(yàn)證這樣的服務(wù)是否可以容忍某些極端情況的故障。為此去团,Netflix 在系統(tǒng)中引入了一系列搞破壞的「猴子」抡诞,它會(huì)主動(dòng)給系統(tǒng)的各個(gè)部分制造麻煩,比如隨時(shí)不小心關(guān)閉一臺(tái)機(jī)器土陪,但是你的服務(wù)還得繼續(xù)運(yùn)行昼汗,所有故障必須自動(dòng)恢復(fù),并且不能被用戶感知到鬼雀。
圖 7. Netflix猴子軍團(tuán)
Netflix 的猴子軍團(tuán):
Chaos Monkey: 隨機(jī)殺死實(shí)例
Latency Monkey: 人為引入延遲
Chaos Gorilla: 模擬整個(gè)可用區(qū)突然斷電
猴子軍團(tuán)中的幾種不同類型的機(jī)器人分別代表了不同的破壞性顷窒,它在穩(wěn)定的線上環(huán)境中隨機(jī)選擇破壞。這樣的測(cè)試模擬了自然災(zāi)難源哩,對(duì)線上環(huán)境進(jìn)行了全黑盒式的演練鞋吉,讓線上系統(tǒng)產(chǎn)生「免疫」。遺憾的是璧疗,即便所幸躲過(guò)所有這些「自然災(zāi)難」坯辩,也無(wú)法說(shuō)明系統(tǒng)是沒(méi)問(wèn)題的。
流量重現(xiàn)
我們前面提到端到端的測(cè)試很難做崩侠,主要是難在它整個(gè)鏈路太長(zhǎng)漆魔,耗時(shí)太長(zhǎng),環(huán)節(jié)也難以控制却音。另外一個(gè)難點(diǎn)在于改抡,我們通常很難獲得和線上一樣真實(shí)的流量去進(jìn)行端到端的測(cè)試,即便某個(gè)環(huán)節(jié)能夠成功模擬相應(yīng)的請(qǐng)求系瓢,但也不是所有請(qǐng)求的比例和線上都是一致的阿纤。
為了模擬線上請(qǐng)求,我們可以講線上流量截獲后導(dǎo)入到測(cè)試環(huán)境中通過(guò)「流量重現(xiàn)」的方式夷陋,在一個(gè)更加真實(shí)的模擬環(huán)境中觀察和調(diào)整欠拾。在這里介紹一個(gè)用 Go 寫的開源工具
圖 8. 流量重現(xiàn)工具 Gor
通過(guò)監(jiān)聽線上服務(wù)的請(qǐng)求,它能夠截獲線上環(huán)境的流量骗绕,并將其在測(cè)試和開發(fā)環(huán)境中重現(xiàn)藐窄,如上圖所示。
典型微服務(wù)架構(gòu)設(shè)計(jì)模式
圖 9. 典型微服務(wù)設(shè)計(jì)模式
圖 9 是一個(gè)典型的微服務(wù)架構(gòu)圖酬土。服務(wù)注冊(cè)和發(fā)現(xiàn)的架構(gòu)圖前面講過(guò)荆忍,為了簡(jiǎn)化圖的結(jié)構(gòu),此圖不再提及∩餐鳎客戶端的請(qǐng)求首先會(huì)到達(dá)一個(gè)負(fù)責(zé)對(duì)外溝通的 API Gateway叽唱,它負(fù)責(zé)識(shí)別客戶端類型,解析和理解客戶端的請(qǐng)求微宝,并將請(qǐng)求分發(fā)到后端對(duì)應(yīng)的微服務(wù)中完成棺亭。
一般來(lái)講,基于 HTTP REST API 的請(qǐng)求都是同步執(zhí)行的蟋软,但是有些場(chǎng)景使用異步的方式更為合理侦铜,比如大視頻轉(zhuǎn)碼服務(wù),它很難在很短時(shí)間內(nèi)完成钟鸵。同時(shí)钉稍,為了最大化微服務(wù)之間的解耦,應(yīng)盡量減少和簡(jiǎn)化微服務(wù)之間的通信棺耍。為此贡未,我們引入消息隊(duì)列作為異步通信的通道。
在微服務(wù)的后端蒙袍,如果每個(gè)微服務(wù)都按照三層結(jié)構(gòu)來(lái)部署俊卤,除了服務(wù)本身之外,還包括緩存層和持久化的數(shù)據(jù)庫(kù)層害幅。
這樣就構(gòu)成了一個(gè)典型的微服務(wù)應(yīng)用架構(gòu)消恍,各項(xiàng)服務(wù)可以自由伸縮,相互之間依賴最小化以现,通過(guò)共享隊(duì)列的方式來(lái)進(jìn)行數(shù)據(jù)共享和信息同步狠怨。當(dāng)然,這樣一個(gè)架構(gòu)要通過(guò)猴子軍團(tuán)的測(cè)試邑遏,首先得保證每個(gè)組件都是高可用甚至是跨機(jī)房部署的佣赖,比如 API Gateway、消息隊(duì)列以及每個(gè)服務(wù)依賴的 Cache 和 DB 都隨時(shí)可能掛掉记盒。
七牛的微服務(wù)架構(gòu)實(shí)踐
圖 10. 七牛微服務(wù)設(shè)計(jì)實(shí)踐
圖 10 展示的是七牛數(shù)據(jù)處理平臺(tái)的微服務(wù)架構(gòu)示意圖憎蛤。七牛的數(shù)據(jù)處理平臺(tái)每天處理接近百億的數(shù)據(jù)處理請(qǐng)求,這些請(qǐng)求包括圖片縮放裁剪等可以實(shí)時(shí)完成的同步請(qǐng)求纪吮,也包括音視頻轉(zhuǎn)碼等無(wú)法實(shí)時(shí)完成的異步請(qǐng)求俩檬。所有這些請(qǐng)求通過(guò)統(tǒng)一的網(wǎng)關(guān)進(jìn)入負(fù)載均衡器,再由負(fù)載均衡器分發(fā)給后端的處理實(shí)例碾盟。后端的處理實(shí)例中棚辽,每個(gè)實(shí)例只部署一種類型的服務(wù),同時(shí)維持一個(gè) Agent 可以從存儲(chǔ)中讀取數(shù)據(jù)巷疼,以及一個(gè) Cache 用于維持狀態(tài)晚胡。由于業(yè)務(wù)相對(duì)簡(jiǎn)單,Cache 可以直接基于內(nèi)存嚼沿,并且沒(méi)有持久化的要求估盘。所有持久化的工作都由客戶端主動(dòng)發(fā)起,由后端 Agent 完成后對(duì)存儲(chǔ)進(jìn)行讀寫骡尽。
問(wèn)答環(huán)節(jié)
:關(guān)于微服務(wù)的注冊(cè)和發(fā)現(xiàn)遣妥,目前有哪些成熟的產(chǎn)品?
:比較成熟的用于協(xié)同的是 Zookeeper攀细,在開源容器產(chǎn)品里面用的比較多的是 etcd箫踩。
:微服務(wù)健康狀況,運(yùn)行情況監(jiān)控是如何做的谭贪?
:如果是使用容器化的部署方式境钟,監(jiān)控方面目前很多都是基于 Google 的 cAdvisor 來(lái)做的。
:請(qǐng)問(wèn)微服務(wù)是否部署了多個(gè)實(shí)例俭识,同服務(wù)的不同實(shí)例間是否有分布式鎖來(lái)保護(hù)慨削?
:如果需要保證服務(wù)之間的原子性,可以使用分布式鎖套媚,但應(yīng)該和微服務(wù)的初衷有點(diǎn)沖突缚态。建議盡量改成異步通信的方式,借助 message queue 等來(lái)通信堤瘤。
:微服務(wù)的部署玫芦,老師比較推薦哪種方式?藍(lán)綠本辐、金絲雀桥帆,或者是其他?
:我們的業(yè)務(wù)是灰度慎皱。
:針對(duì)服務(wù)總線环葵、API GateWay、OpenAPI之間的區(qū)別是什么呢宝冕?您剛才所講的服務(wù)發(fā)現(xiàn)屬于這里面誰(shuí)的范疇张遭?
:服務(wù)總線是針對(duì)數(shù)據(jù)傳輸講的。API Gateway 的針對(duì)請(qǐng)求處理和分發(fā)的地梨。OpenAPI 功能上應(yīng)該差不多菊卷,主要是面向第三方平臺(tái)的開發(fā)者。API Gateway 除了終端(Web/iOS/Android)提供 API 功能之外宝剖,還提供了統(tǒng)一的入口洁闰、微服務(wù)接口聚合以及授權(quán)認(rèn)證、后端服務(wù)負(fù)載均衡等功能万细。
:怎么解決動(dòng)態(tài)拓展Docker扑眉,網(wǎng)絡(luò)問(wèn)題?
:要看具體是啥問(wèn)題…… 網(wǎng)絡(luò)方面 Docker 官方有提供方案,k8s 也有腰素,一般私有部署可以直接使用開源的版本聘裁。
:如果應(yīng)用已經(jīng)基于Spark這樣的分布式框架構(gòu)建了,再想做微服務(wù)拆分有什么比較好的方案嗎弓千?
:我理解你跑在 Spark 上面的計(jì)算任務(wù)更依賴的是 Spark衡便,而不是微服務(wù)的優(yōu)勢(shì)。因此如果你要考慮微服務(wù)話或者為了充分利用容器云平臺(tái)的能力洋访,可以考慮先把你依賴的 Spark 容器化镣陕,后面再考慮計(jì)算任務(wù)容器化的事情。
:以什么標(biāo)準(zhǔn)來(lái)進(jìn)行微服務(wù)顆粒度劃分姻政?
:大家都說(shuō)以業(yè)務(wù)的最小單元來(lái)拆分服務(wù)呆抑,但對(duì)業(yè)務(wù)的最小單元卻沒(méi)有統(tǒng)一的標(biāo)準(zhǔn),也不可能有統(tǒng)一的標(biāo)準(zhǔn)汁展,比如我們做存儲(chǔ)業(yè)務(wù)的和你電商業(yè)務(wù)的標(biāo)準(zhǔn)就沒(méi)法統(tǒng)一起來(lái)理肺。我個(gè)人的看法是,就像康威定律里面說(shuō)的善镰,服務(wù)的復(fù)雜性決定了服務(wù)的大小和拆分的合理性妹萨,除了「以業(yè)務(wù)的最小單元來(lái)拆分」之外,維護(hù)某個(gè)微服務(wù)的團(tuán)隊(duì)不應(yīng)該太大炫欺。還有乎完,拆分之后本來(lái)應(yīng)該是盡量解耦的,所以可以看拆分之后是否帶來(lái)更復(fù)雜的異步通信品洛。
在這里給大家提供一個(gè)交流树姨,討論的平臺(tái),JAVA微服務(wù)討論群:671017482 桥状,