大火的“微服務(wù)架構(gòu)”詳解與實踐
一、業(yè)務(wù)背景
1.1 產(chǎn)品現(xiàn)狀
1、各產(chǎn)品系統(tǒng)獨立開發(fā),代碼復(fù)用率低,系統(tǒng)之間互相調(diào)用,耦合嚴(yán)重,系統(tǒng)解耦獨立部署困難。
2、傳統(tǒng)的單體架構(gòu),規(guī)模越來越大也越來越笨重;當(dāng)新功能的開發(fā)、功能的重構(gòu)變得不再敏捷可控;測試者的回歸測試邊界難以琢磨;系統(tǒng)的上線部署也變的艱難
3、高并發(fā)訪問下無法提供可靠性服務(wù)
4、持續(xù)集成、持續(xù)部署、持續(xù)交付等工程效率化工具嚴(yán)重缺失
5、監(jiān)控系統(tǒng)、日志分析等系統(tǒng)穩(wěn)定性工具嚴(yán)重缺失
以上種種情況,都讓我們應(yīng)對需求的變化而變得遲鈍。
1.2 業(yè)務(wù)需求
架構(gòu)肯定是為業(yè)務(wù)需求而生的,先來看看我們面對的業(yè)務(wù)需求及其特點。平臺最主要滿足兩大類業(yè)務(wù)需求:面向餐飲企業(yè)在餐飲新零售下的經(jīng)營和運營需求和面向產(chǎn)品及運營團(tuán)隊。
具體來看:
1、餐飲新零售下的餐飲企業(yè)經(jīng)營和運營的痛點
- 如何提升營銷能力和管理會員,以更低的成本為餐飲企業(yè)帶來更多利潤
- 如何對數(shù)據(jù)進(jìn)行深度挖掘和分析,助力決策者進(jìn)行運營決策
- 如何掌握實時數(shù)據(jù),讓決策者及時了解餐廳運營情況
2、面向產(chǎn)品及運營團(tuán)隊
- 主要是提升產(chǎn)品控制能力,促進(jìn)整體系統(tǒng)的良好運轉(zhuǎn)
因此開發(fā)SAAS服務(wù)的產(chǎn)品迫在眉睫,需要滿足快速開發(fā)、靈活升級、高性能、高可用、高穩(wěn)定、簡化運維等更高的需求。
這一步的轉(zhuǎn)型,不是"快"與"慢",而是"生"與"死"。
二、微服務(wù)概念
專注于單一責(zé)任與功能獨立運行的服務(wù),模組化方式組合出大型應(yīng)用。

2.1 特點
- 集中式架構(gòu):單體無分散
- 分布式架構(gòu):分散壓力
- 微服務(wù)架構(gòu):分散能力

2.2 微服務(wù)架構(gòu)優(yōu)勢
每個微服務(wù)組件都是簡單靈活的,能夠獨立部署。不再像單體應(yīng)用時代,應(yīng)用需要一個龐大的應(yīng)用服務(wù)器來支撐。
可以由一個小團(tuán)隊負(fù)責(zé)更專注專業(yè),相應(yīng)的也就更高效可靠。
微服務(wù)之間是松耦合的,微服務(wù)內(nèi)部是高內(nèi)聚的,每個微服務(wù)很容易按需擴(kuò)展。
三、微服務(wù)技術(shù)選型和微服務(wù)的問題
3.1 技術(shù)選型

3.1.1 技術(shù)矩陣結(jié)論
- Netflix提供了比較全面的解決方案
- Spring Cloud對于Netflix的封裝比較全面
- Spring Cloud基于Spring Boot,團(tuán)隊有基礎(chǔ)
- Spring Cloud提供了Control Bus能夠幫助實現(xiàn)監(jiān)控埋點
- 業(yè)務(wù)應(yīng)用部署在阿里云,Spring Cloud對12 Factors以及Cloud-Native的支持,有利于在云環(huán)境下使用
3.1.2 團(tuán)隊期望
- 首先支持Rest
- 團(tuán)隊技術(shù)棧和實例比較單薄,希望對新的技術(shù)平滑的學(xué)習(xí)曲線和能夠Hold住
- 小團(tuán)隊,希望能夠有一個比較全面的解決方案
- 目前團(tuán)隊主要采用Spring Cloud + Spring Boot的方式實現(xiàn)服務(wù)化
- 有關(guān)技術(shù)選型詳細(xì)分析,請查看我的上一篇文章《我的技術(shù)選型》。
3.2 微服務(wù)帶來的問題

