微服務(wù)框架
目前主流的應(yīng)用分為兩種:
單體式應(yīng)用和微服務(wù)應(yīng)用,下面將具體對(duì)它們盡心能夠描述馏段。
開(kāi)發(fā)單體式應(yīng)用
假設(shè)你正準(zhǔn)備開(kāi)發(fā)一款與Uber和Hailo競(jìng)爭(zhēng)的出租車調(diào)度軟件毅弧,經(jīng)過(guò)初步會(huì)議和需求分析够坐,你可能會(huì)手動(dòng)或者使用基于Rails崖面、Spring Boot巫员、Play或者M(jìn)aven的生成器開(kāi)始這個(gè)新項(xiàng)目,它的六邊形架構(gòu)是模塊化的 赶掖,架構(gòu)圖如下:

應(yīng)用核心是業(yè)務(wù)邏輯奢赂,由定義服務(wù)膳灶、域?qū)ο蠛褪录哪K完成。圍繞著核心的是與外界打交道的適配器序厉。適配器包括數(shù)據(jù)庫(kù)訪問(wèn)組件弛房、生產(chǎn)和處理消息的消息組件霉晕,以及提供API或者UI訪問(wèn)支持的web模塊等牺堰。
盡管也是模塊化邏輯,但是最終它還是會(huì)打包并部署為單體式應(yīng)用恨搓。具體的格式依賴于應(yīng)用語(yǔ)言和框架斧抱。例如渐溶,許多Java應(yīng)用會(huì)被打包為WAR格式茎辐,部署在Tomcat或者Jetty上拖陆,而另外一些Java應(yīng)用會(huì)被打包成自包含的JAR格式,同樣乎串,Rails和Node.js會(huì)被打包成層級(jí)目錄速警。
這種應(yīng)用開(kāi)發(fā)風(fēng)格很常見(jiàn)闷旧,因?yàn)镮DE和其它工具都擅長(zhǎng)開(kāi)發(fā)一個(gè)簡(jiǎn)單應(yīng)用鸠匀,這類應(yīng)用也很易于調(diào)試逾柿,只需要簡(jiǎn)單運(yùn)行此應(yīng)用,用Selenium鏈接UI就可以完成端到端測(cè)試父腕。單體式應(yīng)用也易于部署璧亮,只需要把打包應(yīng)用拷貝到服務(wù)器端斥难,通過(guò)在負(fù)載均衡器后端運(yùn)行多個(gè)拷貝就可以輕松實(shí)現(xiàn)應(yīng)用擴(kuò)展哑诊。在早期這類應(yīng)用運(yùn)行的很好镀裤。
單體式應(yīng)用的不足
不幸的是,這種簡(jiǎn)單方法卻有很大的局限性骆莹。一個(gè)簡(jiǎn)單的應(yīng)用會(huì)隨著時(shí)間推移逐漸變大幕垦。在每次的sprint中毁习,開(kāi)發(fā)團(tuán)隊(duì)都會(huì)面對(duì)新“故事”纺且,然后開(kāi)發(fā)許多新代碼载碌。幾年后嫁艇,這個(gè)小而簡(jiǎn)單的應(yīng)用會(huì)變成了一個(gè)巨大的怪物。這兒有一個(gè)例子论皆,我最近和一個(gè)開(kāi)發(fā)者討論点晴,他正在寫一個(gè)工具粒督,用來(lái)分析他們一個(gè)擁有數(shù)百萬(wàn)行代碼的應(yīng)用中JAR文件之間的依賴關(guān)系。我很確信這個(gè)代碼正是很多開(kāi)發(fā)者經(jīng)過(guò)多年努力開(kāi)發(fā)出來(lái)的一個(gè)怪物族跛。
一旦你的應(yīng)用變成一個(gè)又大又復(fù)雜的怪物礁哄,那開(kāi)發(fā)團(tuán)隊(duì)肯定很痛苦姐仅。敏捷開(kāi)發(fā)和部署舉步維艱刻盐,其中最主要問(wèn)題就是這個(gè)應(yīng)用太復(fù)雜敦锌,以至于任何單個(gè)開(kāi)發(fā)者都不可能搞懂它乙墙。因此听想,修正bug和正確的添加新功能變的非常困難,并且很耗時(shí)衔峰。另外垫卤,團(tuán)隊(duì)士氣也會(huì)走下坡路出牧。如果代碼難于理解舔痕,就不可能被正確的修改。最終會(huì)走向巨大的耿眉、不可理解的泥潭。
單體式應(yīng)用也會(huì)降低開(kāi)發(fā)速度组底。應(yīng)用越大债鸡,啟動(dòng)時(shí)間會(huì)越長(zhǎng)厌均。比如,最近的一個(gè)調(diào)查表明棺弊,有時(shí)候應(yīng)用的啟動(dòng)時(shí)間居然超過(guò)了12分鐘晶密。我還聽(tīng)說(shuō)某些應(yīng)用需要40分鐘啟動(dòng)時(shí)間。如果開(kāi)發(fā)者需要經(jīng)常重啟應(yīng)用模她,那么大部分時(shí)間就要在等待中渡過(guò)稻艰,生產(chǎn)效率受到極大影響。
另外侈净,復(fù)雜而巨大的單體式應(yīng)用也不利于持續(xù)性開(kāi)發(fā)尊勿。今天,SaaS應(yīng)用常態(tài)就是每天會(huì)改變很多次畜侦,而這對(duì)于單體式應(yīng)用模式非常困難。另外旋膳,這種變化帶來(lái)的影響并沒(méi)有很好的被理解澎语,所以不得不做很多手工測(cè)試。那么接下來(lái)溺忧,持續(xù)部署也會(huì)很艱難咏连。
單體式應(yīng)用在不同模塊發(fā)生資源沖突時(shí),擴(kuò)展將會(huì)非常困難鲁森。比如祟滴,一個(gè)模塊完成一個(gè)CPU敏感邏輯,應(yīng)該部署在AWS EC2 Compute Optimized instances歌溉,而另外一個(gè)內(nèi)存數(shù)據(jù)庫(kù)模塊更合適于EC2 Memory-optimized instances垄懂。然而骑晶,由于這些模塊部署在一起,因此不得不在硬件選擇上做一個(gè)妥協(xié)草慧。
單體式應(yīng)用另外一個(gè)問(wèn)題是可靠性桶蛔。因?yàn)樗心K都運(yùn)行在一個(gè)進(jìn)程中,任何一個(gè)模塊中的一個(gè)bug漫谷,比如內(nèi)存泄露仔雷,將會(huì)有可能弄垮整個(gè)進(jìn)程。除此之外舔示,因?yàn)樗袘?yīng)用實(shí)例都是唯一的碟婆,這個(gè)bug將會(huì)影響到整個(gè)應(yīng)用的可靠性。
最后惕稻,單體式應(yīng)用使得采用新架構(gòu)和語(yǔ)言非常困難竖共。比如,設(shè)想你有兩百萬(wàn)行采用XYZ框架寫的代碼俺祠。如果想改成ABC框架公给,無(wú)論是時(shí)間還是成本都是非常昂貴的,即使ABC框架更好蜘渣。因此淌铐,這是一個(gè)無(wú)法逾越的鴻溝。你不得不在最初選擇面前低頭蔫缸。
總結(jié)一下:一開(kāi)始你有一個(gè)很成功的關(guān)鍵業(yè)務(wù)應(yīng)用匣沼,后來(lái)就變成了一個(gè)巨大的,無(wú)法理解的怪物捂龄。因?yàn)椴捎眠^(guò)時(shí)的释涛,效率低的技術(shù),使得雇傭有潛力的開(kāi)發(fā)者很困難倦沧。應(yīng)用無(wú)法擴(kuò)展唇撬,可靠性很低,最終展融,敏捷性開(kāi)發(fā)和部署變的無(wú)法完成晴音。
微處理架構(gòu)——處理復(fù)雜事物
許多公司密末,比如Amazon陨闹、eBay和NetFlix引矩,通過(guò)采用微處理結(jié)構(gòu)模式解決了上述問(wèn)題。其思路不是開(kāi)發(fā)一個(gè)巨大的單體式的應(yīng)用燕偶,而是將應(yīng)用分解為小的喝噪、互相連接的微服務(wù)。
一個(gè)微服務(wù)一般完成某個(gè)特定的功能指么,比如下單管理酝惧、客戶管理等等榴鼎。每一個(gè)微服務(wù)都是微型六角形應(yīng)用,都有自己的業(yè)務(wù)邏輯和適配器晚唇。一些微服務(wù)還會(huì)發(fā)布API給其它微服務(wù)和應(yīng)用客戶端使用巫财。其它微服務(wù)完成一個(gè)Web UI,運(yùn)行時(shí)哩陕,每一個(gè)實(shí)例可能是一個(gè)云VM或者是Docker容器平项。
每一個(gè)應(yīng)用功能區(qū)都使用微服務(wù)完成,另外悍及,Web應(yīng)用會(huì)被拆分成一系列簡(jiǎn)單的Web應(yīng)用(比如一個(gè)對(duì)乘客葵礼,一個(gè)對(duì)出租車駕駛員)。這樣的拆分對(duì)于不同用戶并鸵、設(shè)備和特殊應(yīng)用場(chǎng)景部署都更容易。
每一個(gè)后臺(tái)服務(wù)開(kāi)放一個(gè)REST API扔涧,許多服務(wù)本身也采用了其它服務(wù)提供的API园担。比如,駕駛員管理使用了告知駕駛員一個(gè)潛在需求的通知服務(wù)枯夜。UI服務(wù)激活其它服務(wù)來(lái)更新Web頁(yè)面弯汰。所有服務(wù)都是采用異步的,基于消息的通訊湖雹。微服務(wù)內(nèi)部機(jī)制將會(huì)在后續(xù)系列中討論咏闪。
這種微服務(wù)架構(gòu)模式深刻影響了應(yīng)用和數(shù)據(jù)庫(kù)之間的關(guān)系,不像傳統(tǒng)多個(gè)服務(wù)共享一個(gè)數(shù)據(jù)庫(kù)摔吏,微服務(wù)架構(gòu)每個(gè)服務(wù)都有自己的數(shù)據(jù)庫(kù)鸽嫂。另外,這種思路也影響到了企業(yè)級(jí)數(shù)據(jù)模式征讲。同時(shí)据某,這種模式意味著多份數(shù)據(jù),但是诗箍,如果你想獲得微服務(wù)帶來(lái)的好處癣籽,每個(gè)服務(wù)獨(dú)有一個(gè)數(shù)據(jù)庫(kù)是必須的,因?yàn)檫@種架構(gòu)需要這種松耦合滤祖。下面的圖演示示例應(yīng)用數(shù)據(jù)庫(kù)架構(gòu)筷狼。
表面上看來(lái),微服務(wù)架構(gòu)模式有點(diǎn)像SOA匠童,他們都由多個(gè)服務(wù)構(gòu)成埂材。但是,可以從另外一個(gè)角度看此問(wèn)題汤求,微服務(wù)架構(gòu)模式是一個(gè)不包含Web服務(wù)(WS-)和ESB服務(wù)的SOA楞遏。微服務(wù)應(yīng)用樂(lè)于采用簡(jiǎn)單輕量級(jí)協(xié)議茬暇,比如REST,而不是WS-寡喝,在微服務(wù)內(nèi)部避免使用ESB以及ESB類似功能糙俗。微服務(wù)架構(gòu)模式也拒絕使用canonical schema等SOA概念。
表面上看來(lái)预鬓,微服務(wù)架構(gòu)模式有點(diǎn)像SOA巧骚,他們都由多個(gè)服務(wù)構(gòu)成。但是格二,可以從另外一個(gè)角度看此問(wèn)題劈彪,微服務(wù)架構(gòu)模式是一個(gè)不包含Web服務(wù)(WS-)和ESB服務(wù)的SOA。微服務(wù)應(yīng)用樂(lè)于采用簡(jiǎn)單輕量級(jí)協(xié)議顶猜,比如REST沧奴,而不是WS-,在微服務(wù)內(nèi)部避免使用ESB以及ESB類似功能长窄。微服務(wù)架構(gòu)模式也拒絕使用canonical schema等SOA概念滔吠。
esb 總線:企業(yè)服務(wù)總線。上面標(biāo)黑的這條線說(shuō)的是 在微服務(wù)框架中挠日,服務(wù)與服務(wù)之間不是通過(guò)總線疮绷,而是通過(guò)rest ful來(lái)通信。
微服務(wù)架構(gòu)的好處
微服務(wù)架構(gòu)模式有很多好處嚣潜。首先冬骚,通過(guò)分解巨大單體式應(yīng)用為多個(gè)服務(wù)方法解決了復(fù)雜性問(wèn)題。在功能不變的情況下懂算,應(yīng)用被分解為多個(gè)可管理的分支或服務(wù)只冻。每個(gè)服務(wù)都有一個(gè)用RPC-或者消息驅(qū)動(dòng)API定義清楚的邊界。微服務(wù)架構(gòu)模式給采用單體式編碼方式很難實(shí)現(xiàn)的功能提供了模塊化的解決方案计技,由此属愤,單個(gè)服務(wù)很容易開(kāi)發(fā)、理解和維護(hù)酸役。
第二住诸,這種架構(gòu)使得每個(gè)服務(wù)都可以有專門開(kāi)發(fā)團(tuán)隊(duì)來(lái)開(kāi)發(fā)。開(kāi)發(fā)者可以自由選擇開(kāi)發(fā)技術(shù)涣澡,提供API服務(wù)贱呐。當(dāng)然,許多公司試圖避免混亂入桂,只提供某些技術(shù)選擇奄薇。然后,這種自由意味著開(kāi)發(fā)者不需要被迫使用某項(xiàng)目開(kāi)始時(shí)采用的過(guò)時(shí)技術(shù)抗愁,他們可以選擇現(xiàn)在的技術(shù)馁蒂。甚至于呵晚,因?yàn)榉?wù)都是相對(duì)簡(jiǎn)單,即使用現(xiàn)在技術(shù)重寫以前代碼也不是很困難的事情沫屡。
第三饵隙,微服務(wù)架構(gòu)模式是每個(gè)微服務(wù)獨(dú)立的部署。開(kāi)發(fā)者不再需要協(xié)調(diào)其它服務(wù)部署對(duì)本服務(wù)的影響沮脖。這種改變可以加快部署速度金矛。UI團(tuán)隊(duì)可以采用AB測(cè)試,快速的部署變化勺届。微服務(wù)架構(gòu)模式使得持續(xù)化部署成為可能驶俊。
最后,微服務(wù)架構(gòu)模式使得每個(gè)服務(wù)獨(dú)立擴(kuò)展免姿。你可以根據(jù)每個(gè)服務(wù)的規(guī)模來(lái)部署滿足需求的規(guī)模饼酿。甚至于,你可以使用更適合于服務(wù)資源需求的硬件胚膊。比如故俐,你可以在EC2 Compute Optimized instances上部署CPU敏感的服務(wù),而在EC2 memory-optimized instances上部署內(nèi)存數(shù)據(jù)庫(kù)澜掩。
springboot 微服務(wù)框架
在微服務(wù)架構(gòu)設(shè)計(jì)中,需要抽象出一些核心問(wèn)題來(lái)統(tǒng)一解決杖挣,這包括九條核心問(wèn)題肩榕。第一點(diǎn)是服務(wù)的注冊(cè)中心。第二是統(tǒng)一的接入服務(wù)接口惩妇。第三是服務(wù)的容錯(cuò)和負(fù)載均衡保證服務(wù)的高可用株汉。第四是服務(wù)的限流和降級(jí)保證核心服務(wù)的穩(wěn)定性。第五是服務(wù)系統(tǒng)的安全及全鏈路日志跟蹤歌殃。第六是支持多種通訊方式乔妈。第七是監(jiān)控和日志管理,第八是下面詳細(xì)描述各個(gè)核心問(wèn)題的內(nèi)容:
- 服務(wù)注冊(cè)中心氓皱,主要實(shí)現(xiàn)服務(wù)注冊(cè)與服務(wù)發(fā)現(xiàn)路召。微服務(wù)架構(gòu)由一組獨(dú)立的微服務(wù)組成,這些微服務(wù)之間存在一種發(fā)現(xiàn)機(jī)制波材,目前我們通過(guò)服務(wù)注冊(cè)與發(fā)現(xiàn)來(lái)讓微服務(wù)可以感知彼此股淡,微服務(wù)框架在啟動(dòng)的時(shí)候,將自己的信息注冊(cè)到注冊(cè)中心廷区,同時(shí)從注冊(cè)中心訂閱自己需要引用的服務(wù)唯灵。
- 統(tǒng)一的接入服務(wù)接口。由于把UI和后端服務(wù)分離隙轻。API Gateway是一個(gè)網(wǎng)關(guān)服務(wù)器埠帕,也可以說(shuō)是進(jìn)入系統(tǒng)的唯一節(jié)點(diǎn)垢揩。這跟面向?qū)ο笤O(shè)計(jì)模式中的Facade模式很像。API Gateway封裝內(nèi)部系統(tǒng)的架構(gòu)敛瓷,并且提供API給各個(gè)客戶端叁巨。API Gateway還可能有其他功能,如授權(quán)琐驴、監(jiān)控俘种、負(fù)載均衡、緩存绝淡、請(qǐng)求分片和管理宙刘、靜態(tài)響應(yīng)處理等。
- 服務(wù)的容錯(cuò)和負(fù)載均衡保證服務(wù)的高可用牢酵。為了保證微服務(wù)的高可用悬包,每個(gè)微服務(wù)一般會(huì)有多個(gè)實(shí)例服務(wù)提供服務(wù),此時(shí)需要客戶端在進(jìn)行服務(wù)的負(fù)載均衡馍乙;目前微服務(wù)框架中布近,現(xiàn)支持常見(jiàn)的負(fù)載均衡策略,如隨機(jī)丝格,輪訓(xùn)撑瞧,hash,權(quán)重显蝌,連接數(shù)预伺,缺省是根據(jù)連接數(shù),連接數(shù)越少曼尊,優(yōu)先級(jí)越高酬诀。
- 服務(wù)的容錯(cuò)可以保證核心服務(wù)的連續(xù)性。在調(diào)用服務(wù)集群的時(shí)候骆撇,如果一個(gè)微服務(wù)調(diào)用異常瞒御,如超時(shí),或者發(fā)生連接異常神郊,網(wǎng)絡(luò)異常肴裙,則根據(jù)容錯(cuò)策略進(jìn)行服務(wù)容錯(cuò),如果連續(xù)失敗多次涌乳,則需要直接熔斷践宴,不再發(fā)起調(diào)用,這樣可以防止一個(gè)服務(wù)異常拖垮所有依賴它的服務(wù)爷怀。
- 服務(wù)的限流和降級(jí)等措施可以保證核心服務(wù)的穩(wěn)定性阻肩。隨著訪問(wèn)量的增加,微服務(wù)架構(gòu)設(shè)置了一個(gè)系統(tǒng)能夠處理的極限閥值,超過(guò)這個(gè)閥值的請(qǐng)求則直接拒絕烤惊。同時(shí)乔煞,為了保證某些核心服務(wù)可用,需要對(duì)某些非核心業(yè)務(wù)進(jìn)行降級(jí)柒室。這些操作可以自動(dòng)降級(jí)也可以人工降級(jí)渡贾。
- 安全控制和權(quán)限驗(yàn)證:保障系統(tǒng)的安全。微服務(wù)架構(gòu)推薦采用token機(jī)制保證微服務(wù)的安全雄右。用戶在登錄的時(shí)候會(huì)頒發(fā)給用戶一個(gè)token空骚,用戶每次訪問(wèn)平臺(tái)的時(shí)候,需要傳遞此token擂仍,后臺(tái)校驗(yàn)此token的合法性囤屹,如果合法則可以訪問(wèn),如果沒(méi)有token或者token不合法逢渔,則禁止訪問(wèn)肋坚。
- 支持多種通訊方式。在微服務(wù)架構(gòu)下肃廓,一般采用輕量級(jí)的方式進(jìn)行通訊智厌,每個(gè)微服務(wù)都統(tǒng)一對(duì)外暴露RESTFul服務(wù),無(wú)論是前端調(diào)用后端服務(wù)盲赊,還是后端服務(wù)間的調(diào)用铣鹏,都統(tǒng)一走RESTFul,這樣統(tǒng)一了協(xié)議棧哀蘑。
- 日志和監(jiān)控管理诚卸。在微服務(wù)框架中,所有的系統(tǒng)調(diào)用邊界递礼、請(qǐng)求接入接出邊界惨险,都存在統(tǒng)一的日志埋點(diǎn)羹幸,這些日志埋點(diǎn)和監(jiān)控系統(tǒng)對(duì)接脊髓,可以方便的查看系統(tǒng)的運(yùn)行各項(xiàng)指標(biāo),同時(shí)也可以根據(jù)日志跟蹤到一個(gè)服務(wù)從前到后的整個(gè)調(diào)用鏈路栅受。
- 統(tǒng)一配置管理将硝。統(tǒng)一的配置服務(wù)器為各應(yīng)用的所有環(huán)境提供了一個(gè)中心化的外部配置。這樣可以簡(jiǎn)化很多開(kāi)發(fā)過(guò)程中的繁瑣工作屏镊。
10.CI/CD自動(dòng)化依疼。快速完成源碼構(gòu)建而芥、鏡像打包律罢、應(yīng)用部署,實(shí)現(xiàn)微服務(wù)的高效運(yùn)營(yíng)。
服務(wù)注冊(cè)中心 即 服務(wù)發(fā)現(xiàn)误辑〔滋ぃ可以使用的工具有etcd、Spring Cloud Consul等巾钉。
額外的補(bǔ)充
zookeeper 使用的是 fast paxos共識(shí)算法翘狱。
etcd 使用的是raft共識(shí)算法。