微服務(wù)的10個優(yōu)秀實踐,入門必看!
1. 領(lǐng)域驅(qū)動設(shè)計
微服務(wù)開發(fā)的首要挑戰(zhàn):
把大的、復(fù)雜的應(yīng)用拆分為小的、自治的、可獨立部署的模塊。
如果沒有正確的拆分,那么結(jié)果就是一堆漿糊,有著單體結(jié)構(gòu)的缺點,和微服務(wù)結(jié)構(gòu)的復(fù)雜度,可以稱之為分布式單體。
幸運的是,Eric Evans 為領(lǐng)域驅(qū)動設(shè)計提出了大量的最佳實踐和經(jīng)驗技巧,有3個核心思維:
- 開發(fā)團隊要和業(yè)務(wù)部門、業(yè)務(wù)領(lǐng)域?qū)<揖o密合作。
- 架構(gòu)師、開發(fā)人員、領(lǐng)域?qū)<覒?yīng)該先做出戰(zhàn)略設(shè)計:找出邊界上下文、核心域、子域、上下文映射關(guān)系。
- 架構(gòu)師、開發(fā)人員根據(jù)戰(zhàn)略設(shè)計梳理出一套核心構(gòu)造塊:實體、值對象、聚合等等。
把一個大型系統(tǒng)劃分為核心域、子域,再把核心域、子域映射為微服務(wù),這樣我們就可以得到一個理想的松耦合微服務(wù)體系。
2. 每個微服務(wù)一個數(shù)據(jù)庫
微服務(wù)模塊結(jié)構(gòu)設(shè)計好了,下面一個重要問題就是怎么處理數(shù)據(jù)庫,各個微服務(wù)是否共享數(shù)據(jù)庫呢?
如果共享,將導(dǎo)致微服務(wù)之間緊耦合,違背了微服務(wù)的松耦合原則。數(shù)據(jù)庫中一個小小的變動就需要各個團隊同步修改。
如果每個微服務(wù)都有自己的數(shù)據(jù)庫,那么微服務(wù)之間的數(shù)據(jù)交換將非常麻煩,就像打開了潘多拉魔盒,跑出一堆問題,例如在多個服務(wù)中管理事務(wù)。
所以,很多人主張共享數(shù)據(jù)庫。
但是,微服務(wù)是持續(xù)的、長期的軟件開發(fā),每個微服務(wù)應(yīng)該有其自己的數(shù)據(jù)庫。
3. 微前端
很多后端開發(fā)者輕視前端,認為太簡單。
大多數(shù)架構(gòu)師也是后端出來的,在架構(gòu)設(shè)計中對前端不夠重視。
導(dǎo)致現(xiàn)狀就是,后端模塊化做的很好,而前端還是一整坨。
前端單體結(jié)構(gòu)和后端單體有一樣的問題,所以前端也需要進行現(xiàn)代化的改造。
現(xiàn)在的 web 技術(shù)簡單、強大,例如 web 組件、Angular/React。
4. 持續(xù)交付
每個微服務(wù)可以獨立部署,是微服務(wù)架構(gòu)的核心優(yōu)勢之一。
比如你的系統(tǒng)包含 100 個微服務(wù),現(xiàn)在有一個需要更新,那么你可以只需要發(fā)布這一個,而另外 99 個不需要動。
這就需要 CI/CD 和 DevOps,如果沒有這套自動化流程的話,就像拉著手剎開法拉利。
5. 可觀察性
微服務(wù)架構(gòu)簡化了開發(fā),但復(fù)雜了運維。
單體結(jié)構(gòu)是非常便于監(jiān)控的,但在微服務(wù)架構(gòu)中,服務(wù)很多,而且通常是跑在容器中,對整個系統(tǒng)的監(jiān)控就變得非常復(fù)雜。
需要把所有容器、機器中的日志聚合到一起。
幸運的是已經(jīng)有成熟的解決方案,例如,使用 ELK/Splunk 處理日志,使用 Prometheus/App Dynamics 處理監(jiān)控。
還有一個比較重要的方面:調(diào)用跟蹤。
微服務(wù)間會產(chǎn)生級聯(lián)調(diào)用,為了分析系統(tǒng)延遲,就需要測量每個服務(wù)的延遲,Zipkin/Jaeger 提供了這個能力。
6. 統(tǒng)一技術(shù)棧
微服務(wù)體系中,不同服務(wù)有不同的特性,例如有的服務(wù)是 CPU 密集型操作,使用 C++/Rust 比較合適;有的服務(wù)是做機器學(xué)習(xí)的,使用 Python 比較合適。
所以,可以使用不同的技術(shù)處理相應(yīng)的需求,但是,一定要注意合理性,不要毫無根據(jù)的混合使用不同的技術(shù)。
想象一下,在一套系統(tǒng)中,有的微服務(wù)使用 Spring Boot + Kotlin+ React + MySQL,有的使用 JakartaEE + Java + Angular + PostgreSQL,有的使用 Scala + Play Framework + VueJS + Oracle。
這會不會讓人很崩潰,太難維護了。
7. 異步通信
服務(wù)間的通信問題是微服務(wù)架構(gòu)的重要挑戰(zhàn),比是否共享數(shù)據(jù)庫那個問題還麻煩。
為了實現(xiàn)業(yè)務(wù)需求,需要多個微服務(wù)的協(xié)同工作,服務(wù)間需要進行數(shù)據(jù)交換,一個服務(wù)需要觸發(fā)其他服務(wù)。
最簡單的就是通過 REST 接口直接調(diào)用,但這種同步調(diào)用方式問題比較大。
例如 A -> B -> C -> D,這種多級調(diào)用主要的3個問題:
- 增加了系統(tǒng)延遲。
- 每個服務(wù)可能會故障,這就產(chǎn)生了級聯(lián)性的錯誤。
- 服務(wù)間緊耦合。
最好是使用異步通信的方式,例如通過消息隊列(如 kafka)、異步的 REST(ATOM)、CQRS。
8. 微服務(wù)優(yōu)先
很多人認為新項目應(yīng)該使用單體結(jié)構(gòu),這樣起步快,比微服務(wù)簡單,當發(fā)展大了之后再改造為微服務(wù)。
然而,這個改造是非常困難的,因為單體中模塊的耦合度太高了。
而且產(chǎn)品成熟后,對在線可用性要求很高,那個時候再改造的話,一定會中斷產(chǎn)品運行。
9. 基礎(chǔ)設(shè)施優(yōu)于類庫
Netflix 早期開發(fā)微服務(wù)時,主要使用 java 來開發(fā),Netflix 開發(fā)出了很多優(yōu)秀的庫,如 Hystrix, Zuul,很多公司都使用他們。
后來,包括 Netflix 在內(nèi)的很多公司都發(fā)現(xiàn) java 其實并不擅長微服務(wù)開發(fā),例如 java 體積過于龐大。
Netflix 轉(zhuǎn)向了 Polyglot,并停止了之前那些庫的維護,這就讓很多公司被動了。
所以,不要過度依賴特定語言的類庫,可以使用更底層的基礎(chǔ)框架,例如 Service Meshes。
10. 組織考慮
50 年前,Melvin Conway 發(fā)現(xiàn)公司的軟件架構(gòu)受限于其組織結(jié)構(gòu)。
其實在現(xiàn)在,這個觀點依然正確。
如果一個組織想使用微服務(wù)架構(gòu),那么就應(yīng)該調(diào)整好團隊的大小。
兩個披薩餅原則:如果兩個披薩不足以喂飽一個項目團隊,那么這個團隊可能就顯得太大了。
而且,團隊成員應(yīng)該是多元化的,有前端、后端、測試、運維。
只有高層領(lǐng)導(dǎo)者轉(zhuǎn)變思維方式,微服務(wù)架構(gòu)才有可能發(fā)揮作用。