- 依賴服務(wù)變更很難跟蹤,其他團(tuán)隊的服務(wù)接口文檔過期怎么辦?依賴的服務(wù)沒有準(zhǔn)備好,如何驗證我開發(fā)的功能。
- 部分模塊重復(fù)構(gòu)建,跨團(tuán)隊、跨系統(tǒng)、跨語言會有很多的重復(fù)建設(shè)。
- 微服務(wù)放大了分布式架構(gòu)的系列問題,如分布式事務(wù)怎么處理?依賴服務(wù)不穩(wěn)定怎么辦?
- 運維復(fù)雜度陡增,如:部署物數(shù)量多、監(jiān)控進(jìn)程多導(dǎo)致整體運維復(fù)雜度提升。

上面這些問題我們應(yīng)該都遇到過,并且總結(jié)形成了自己的一些解決方案,比如提供文檔管理、服務(wù)治理、服務(wù)模擬的工具和框架; 實現(xiàn)統(tǒng)一認(rèn)證、統(tǒng)一配置、統(tǒng)一日志框架、分布式匯總分析; 采用全局事務(wù)方案、采用異步模擬同步;搭建持續(xù)集成平臺、統(tǒng)一監(jiān)控平臺等等。
微服務(wù)架構(gòu)是一把雙刃劍,雖然解決了集中式架構(gòu)和分布式架構(gòu)的問題,卻帶來了如上種種問題。因此我們是需要一個微服務(wù)應(yīng)用平臺才能整體性的解決這些問題。
四、微服務(wù)架構(gòu)設(shè)計
4.1 微服務(wù)應(yīng)用架構(gòu)設(shè)計原則

4.2 微服務(wù)應(yīng)用架構(gòu)設(shè)計目標(biāo)
微服務(wù)架構(gòu)設(shè)計的目標(biāo),滿足快速開發(fā)、靈活升級、高性能、高可用、高穩(wěn)定、簡化運維等更高的需求。

4.3 微服務(wù)應(yīng)用總體架構(gòu)

微服務(wù)應(yīng)用平臺的總體架構(gòu),主要是從開發(fā)集成、微服務(wù)運行容器與平臺、運行時監(jiān)控治理和外部渠道接入等維度來劃分和考慮的。
- 開發(fā)集成:主要是搭建一個微服務(wù)平臺需要具備的一些工具和倉庫
- 運行時:要有微服務(wù)平臺來提供一些基礎(chǔ)能力和分布式的支撐能力,我們的微服務(wù)運行容器則會運行在這個平臺之上。
- 監(jiān)控治理:則是致力于在運行時能夠?qū)κ芄艿奈⒎?wù)進(jìn)行統(tǒng)一的監(jiān)控、配置等能力。
- 服務(wù)網(wǎng)關(guān): 則是負(fù)責(zé)與前端的WEB應(yīng)用 移動APP 等渠道集成,對前端請求進(jìn)行認(rèn)證鑒權(quán),然后路由轉(zhuǎn)發(fā)。
4.4 微服務(wù)框架概覽

這里不詳細(xì)講解服務(wù)框架中每一個組件,另開一篇文章來講解。
五、微服務(wù)架構(gòu)設(shè)計落地
5.1 基礎(chǔ)環(huán)境

