支撐日均百萬訂單的微服務(wù)架構(gòu)應(yīng)該這么搞!
最近幾年微服務(wù)很火,大家都在建設(shè)微服務(wù),如果不懂點(diǎn)微服務(wù)相關(guān)的技術(shù),都不好意思跟同行打招呼了。
圖片來自 Pexels
我也見過身邊很多人在微服務(wù)踩過很多坑,我從 2016 年開始接觸微服務(wù),有多家大型企業(yè)的微服務(wù)分布式系統(tǒng)的架構(gòu)經(jīng)驗(yàn),不過微服務(wù)和涉及的分布式計(jì)算非常的復(fù)雜,絕非是一篇文章就可以講清楚的。
本文只是從最簡單的概念的基本使用帶你入門,如果后續(xù)還有興趣的話,可以查閱相關(guān)的文獻(xiàn)和技術(shù)書籍去深入學(xué)習(xí)。
本文的微服務(wù)分享以下三部分,總體大綱如下:
- 微服務(wù)的概念和原則(理論)
- Spring Cloud 如何低成本的實(shí)現(xiàn)微服務(wù)(實(shí)現(xiàn))
- Spring Cloud 大型項(xiàng)目的架構(gòu)方案(真實(shí)案例)
微服務(wù)的概念和原則
什么是微服務(wù)?
簡單舉例:看軍事新聞的同學(xué)應(yīng)該都知道,一艘航空母艦作戰(zhàn)能力雖然很強(qiáng),但是弱點(diǎn)太明顯,就是防御能力太差,單艘的航空母艦很少單獨(dú)行動(dòng),通常航空母艦戰(zhàn)斗群才是主要軍事力量。
你可以把單艘航母理解為的單體應(yīng)用(防御差,機(jī)動(dòng)性不好),把航母戰(zhàn)斗群(調(diào)度復(fù)雜,維護(hù)費(fèi)用高)理解為微服務(wù)。
簡單講特征就是:
- 單體應(yīng)用:簡單,脆弱(某個(gè)模塊出問題,整個(gè)系統(tǒng)不可用),戰(zhàn)斗力弱,維護(hù)成本低。
- 微服務(wù)架構(gòu):復(fù)雜,健壯(某個(gè)模塊出問題,不會(huì)影響系統(tǒng)整體的可用性),戰(zhàn)斗力強(qiáng),維護(hù)成本高。
單體作戰(zhàn)的應(yīng)用(圖)
微服務(wù)戰(zhàn)斗群(圖)
大部分的開發(fā)者經(jīng)歷和開發(fā)過單體應(yīng)用,無論是傳統(tǒng)的 SSM,還是現(xiàn)在的 Spring Boot/Rails,它們都是單體應(yīng)用。
那么長期陪伴我們的單體應(yīng)用有什么弊端?我們是面臨了什么問題,導(dǎo)致我們要拋棄單體應(yīng)用轉(zhuǎn)向微服務(wù)架構(gòu)?
個(gè)人總結(jié)主要問題如下:
- 部署成本高(無論是修改 1 行代碼,還是 10 行代碼,都要全量部署替換)。
- 改動(dòng)影響大,風(fēng)險(xiǎn)高,測試成本高(不論代碼改動(dòng)多小,成本都相同)。
- 因?yàn)槌杀靖撸L(fēng)險(xiǎn)高,所以導(dǎo)致部署頻率低(無法滿足快速交付客戶需求)。
當(dāng)然還有例如無法滿足快速擴(kuò)容,彈性伸縮,無法適應(yīng)云環(huán)境特性等問題,但我們不一一詳談了,以上的問題,都是微服務(wù)架構(gòu)要解決的問題,至于具體是怎么解決的,我們先放到后面再聊。
歷代應(yīng)用程序的架構(gòu)變遷(圖)
解決什么問題,又引入了什么問題?
我們先看看微服務(wù)能帶給我們什么?微服務(wù)架構(gòu)的特點(diǎn):
- 針對特定服務(wù)發(fā)布,影響小,風(fēng)險(xiǎn)小,成本低
- 頻繁發(fā)布版本,快速交付需求
- 低成本擴(kuò)容,彈性伸縮,適應(yīng)云環(huán)境
我們知道一個(gè)樸素的理念,沒有任何事物是完美的,任何東西都有兩面性,有得必有失。
那么在選擇微服務(wù)在解決了快速響應(yīng)和彈性伸縮的問題同時(shí),它又給我們帶來了什么問題?
個(gè)人總結(jié)如下:
- 分布式系統(tǒng)的復(fù)雜性
- 部署,測試和監(jiān)控的成本問題
- 分布式事務(wù)和 CAP 的相關(guān)問題
系統(tǒng)應(yīng)用由原來的單體變成幾十到幾百個(gè)不同的工程,會(huì)所產(chǎn)生例如包括服務(wù)間的依賴,服務(wù)如何拆封,內(nèi)部接口規(guī)范,數(shù)據(jù)傳遞等等問題。
尤其是服務(wù)拆分,需要團(tuán)隊(duì)熟悉業(yè)務(wù)流程,懂得取舍,要保證拆分的粒度服務(wù)既符合“高內(nèi)聚,低耦合”的基本原則,還要兼顧業(yè)務(wù)的發(fā)展以及公司的愿景,要還要說服團(tuán)隊(duì)成員為之努力,并且積極投入,在多方中間取得平衡。
對于分布式系統(tǒng),部署,測試和監(jiān)控都需要大量的中間件來支撐,而且中間件本身也要維護(hù)。
原先單體應(yīng)用很簡單的事務(wù)問題 ,轉(zhuǎn)到分布式環(huán)境就變得很復(fù)雜,分布式事務(wù)是采用簡單的重試+補(bǔ)償機(jī)制,還是采用二階段提交協(xié)議等強(qiáng)一致性方法來解決,就要取決對業(yè)務(wù)場景的熟悉加上反復(fù)的權(quán)衡了。
相同問題還包括對 CAP 模型的權(quán)衡,總之微服務(wù)對團(tuán)隊(duì)整體的技術(shù)棧水平整體要求更高。
微服務(wù)有哪些應(yīng)該遵循哪些原則?
古人云:兵馬未動(dòng),糧草先行。建設(shè)微服務(wù)是需要建立長遠(yuǎn)規(guī)劃,不是像寫 CMS 那樣建好數(shù)據(jù)庫表,然后就開始干活,這樣十有八九是會(huì)失敗的。
我們要進(jìn)行微服務(wù)改造前,架構(gòu)師要提前做好規(guī)劃,我們把這里分為三步,前期階段,設(shè)計(jì)階段,技術(shù)階段。
前期階段,大致要做好如下事情:
- 和多方充分溝通,確保能符合客戶和組織的需求,并且得到認(rèn)同。
- 和團(tuán)隊(duì)溝通,讓隊(duì)友(開發(fā)/測試/運(yùn)維)理解,并且積極投入。
- 和業(yè)務(wù)部門溝通,指定版本計(jì)劃和上線時(shí)間。
設(shè)計(jì)階段,參考 Sam Newman 的著作《微服務(wù)設(shè)計(jì)》,單微服務(wù)必須要滿足以下的條件,才符合微服務(wù)的基本要求:
- 標(biāo)準(zhǔn)的 REST 風(fēng)格接口(基于 HTTP 和 JSON 格式)。
- 獨(dú)立部署,避免共享數(shù)據(jù)庫(避免因?yàn)閿?shù)據(jù)庫而影響整個(gè)分布式系統(tǒng))。
- 業(yè)務(wù)上的高內(nèi)聚,減少依賴(從設(shè)計(jì)上要避免服務(wù)過大或者太小)。
龐大的分布式系統(tǒng),需要強(qiáng)大基礎(chǔ)設(shè)施來支撐,微服務(wù)涉及哪些基礎(chǔ)設(shè)施?
- CI/CD 和自動(dòng)化(分布式系統(tǒng)幾乎不可能通過人工手動(dòng)發(fā)布。)
- 虛擬化技術(shù)(要保證微服務(wù)運(yùn)行環(huán)境隔離,目前行業(yè)主流的是使用 Docker 容器)。
- 日志聚合,全鏈路監(jiān)控(高度可觀察和分析診斷問題)。
說了那么多,那什么樣的情況下,你的團(tuán)隊(duì)不適合建設(shè)微服務(wù)?(請勿對號(hào)入座)
- 開發(fā)團(tuán)隊(duì)不具備自主性,所在組織對開發(fā)團(tuán)隊(duì)限制非常多(具體請參考 康威定律)。
- 團(tuán)隊(duì)不熟悉業(yè)務(wù),無法識(shí)別出服務(wù)的邊界,進(jìn)行合理的拆分(請參考 DDD 領(lǐng)域驅(qū)動(dòng)設(shè)計(jì))。
微服務(wù)設(shè)計(jì)其實(shí)是很早就有的設(shè)計(jì)思想,因?yàn)殡S著虛擬化技術(shù)的崛起,微服務(wù)可以低成本的實(shí)現(xiàn),所以也開始流行和興起。
微服務(wù)的內(nèi)涵很深,其中就包括,自動(dòng)化,去中心化,獨(dú)立性等等,其中細(xì)節(jié)無法用一篇文章概述清楚,我們在做技術(shù)選型或者方案的時(shí)候,盡可能多去了解技術(shù)的本身和起源再結(jié)合我們業(yè)務(wù)的特點(diǎn),進(jìn)行更好的選擇。
如何低成本的實(shí)現(xiàn)微服務(wù)?
Spring Cloud 為什么是國內(nèi)最流行的微服務(wù)框架,它提供哪些開箱即用的組件 ?
概覽如下:
- Srping Boot 服務(wù)應(yīng)用
- Spring Cloud Config 配置中心
- Spring Cloud Eureka 服務(wù)發(fā)現(xiàn)
- Spring Cloud Hystrix 熔斷保護(hù)
- Spring Cloud Zuul 服務(wù)網(wǎng)關(guān)
- Spring Cloud OAuth 2 服務(wù)保護(hù)
- Spring Cloud Stream 消息驅(qū)動(dòng)
- 分布式全鏈路跟蹤
- 部署微服務(wù)
①Spring Boot 微服務(wù)基石
Spring Boot 是構(gòu)建微服務(wù)的理想框架,主要得益于 Spring Boot 可以打包成為單個(gè)可執(zhí)行JAR文件交付服務(wù),Spring Actuator 公開服務(wù)健康信息都是微服務(wù)的基石,為什么這么說 ?
我們先看看構(gòu)建微服務(wù)的四個(gè)重要原則:
- 服務(wù)應(yīng)該是獨(dú)立和可獨(dú)立部署的
- 應(yīng)該從中央(配置中心)讀取配置
- 對客戶端是透明的
- 傳達(dá)健康信息
微服務(wù)有優(yōu)點(diǎn)和缺點(diǎn),并非所有應(yīng)用都適合用微服務(wù)架構(gòu),架構(gòu)師需要能做到以下要求:
- 分解業(yè)務(wù)問題:描述業(yè)務(wù)問題,注意動(dòng)詞,尋找數(shù)據(jù)內(nèi)聚。
- 建立服務(wù)粒度:講大服務(wù)重構(gòu)到更小的服務(wù),重點(diǎn)關(guān)注服務(wù)如何相互交互,服務(wù)職責(zé)隨時(shí)間改變。
- 定義服務(wù)接口:擁抱 REST 的理念,使用 URI 來傳達(dá)意圖,使用 HTTP 狀態(tài)碼傳達(dá)結(jié)果。
糟糕的微服務(wù)有哪些特征?
- 過于粗粒度:服務(wù)承擔(dān)過多的職責(zé),服務(wù)跨大量表來管理數(shù)據(jù),測試用例太多。
- 過于細(xì)粒度:服務(wù)彼此依賴嚴(yán)重,服務(wù)內(nèi)部沒有邏輯。
何時(shí)不應(yīng)該使用微服務(wù) ?
- 不愿投入(需要高度成熟的運(yùn)維,伸縮,復(fù)雜性問題)。
- 管理/監(jiān)控散亂的服務(wù)器也需要很高的成本。
- 小型應(yīng)用不適合,太昂貴。
- 數(shù)據(jù)事務(wù)(分布式系統(tǒng)處理事務(wù)非常困難)
②Spring Cloud Config 配置服務(wù)
Spring Config 是 Spring 提供的配置中心輕量級(jí)實(shí)現(xiàn),基于 Git 存儲(chǔ),國內(nèi)用戶大多推薦使用 Alibaba 開源的 Nacos(集成配置中心和注冊中心)都是非常不錯(cuò)的配置中心的實(shí)現(xiàn)。
微服務(wù)程序?qū)τ谂渲弥行牡膸c(diǎn)管理原則:
- 應(yīng)用程序的配置和部署的實(shí)際代碼分離(配置中心和應(yīng)用程序分離)。
- 集中(將配置中心集中在少量的存儲(chǔ)庫中)。
- 穩(wěn)定(配置中心要保證高可用)。
Spring Config 這款配置中心提供的核心功能:
- 配置服務(wù)器允許使用環(huán)境特定值。
- 使用 Spring Profile 區(qū)分環(huán)境值。
- 可以使用基于文件或基于 Git 存儲(chǔ)屬性。
- 允許對稱加密和非對稱加密。
③Spring Cloud Eureka 服務(wù)發(fā)現(xiàn)
服務(wù)發(fā)現(xiàn)是微服務(wù)架構(gòu)中非常重要的概念,也稱注冊中心,類似我們生活中的房地產(chǎn)中介的角色,買房賣房都要通過它。
所以它是所有微服務(wù)上線/下線的必經(jīng)之路,也掌握微服務(wù)的生殺大權(quán),注冊中心會(huì)根據(jù) CAP 策略和對微服務(wù)的健康檢查,作出對具體服務(wù)剔除,下線,恢復(fù)上線等操作。
主要還有以下幾個(gè)核心功能:
- 快速對環(huán)境中服務(wù)數(shù)量水平伸縮(功能和 K8s 有些重合,不過也可以設(shè)定具體服務(wù)的運(yùn)行時(shí)數(shù)量)。
- 抽象服務(wù)的物理位置(微服務(wù)通常運(yùn)行在 Docker 容器內(nèi),沒有固定 IP,只能通過注冊中心才能找到它)。
- 提高程序的彈性,自動(dòng)伸縮。
- 信息共享, 健康檢測。
微服務(wù)架構(gòu)里面要實(shí)現(xiàn)注冊中心,需要達(dá)到哪些基本要求?
- 高可用,注冊信息共享(注冊中心集群部署),不可能因?yàn)樽灾行膾炝?,?dǎo)致所有集群不可用。
- 負(fù)載均衡(對服務(wù)間的動(dòng)態(tài)請求負(fù)載均衡),合理在服務(wù)間分配流量。
- 有彈性(客戶端緩存服務(wù)信息)。
- 容錯(cuò),健康檢查(檢測壞掉的服務(wù)自動(dòng)移除,無需人工干預(yù))。
Spring Eureka 提供的服務(wù)發(fā)現(xiàn)實(shí)現(xiàn),具備哪些特點(diǎn) ?
- 服務(wù)發(fā)現(xiàn)抽象服務(wù)的物理位置。
- 無感知添加和移除服務(wù)。
- 為服務(wù)間調(diào)用提供負(fù)載均衡。
- 使用 3 種不同機(jī)制來調(diào)用服務(wù):DiscoveryClient,支持 Ribbon 的 RestTemplate,Netflix 的 FeignClient。
④Spring Cloud Hystrix 熔斷保護(hù)
為什么微服務(wù)進(jìn)行熔斷 ?當(dāng)一個(gè)服務(wù)出現(xiàn)問題:
- 通常都是從小部分開始,到耗盡線程徹底崩潰。
- 服務(wù)間調(diào)用會(huì)長時(shí)間阻塞。
- 服務(wù)未關(guān)閉就會(huì)一直被調(diào)用,導(dǎo)致連鎖效應(yīng)。
- 一個(gè)性能不佳的服務(wù)可以迅速拖垮整個(gè)應(yīng)用。
為什么熔斷很重要 ?
- 每個(gè)節(jié)點(diǎn)(調(diào)用服務(wù)和數(shù)據(jù)庫)實(shí)現(xiàn)斷路器,可以避免服務(wù)崩潰的連鎖效應(yīng)。
- 實(shí)現(xiàn)只有出問題的服務(wù)受影響,其余的服務(wù)功能都是完整的(影響范圍降到最小)。
- 熔斷是服務(wù)器的靈活的基礎(chǔ)。
斷路器提供的關(guān)鍵能力:
- 快速失敗。
- 功能降級(jí)(替代方案)。
- 無縫恢復(fù)(斷路器定期檢查,自動(dòng)恢復(fù)服務(wù))。
Netflix 研發(fā)和出品的 Hystrix 實(shí)現(xiàn)是一款成熟穩(wěn)定的熔斷實(shí)現(xiàn),在 Netflix 在生產(chǎn)實(shí)踐和運(yùn)行多年,非??煽?,后面加入 Spring Cloud 體系,成為 Spring Cloud 微服務(wù)生態(tài)鏈的一員,使用起來也非常的簡單和方便。
Hystrix 支持四種斷路模式:
- 客戶端負(fù)載均衡模式(檢測服務(wù)出錯(cuò),移除服務(wù))。
- 斷路器模式(出現(xiàn)超時(shí)拋出異常強(qiáng)行失敗,超過閾值強(qiáng)行失敗所有調(diào)用)。
- 后備模式(不是拋出異常而是執(zhí)行替代方案,例如排隊(duì),稍后再試等)。
- 艙壁模式(把遠(yuǎn)程調(diào)用的資源分配到獨(dú)立的線程池中,調(diào)用出問題只是線程池飽和并停止請求)。
跳閘會(huì)導(dǎo)致的三種結(jié)果:
- 服務(wù) B 立即知道服務(wù) C 有問題,不必等待,立即失敗。
- 服務(wù) B 執(zhí)行服務(wù) C 的替代代碼來采取行動(dòng)(后備模式)。
- 服務(wù) C 可以在跳閘后,檢查問題,快速恢復(fù)。
熔斷的幾個(gè)處理原則:
- 設(shè)計(jì)分布式應(yīng)用必須考慮彈性。
- 服務(wù)的徹底故障是很容易檢測和處理,只是需要時(shí)間,斷路器給了這個(gè)時(shí)間窗口。
- 一個(gè)服務(wù)性能不佳,可能導(dǎo)致集群崩潰,因?yàn)橄嗷フ{(diào)用會(huì)阻塞線程,耗盡資源。
- Hystrix 支持兩種隔離模型,即 THREAD 和 SEMAPHORE。
⑤Spring Cloud Zuul 網(wǎng)關(guān)
網(wǎng)關(guān)是整個(gè)微服務(wù)分布式集群的入口,對于用戶來說,用戶無需知道你每個(gè)服務(wù)的地址,只需要記住網(wǎng)關(guān)地址就可以了。
這樣理解可能比較抽象,舉一個(gè)生活的例子,微服務(wù)集群是一個(gè)大型公司,公司內(nèi)部有很多個(gè)不同的職能部門(對應(yīng)每個(gè)微服務(wù))。
但是你如果要訪問具體的職能部門,你必須先到前臺(tái)登記,再由前臺(tái)帶你到你想訪問的具體職能部門去辦理實(shí)際的業(yè)務(wù)(智能路由)。
微服務(wù)對于網(wǎng)關(guān)實(shí)現(xiàn)的規(guī)范:
- 一個(gè)獨(dú)立負(fù)責(zé)所有服務(wù)調(diào)用過濾和路由的服務(wù)。
- 服務(wù)和客戶端的中間人,簡化客戶端開發(fā)。
網(wǎng)關(guān)通常要做哪些事情:
- 靜態(tài)路由,從注冊中心獲取每個(gè)微服務(wù)的具體位置。
- 動(dòng)態(tài)路由(根據(jù)參數(shù)特點(diǎn),調(diào)用特定服務(wù),少量用戶體驗(yàn)新功能,通常用于灰度發(fā)布)。
- 驗(yàn)證和授權(quán):驗(yàn)證訪客的身份信息(統(tǒng)一驗(yàn)證,服務(wù)只需要關(guān)注業(yè)務(wù)邏輯)。
- 數(shù)據(jù)收集和日志(收集調(diào)用次數(shù)和響應(yīng)時(shí)間等)。
Zuul 網(wǎng)關(guān)的具體運(yùn)行參考圖:
Spring Cloud Zuul 是初期版本的 API 網(wǎng)關(guān)實(shí)現(xiàn),提供以下功能:
- 結(jié)合 Spring Cloud Eureka 將服務(wù)發(fā)現(xiàn)的注冊地址加入到 Zuul 路由。
- Zuul 可以給所有服務(wù)輕松的添加/API 之類的前綴路由地址。
- 在全局上定制 Zuul 的 Spring Cloud Hystrix 和 Spring Cloud Ribbon (調(diào)度策略)的超時(shí)。
- 實(shí)現(xiàn)動(dòng)態(tài)路由,不同版本進(jìn)行 A/B 測試。
- 檢查參數(shù)合法性等,例如 JWT,時(shí)間戳等等。
⑥Spring Cloud OAuth 2 服務(wù)保護(hù)
Oauth 2 是用于保證請求的合法和正確性,為了讓微服務(wù)本身更加專注于業(yè)務(wù),所以 OAuth 2 類似配置中心被單獨(dú)抽離出來作為基礎(chǔ)組件的統(tǒng)一認(rèn)證中心來使用。
OAuth 2 的作用類似我們生活中的公安局的角色,當(dāng)我們需要去正規(guī)機(jī)構(gòu)辦理業(yè)務(wù)的時(shí)候,我們需要提供有效的身份證(合法的身份認(rèn)證標(biāo)示)。
如果沒有你就需要去公安局(OAuth)申請一張?jiān)谟行趦?nèi)的身份證(Token),然后帶著這張身份證我們才能去購買機(jī)票,酒店等其他社會(huì)服務(wù)(微服務(wù))。
社會(huì)服務(wù)機(jī)構(gòu)在拿到你提供的身份證(Token)后,也會(huì)向公安局(OAuth)聯(lián)網(wǎng)發(fā)送信息,來驗(yàn)證你的身份證的合法性(Token 合法性校驗(yàn)),身份認(rèn)證不通過就會(huì)被拒絕服務(wù),合法的身份才能進(jìn)行業(yè)務(wù)的辦理。
關(guān)于 OAuth 的工作流程,可以結(jié)合下圖來理解:
微服務(wù)對于 OAuth2 規(guī)范的 4 種類型授權(quán):密碼/客戶端憑據(jù)/授權(quán)碼/隱式。
Spring Cloud OAuth 2 為我們提供哪些便利?
- 安全框架,提供令牌生成,驗(yàn)證等邏輯。
- 開箱即用,和其他服務(wù)無縫集成。
- 行業(yè)標(biāo)準(zhǔn),輕松與云服務(wù)商集成。
OAuth 2:/auth/oauth/token 的返回信息:
- access_token(OAuth 2 令牌,每次調(diào)用出示)。
- token_type(令牌類型,常用 bearer token)。
- refresh_token(續(xù)約令牌)。
- expires_in(過期描述,默認(rèn) 12H)。
- scope(令牌有效作用域)。
OAuth 2 支持 JWT (JSON Web Token)的規(guī)范,關(guān)于 JWT 的原理就不特別解釋了。
簡單的 JWT 有以下幾個(gè)特點(diǎn):
- 小巧(Base64編碼)。
- 密碼簽名(防篡改)。
- 自包含(不需要調(diào)用驗(yàn)證服務(wù)確認(rèn)內(nèi)容,通過相同的密鑰進(jìn)行對稱解密)。
- 可擴(kuò)展(可在令牌內(nèi)包含額外的信息)。
OAuth 2 的簡單總結(jié):
- OAuth 2 是一個(gè)令牌驗(yàn)證框架。
- 使用 OAuth 2 需要建立 OAuth 2 驗(yàn)證服務(wù)。
- 調(diào)用受保護(hù)的資源都要通過 OAuth 2 驗(yàn)證。
⑦Spring Cloud Stream 消息驅(qū)動(dòng)
我們和世界的互動(dòng)不是同步的,很多時(shí)候是基于消息異步驅(qū)動(dòng)模型,比如郵件,點(diǎn)餐,訂票等等,想要了解 Spring Cloud Stream,必須先要理解基于事件(MQ)編程的模型,基于消息驅(qū)動(dòng)有利于開發(fā)構(gòu)建高度解耦的系統(tǒng)。
因?yàn)?Spring Cloud Stream 并不是自己實(shí)現(xiàn)了消息中間件,而是對于市場上主流(例如 RabbitMQ,KafKa)的 MQ 產(chǎn)品做了一層封裝和抽象。
Spring Cloud Stream 做的事情并不是什么新鮮的事情,非常類似 ORM 所做的事情,了解 ORM 框架的同學(xué)應(yīng)該都熟悉對于多種數(shù)據(jù)庫(MySQL,Oracle,SQL Server)產(chǎn)品的抽象是何等重要。
面向 ORM 進(jìn)行數(shù)據(jù)庫訪問,可以讓你脫離對于指定數(shù)據(jù)庫產(chǎn)品的深度依賴和綁定,而且可以不用特意去學(xué)習(xí)不同數(shù)據(jù)庫的本地化特性和方言,降低學(xué)習(xí)成本。
假如你想從 Oracle 遷移到 MySQL 上面,幾乎是不需要改動(dòng)一行代碼,只需要改動(dòng) ORM 的配置就可以實(shí)現(xiàn)了。
參考下圖簡單了解一下 ORM:
Spring Cloud Stream 類似 ORM,你只需要基于 Spring Cloud Stream 提供的消息模型進(jìn)行編程。
至于底層的消息組件是用的 RabbitMQ 還是 Kafka 還是其他的消息中間件產(chǎn)品,都沒有關(guān)系,甚至更換底層消息組件也不會(huì)對你的應(yīng)用產(chǎn)生任何影響,這就是標(biāo)準(zhǔn)化所帶來的收益。
關(guān)于如何更好的理解 Spring Cloud Stream 工作模型可以簡單參考下圖:
微服務(wù)中使用的的兩種服務(wù)通信方式對比:
- 同步:通過 REST 端點(diǎn)接口進(jìn)行請求:服務(wù)之間緊耦合(強(qiáng)依賴),服務(wù)之間的脆弱性(連鎖效應(yīng)),增加新的消費(fèi)者不靈活。
- 異步:基于消息中間件通信:松耦合(無接口直接調(diào)用的依賴),耐久性(服務(wù)重啟后可以消費(fèi)歷史消息),可伸縮性(消息過多可啟動(dòng)多服務(wù)來處理消息),靈活性(輕松添加新的消費(fèi)者)。
消息傳遞架構(gòu)的缺點(diǎn):
- 消息處理語義:消息順序處理,消息異常處理。
- 消息可見性:消息不會(huì)立刻被處理,事務(wù)關(guān)聯(lián) ID 在消息中的傳遞。
消息中放置什么數(shù)據(jù) ?
- 消息體要盡可能的小,減少傳輸成本:通常只返回 action 類型和 id,然后用id獲取最新數(shù)據(jù)。
- 只使用消息傳遞狀態(tài):在消息中包含版本號(hào)和時(shí)間戳,處理數(shù)據(jù)服務(wù)可以檢查數(shù)據(jù)的版本號(hào)。
Spring Cloud Stream 的消息模型和概念:
- 發(fā)射器(Source):接收對象(對象表示要發(fā)布的消息),序列化對象,將消息發(fā)布到通道。
- 通道(Channel):隊(duì)列的抽象,通道寫在配置文件,更改配置切換通道(讀取和寫入隊(duì)列)。
- 綁定器(Binder):與消息平臺(tái)對話的 Spring 代碼,不必依賴特定的 API 來發(fā)布和消費(fèi)消息。
- 接收器(Sink):從隊(duì)列接收消息,將消息反序列化為 POJO。
Spring Cloud Stream 的簡單總結(jié):
- 使用消息傳遞的異步通信是微服務(wù)架構(gòu)的關(guān)鍵部分。
- 使用消息傳遞可以使服務(wù)能夠伸縮并且更具有容錯(cuò)性。
- Spring Cloud Stream 通過簡單的注解抽象底層的消息平臺(tái)細(xì)節(jié)。
⑧Sleuth 和 Zipkin 分布式跟蹤
微服務(wù)分布式架構(gòu)帶來了復(fù)雜度,成本最高的就是跟蹤檢查和運(yùn)維,分布式意味要在多個(gè)服務(wù),機(jī)器跟蹤一個(gè)事務(wù),Sleuth 和 Zipkin 都是用于 Spring Cloud 服務(wù)體系的分布式跟蹤技術(shù),先直接看下最終效果。
下圖一個(gè)簡單的可視化鏈路跟蹤調(diào)用,ZipKin 可以清晰的看到一個(gè)客戶端請求在每個(gè)服務(wù)上面處理所消耗的事情,點(diǎn)擊進(jìn)去可以看到具體的事務(wù)執(zhí)行內(nèi)容,方便排查錯(cuò)誤。
Spring Cloud Sleuth 的工作流程:
- 透明地創(chuàng)建并注入一個(gè)關(guān)聯(lián) ID 到服務(wù)調(diào)用中。
- 管理關(guān)聯(lián) ID 到出站服務(wù)調(diào)用的傳播。
- 將關(guān)聯(lián)信息添加到 Spring 的 MDC 日志記錄(應(yīng)用/跟蹤 ID/跨度 ID/數(shù)據(jù)發(fā)送)。
- 將服務(wù)調(diào)用中的跟蹤信息發(fā)布到 Zipkin 跟蹤平臺(tái)。
Open Zipkin 的簡單概述:
- 調(diào)用鏈?zhǔn)褂靡粡埜蓛艉啙嵉膱D片,比一百萬條日志要好看的多。
- 分布式跟蹤平臺(tái),用于跟蹤多個(gè)服務(wù)調(diào)用的事務(wù)。
- 圖形的方式查看事務(wù)占用的時(shí)間量,分解每個(gè)服務(wù)所用的時(shí)間。
- 4 種不同的數(shù)據(jù)存儲(chǔ):內(nèi)存數(shù)據(jù)/MySQL/Cassandra/Elasticsearch。
關(guān)于微服務(wù)全鏈路跟蹤的總結(jié):
- Spring Cloud Sleuth 可以無縫將關(guān)聯(lián) ID 添加到微服務(wù)中。
- 可以使用關(guān)聯(lián) ID 查看事務(wù)涉及的所有服務(wù)行為。
- 關(guān)聯(lián) ID 需要與日志聚合結(jié)合使用。
- 日志平臺(tái)很重要,但是可視化跟蹤事務(wù)也是有價(jià)值的工具。
⑨部署微服務(wù)
構(gòu)建和部署管道是微服務(wù)架構(gòu)最重要的部分,微服務(wù)的主要特點(diǎn)是快速構(gòu)建,修改,發(fā)布。
符合微服務(wù)特征的部署要達(dá)到以下幾個(gè)要求:
- 自動(dòng)的(自動(dòng)構(gòu)建和部署代碼。
- 完整的(軟件成品是鏡像),不可變(發(fā)布過程不可人為干預(yù))。
- 良好的微服務(wù)部署管道應(yīng)該允許在幾分鐘部署新功能和修復(fù) Bug。
Spring Cloud 大型項(xiàng)目的架構(gòu)方案
這是一個(gè)真實(shí)用于國內(nèi)某大型企業(yè)的微服務(wù)架構(gòu)體系,支撐日均百萬訂單的項(xiàng)目,因?yàn)橐呀?jīng)過了 2 年的保密期,所以可以拿出來分享。
剛好可以結(jié)合前面凌亂的知識(shí)點(diǎn),看看 Spring Cloud 這套組件是如何搭建起來的。
整套微服務(wù)就是下面這張架構(gòu)圖:
具體每個(gè)組件的作用就不在這里詳細(xì)說明了,在這套架構(gòu)方案里面,我們沒有完全照搬 Spring Cloud 全家桶的組建,還是根據(jù)自己的需求對其中組件進(jìn)行的更換。
例如:
- 配置中心從 Spring Cloud Config 更換為 Apollo ,除了有更好的性能,還有更加簡化的操作頁面,修改配置文件毫秒級(jí)響應(yīng)。
- 服務(wù)發(fā)現(xiàn) Eureka 官網(wǎng)已經(jīng)停止維護(hù),我們后面更換為 Alibaba Nacos,服務(wù)注冊和心跳檢測都提升到毫秒級(jí),Eureka 是 90 秒輪詢。
- 分布式任務(wù)調(diào)度引入了 XXL-JOB,這是國內(nèi)主流的分布式任務(wù)調(diào)度平臺(tái),沒有特別需要說明的地方。
- 日志聚合也是用了主流的 ELK 技術(shù)方案,用于收集和檢索日志。
PS:另外在值得補(bǔ)充的是,在寫這篇文章的時(shí)候 Spring Cloud Zuul 已經(jīng)不被官方推薦使用了,替代品是性能更好的 Spring Cloud Gateway ,大家可以在了解的時(shí)候需要注意一下。
總結(jié)
微服務(wù)是未來大型企業(yè)的必經(jīng)之路,雖然成本很高,但是可以提升 IT 系統(tǒng)的健壯性和提升技術(shù)人員的廣度和深度都還是很有幫助的。
作者:肖斌
編輯:陶家龍
出處:轉(zhuǎn)載自公眾號(hào)小二十七(ID:drak-phoenix)