一個企業(yè)的IT建設(shè)非常重要的三大基礎(chǔ)環(huán)境:團(tuán)隊協(xié)作環(huán)境、服務(wù)基礎(chǔ)環(huán)境、IT基礎(chǔ)設(shè)施。
- 團(tuán)隊協(xié)作環(huán)境:主要是DevOps領(lǐng)域的范疇,負(fù)責(zé)從需求到計劃任務(wù),團(tuán)隊協(xié)作,再到質(zhì)量管理、持續(xù)集成和發(fā)布。
- 服務(wù)基礎(chǔ)環(huán)境:指的是微服務(wù)應(yīng)用平臺,其目標(biāo)主要就是要支撐微服務(wù)應(yīng)用的設(shè)計開發(fā)測試,運行期的業(yè)務(wù)數(shù)據(jù)處理和應(yīng)用的管理監(jiān)控。
- IT基礎(chǔ)設(shè)施:主要是各種運行環(huán)境支撐如IaaS (VM虛擬化)和CaaS (容器虛擬化)等實現(xiàn)方式。
5.2 服務(wù)通信

服務(wù)間的通信,往往采用HTTP+REST 和 RPC通信協(xié)議。
HTTP+REST,對服務(wù)約束完全靠提供者的自覺。
- 特點是簡單,對開發(fā)使用友好。
- 缺點治理起來困難,連接的無狀態(tài),缺失多路復(fù)用、服務(wù)端推送等。
RPC對通信雙方定義了數(shù)據(jù)約束。
- 連接大多基于長連接以獲得性能的提升及附帶的服務(wù)端推、調(diào)用鏈路監(jiān)控埋點等,增強(qiáng)了系統(tǒng)的附加能力。
- 缺點是對調(diào)用端提出了新的要求。
綜合來看,RPC從性能、契約優(yōu)先來說具有優(yōu)勢,如何做到揚長避短呢?
引入GateWay層,讓REST與RPC的優(yōu)點進(jìn)行融合,在GateWay層提供REST的接入能力。
5.3 服務(wù)注冊/發(fā)現(xiàn)

以前的單體應(yīng)用之間互相調(diào)用時配置個IP或域名就行了,但在微服務(wù)架構(gòu)下,服務(wù)提供者會有很多,手工配置IP地址或域名又變成了一個耦合和繁瑣的事情。那么服務(wù)自動注冊發(fā)現(xiàn)的方案就解決了這個問題。
我們的服務(wù)注冊發(fā)現(xiàn)能力是依賴SpringCloud Eureka組件實現(xiàn)的。服務(wù)在啟動的時候,會將自己要發(fā)布的服務(wù)注冊到服務(wù)注冊中心;運行時,如果需要調(diào)用其他微服務(wù)的接口,那么就要先到注冊中心獲取服務(wù)提供者的地址,拿到地址后,通過微服務(wù)容器內(nèi)部的簡單負(fù)載均衡期進(jìn)行路由用。
Eureka Server特點:
- Eureka Client會緩存服務(wù)注冊信息
- Eureka Server的注冊信息只存儲在內(nèi)存中
- Eureka的注冊只針對application級別,不支持更細(xì)粒度的服務(wù)注冊,如單個服務(wù)Rest
- 服務(wù)每隔30秒向Eureka Server發(fā)送心跳,不建議修改心跳時間。Eureka用這個時間來判斷集群內(nèi)是否存在大范圍的服務(wù)通信異常
- 如果在15分鐘內(nèi)有85%的服務(wù)沒有被續(xù)約,則Eureka Server停止移除已注冊的服務(wù),以保障已注冊的服務(wù)信息不丟失
- Eureka Server之間的數(shù)據(jù)同步,采用全量拉取,增量同步的方式
- Eureka 滿足分布式事務(wù)中的CAP理論中的AP
5.4 集中式配置管理

微服務(wù)分布式環(huán)境下,一個系統(tǒng)拆分為很多個微服務(wù),一定要告別運維手工修改配置配置的方式。需要采用集中配置管理的方式來提升運維的效率。
配置文件主要有運行前的靜態(tài)配置和運行期的動態(tài)配置兩種。
- 靜態(tài)配置通常是在編譯部署包之前設(shè)置好。
- 動態(tài)配置則是系統(tǒng)運行過程中需要調(diào)整的系統(tǒng)變量或者業(yè)務(wù)參數(shù)。
要想做到集中的配置管理,那么需要注意以下幾點。
- 配置與介質(zhì)分離,這個就需要通過制定規(guī)范的方式來控制。
- 配置的方式要統(tǒng)一,格式、讀寫方式、變更熱更新的模式盡量統(tǒng)一,要采用統(tǒng)一的配置框架。
- 需要運行時需要有個配置中心來統(tǒng)一管理業(yè)務(wù)系統(tǒng)中的配置信息。
概念抽象:
介質(zhì),是源碼編譯后的產(chǎn)物與環(huán)境無關(guān),多環(huán)境下應(yīng)該是可以共用的如:jar
5.5 統(tǒng)一認(rèn)證鑒權(quán)

安全認(rèn)證方面,我們基于Spring Security OAuth2 + JWT做安全令牌,實現(xiàn)統(tǒng)一的安全認(rèn)證與鑒權(quán),使得微服務(wù)之間能夠按需隔離和安全互通。
認(rèn)證鑒權(quán)一定是個公共的服務(wù),而不是多個系統(tǒng)各自建設(shè)。
5.6 分布式調(diào)用
微服務(wù)架構(gòu)下,相對于傳統(tǒng)部署方式,存在更多的分布式調(diào)用,那么“如何在不確定的環(huán)境中交付確定的服務(wù)”,這句話可以簡單理解為,我所依賴的服務(wù)的可靠性是無法保證的情況下,我如何保證自己能夠正常的提供服務(wù),不被我依賴的其他服務(wù)拖垮?
我們采用的方案:
- 合理的超時時間
- 合理的重試機(jī)制
- 合理的異步機(jī)制
- 合理的限流機(jī)制(調(diào)用次數(shù)和頻率)
- 合理的降級機(jī)制
- 合理的熔斷機(jī)制
推薦SEDA架構(gòu)來解決這個問題。
SEDA : staged event-driven architecture本質(zhì)上就是采用分布式事件驅(qū)動的模式,用異步模擬來同步,無阻塞等待,再加上資源分配隔離結(jié)起來的一個解決方案。

5.7 分布式事務(wù)
分布式事務(wù)-CAP
- C 分布式環(huán)境下多個節(jié)點的數(shù)據(jù)是否強(qiáng)一致
- A 分布式服務(wù)能一直保證可用狀態(tài)
- P 網(wǎng)絡(luò)分區(qū)的容錯性

分布式事務(wù)-策略
- 避免跨庫事務(wù),盡可能相關(guān)表在同一個DB
- 2PC 3PC TCC 補償模式等, 耗時且復(fù)雜
- 基于MQ的最終一致性 簡單、高效、易于理解
- 將遠(yuǎn)程分布式事務(wù)拆解成一系列本地的事務(wù)
分布式事務(wù)-基于MQ

5.8 服務(wù)拆分
服務(wù)拆分方式

AKF擴(kuò)展立方體,是抽象總結(jié)的應(yīng)用擴(kuò)展的三個維度。
- X軸 擴(kuò)展部署實例,就是講單體系統(tǒng)多運行幾個實例,做個集群加負(fù)載均衡的模式。
- Y軸 業(yè)務(wù)領(lǐng)域分離,就是基于不同的業(yè)務(wù)拆分。
- Z軸 數(shù)據(jù)隔離分區(qū),比如共享單車在用戶量激增時,集群模式撐不住了,那就按照用戶請求的地區(qū)進(jìn)行數(shù)據(jù)分區(qū),北京、上海、深圳等多建幾個集群。
服務(wù)拆分要點
- 低耦合、高內(nèi)聚:一個服務(wù)完成一個獨立的功能
- 按照團(tuán)隊結(jié)構(gòu):小規(guī)模團(tuán)隊維護(hù),快速迭代
5.9 數(shù)據(jù)庫拆分
單庫單表難以支撐日益增長的業(yè)務(wù)量和數(shù)據(jù)量,服務(wù)拆分了數(shù)據(jù)庫也跟著拆分。
5.9.1 模式
- 垂直拆分
- 水平拆分
5.9.2 原則
- 盡可能不拆分
- 避免跨庫事務(wù)
- 單表量級1000w
- 避免垮褲join(冗余、全局表)

5.10 日志管理
日志主要有三種,系統(tǒng)日志,業(yè)務(wù)日志,跟蹤日志。有了這些日志,在出問題的時候能夠幫助我們獲取一些關(guān)鍵信息進(jìn)行問題定位。
要想做到,出了問題能夠追根溯源,那么我們需要一個可以將整個完整的請求調(diào)用鏈串聯(lián)起來的標(biāo)識,這個標(biāo)識能夠讓我們快速定位問題發(fā)生的具體時間地點以及相關(guān)信息,能夠快速還原業(yè)務(wù)交易全鏈路。對這些日志與流水的細(xì)節(jié)處理,對于系統(tǒng)運維問題定位有非常大的幫助。通常開源框架只是提供基礎(chǔ)的框架,而設(shè)計一個平臺則一定要考慮直接提供統(tǒng)一規(guī)范的基礎(chǔ)能力。
分布式跟蹤



5.11 服務(wù)契約與API管理

對于前面提到的微服務(wù)帶來的依賴管理問題,我們需要提供API管理能力。說到API管理,那首先就用提到服務(wù)契約。
服務(wù)契約,主要描述服務(wù)接口的輸入輸出規(guī)格標(biāo)準(zhǔn)和其他一些服務(wù)調(diào)用集成相關(guān)的規(guī)格內(nèi)容。
5.12 服務(wù)契約與服務(wù)模擬

有了服務(wù)契約,研發(fā)人員就可以方便的獲取到依賴服務(wù)變更的情況,能夠及時的根據(jù)依賴服務(wù)的變化調(diào)整自己的程序,并且能夠方便的進(jìn)行模擬測試驗證。
根據(jù)契約生成模擬服務(wù)也就是我們常說的服務(wù)擋板,這樣即使依賴的其他服務(wù)還無法提供功能,我們也可以通過擋板來進(jìn)行聯(lián)調(diào)測試。
5.13 微服務(wù)容器

我們要做穩(wěn)定、高效、易擴(kuò)展的微服務(wù)應(yīng)用,實際上我們需要做的事情還是非常多的。如果沒有一個統(tǒng)一的微服務(wù)容器,這些能力在每個微服務(wù)組件中都需要建設(shè)一遍,也很難集成到一起。有了統(tǒng)一的微服務(wù)運行容器和一些公共的基礎(chǔ)服務(wù),前面所提到的微服務(wù)架構(gòu)下部分組件重復(fù)建設(shè)的問題也迎刃而解。
5.14 持續(xù)集成與持續(xù)部署

在運維方面,首先我們要解決的就是持續(xù)集成和持續(xù)交付,能夠方便的用持續(xù)集成環(huán)境把程序編譯成介質(zhì)包和部署包并持續(xù)穩(wěn)定的部署到每個環(huán)境。
概念抽象:
介質(zhì):是源碼編譯后的產(chǎn)物與環(huán)境無關(guān),多環(huán)境下應(yīng)該是可以共用的。如:jar
配置:則是環(huán)境相關(guān)的信息。
部署包=配置+介質(zhì)。
5.15 微服務(wù)平臺與容器云、DevOps的關(guān)系

就微服務(wù)應(yīng)用平臺本身來說,并不依賴DevOps和容器云,開發(fā)好的部署包可以運行在物理機(jī)、虛擬機(jī)或者是容器中。然而當(dāng)微服務(wù)應(yīng)用平臺結(jié)合了DevOps和容器云之后,我們就會發(fā)現(xiàn),持續(xù)集成和交付變成了一個非常簡單便捷并且又可靠的過程。簡單幾步操作,整套開發(fā)、測試、預(yù)發(fā)或者生產(chǎn)環(huán)境就能夠搭建完成。
整個過程的復(fù)雜度都由平臺給屏蔽掉了,通過三大基礎(chǔ)環(huán)境的整合,我們能夠使分散的微服務(wù)組件更簡單方便的進(jìn)行統(tǒng)一管理和運維交付。
5.16 技術(shù)團(tuán)隊的組織
技術(shù)團(tuán)隊組織 – 小團(tuán)隊

根據(jù)“康威定律”,軟件架構(gòu)是由組織的架構(gòu)決定的,因此按照貝索斯“two-pizza”團(tuán)隊的理論和敏捷方法,構(gòu)建小的團(tuán)隊,可以有效減少溝通成本,有利于團(tuán)隊的自治。
我們通過讓一個小的團(tuán)隊有比較全面的建制,Leader(熟悉業(yè)務(wù)和技術(shù))+ 前端工程師 + 后端工程師,往往可以能夠比較獨立地承接一個或者幾個業(yè)務(wù)的工作。這樣團(tuán)隊成員整體負(fù)責(zé)一個或者幾個業(yè)務(wù)模塊,可以極大地提高團(tuán)隊成員的參與感、使命感和責(zé)任感,團(tuán)隊成員相互幫助,高度自治,大家要么一起成功,要么一起失敗。
技術(shù)團(tuán)隊組織 – 團(tuán)隊劃分

團(tuán)隊的劃分,是按照業(yè)務(wù)線劃分的。隨著業(yè)務(wù)的復(fù)雜度的增加,可以按照業(yè)務(wù)/子業(yè)務(wù)線的方式來劃分團(tuán)隊,但并不是絕對的扁平化,而是嚴(yán)格遵循two-pizza原則。
業(yè)務(wù)線的劃分常常按業(yè)務(wù)細(xì)分,技術(shù)團(tuán)隊要負(fù)責(zé)支持全部業(yè)務(wù)線,因此技術(shù)團(tuán)隊的劃分通常按系統(tǒng)或者是業(yè)務(wù),Two pizza團(tuán)隊的原則在組織層級的任何部分都適用,當(dāng)人數(shù)過多時,必須繼續(xù)拆分。
技術(shù)團(tuán)隊組織 – 團(tuán)隊合作

技術(shù)團(tuán)隊組織 – 結(jié)果導(dǎo)向
1.主人翁意識(Ownership)
2.行動力(Bias for Action)
3.吃自己的狗糧(Eat your dog food)
- 工程師負(fù)責(zé)從需求調(diào)研、設(shè)計、開發(fā)、測試、部署、維護(hù)、監(jiān)控、功能升級等一系列的工作,也就是說軟件工程師負(fù)責(zé)應(yīng)用或者服務(wù)的全生命周期的所有工作
- 運維是團(tuán)隊成員的第一要務(wù),在強(qiáng)大的自動化運維工具的支撐下,軟件工程師必須負(fù)責(zé)服務(wù)或者應(yīng)用的SLA
4.開發(fā)人員參與架構(gòu)設(shè)計,而不是架構(gòu)師參與開發(fā)
- 研發(fā)人員是Owner,對業(yè)務(wù)和團(tuán)隊負(fù)責(zé)
- 強(qiáng)調(diào)抽象和簡化,將復(fù)雜的問題分解成簡單的問題,并有效解決,避免過度設(shè)計
- 鼓勵用新技術(shù)解決問題,但強(qiáng)調(diào)掌控力
六、微服務(wù)架構(gòu)設(shè)計過程中積累的心得
- 深入理解業(yè)務(wù)
- 設(shè)計階段要追求完美,實踐階段要考慮實際情況作出平衡
- 容錯能力
- 監(jiān)控先行
- 任何上線可回滾
七、總結(jié)
微服務(wù)架構(gòu)是技術(shù)升級,但更多的是管理模式的升級、思維方式的轉(zhuǎn)變。