新聞中心
微服務“很香”,它有許多優(yōu)勢,比如更快的開發(fā)、更好的可擴展性、更小的獨立團隊等等。但是,很多團隊卻在微服務上舉步維艱,沒有很好利用其優(yōu)勢。原因到底是什么?這是本文作者試圖回答的。

過去幾年,我對推進數(shù)字化轉(zhuǎn)型的多家產(chǎn)品團隊進行了架構審查。我發(fā)現(xiàn):大多數(shù)團隊都是遵循微服務架構來構建產(chǎn)品。更快的開發(fā)、更好的可擴展性、更小的獨立團隊、獨立部署和使用正確的技術來完成工作等等,這些優(yōu)勢讓他們有充足的理由采用微服務架構。
但是,我經(jīng)常發(fā)現(xiàn):很多團隊在微服務上舉步維艱。他們并未充分利用微服務的優(yōu)勢。為什么許多團隊在微服務之路上“舉步維艱”?這是我試圖回答的。
如果你是微服務新手,我推薦你閱讀 Martin Fowler 關于微服務的文章。
https://martinfowler.com/articles/microservices.html
這篇文章闡釋了何為微服務架構:
微服務架構的風格是一種將單個應用程序開發(fā)成一套小型服務的方法,每個應用程序都在自己的進程中運行,并與輕量級機制(通常是 HTTP 資源 API)進行通信。這些服務是圍繞業(yè)務功能而構建的,并且可以由完全自動化的部署機制來獨立部署。這些服務只有最低限度的集中管理,可以用不同的編程語言編寫,并使用不同的數(shù)據(jù)存儲技術。
1. 管理層低估開發(fā)微服務的復雜性
我曾與許多非??春梦⒎盏目蛻粢黄鸷献鬟^。對他們來說,微服務就是解決他們所有問題的“靈丹妙藥”。
當討論逐漸深入,我發(fā)現(xiàn):大多數(shù)團隊及其管理層都低估了微服務開發(fā)的復雜性。
要開發(fā)微服務,開發(fā)人員需要一個高效的本地環(huán)境設置。
隨著系統(tǒng)中服務數(shù)量開始增加,在一臺機器上運行應用程序的子集變得越來越困難。特別是當你使用消耗較多內(nèi)存的語言(如 Java)構建應用程序時,更是如此。
下面是與本地開發(fā)設置相關的要點:
- 本地開發(fā)的第一個重要方面是要有一個好的開發(fā)機器。
我發(fā)現(xiàn),大多數(shù)組織想要使用所有最新的、最技術,但卻不想替換掉糟糕的 Windows 開發(fā)機器。開發(fā)人員受限于他們的開發(fā)機器。我曾見過開發(fā)人員使用 VDI 映像或配置交叉的機器來構建基于微服務的系統(tǒng)。這不僅降低了他們的工作效率,而且讓他們無法完全投入工作。使用糟糕的開發(fā)機器帶來的副作用就是,開發(fā)人員無法得到快速反饋。如果知道了必須等數(shù)分鐘才能運行集成測試套件,那么你就不會編寫更多的集成測試套件,免得讓你更痛苦。糟糕的開發(fā)機器將會導致糟糕的開發(fā)實踐。
- 一旦你為開發(fā)人員配備了合適的開發(fā)機器,那么下一步就是確保所有服務都使用構建工具。
你應該能在一臺新機器上構建整個應用程序,而不需要進行太多配置。根據(jù)我在微服務方面的經(jīng)驗,使用能構建整個應用程序的根構建腳本也會有所幫助。
- 下一個要點是要讓開發(fā)人員能輕松地在他們的系統(tǒng)上運行應用程序的各個部分。在配置了所有端口和卷的情況下,你應該使用多個 docker-compose 文件來提供不同服務。
- 接下來,如果你使用的是類似于 Kubernetes 的容器編排工具,那么你應該投資類似于 Telepresence 這樣的工具,以便輕松調(diào)試 Kubernetes 集群中的應用程序。
如果組織對微服務開發(fā)的復雜性缺乏理解,那么團隊速度將會隨著時間的推移而下降。
2. 沒有將庫和工具更新到最新版
我發(fā)現(xiàn)一個新的平臺已經(jīng)成為一種遺產(chǎn)。團隊沒有確保依賴項是最新的版本,或者將像數(shù)據(jù)庫這樣的工具升級到最新版本。
因此,兩年前開始的現(xiàn)代化改造,如今已經(jīng)背負長達數(shù)月的技術債。
幾年前,許多團隊開始將 Spring Cloud Netflix OSS 項目用于微服務。他們使用像 Kubernetes 這樣的容器編排工具,但是因為是從 Netflix OSS 開始的,所以他們沒有使用 Kubernetes 提供的所有功能。當 Kubernetes 內(nèi)置了服務發(fā)現(xiàn)時,他們?nèi)匀皇褂?Eureka 作為服務發(fā)現(xiàn)。
此外,通過類似 Istio 這樣的服務網(wǎng)格,你可以擺脫 Netflix OSS 提供的大部分服務。這有助于降低復雜性,并將許多“橫向關注點”(cross cutting concerns)轉(zhuǎn)移到平臺上。
需要記住的另一點是,要使所有服務的依賴項版本保持同步。
最近,我在幫助一個客戶,它使用 Spring Boot 來構建微服務。在過去兩年,他們已經(jīng)構建了 20 多個 Spring Boot 服務。在其環(huán)境中,他們使用的 Spring Boot 版本從 1.5 到 2.1 不等。這意味著一旦有人設置他們的機器時,他們必須下載多個版本的 Spring Boot。
此外,他們還缺乏自 1.5 版本以來在 Spring Boot 中所做的許多改進。
建議是,組織應該在其積壓中為這些升級創(chuàng)建技術債務項。這些技術債務項應作為架構委員會會議的一部分加以討論,并定期予以解決。在我的上一個項目中,我們每三個月設置為期一周的 sprint,將所有依賴項更新到最新版本。
3. 利用共享服務促進本地開發(fā)
由于本地開發(fā)狀況不佳,大多數(shù)團隊開始依賴于共享環(huán)境來獲得關鍵服務。開發(fā)人員機器中的第一件事就是數(shù)據(jù)庫。大多數(shù)年輕的開發(fā)人員并沒有意識到基于共享數(shù)據(jù)庫的開發(fā)是“邪惡的”。
下面,是我在共享數(shù)據(jù)庫中看到的主要問題:
- 團隊成員必須建立一個工作的社會契約,以避免最后寫入者勝出(Last write wins,LWW)問題。一個開發(fā)人員可以刪除其他開發(fā)人員為他們工作編寫的數(shù)據(jù)。這種工作方式既痛苦又容易失敗,遲早會影響整個團隊。
- 開發(fā)人員害怕實驗,因為他們的工作會影響其他團隊成員。我們都知道,更好的學習方法是實驗和快速反饋。有了共享數(shù)據(jù)庫,就可以進行實驗。我們需要進行實驗,以提出數(shù)據(jù)庫模式,并執(zhí)行任務,如性能調(diào)優(yōu)之類。
- 另一個副作用就是,很難單獨測試更改。你的集成測試將變得不可靠,從而進一步降低開發(fā)速度。
- 共享數(shù)據(jù)庫必須像寵物一樣對待,因為你不希望它出現(xiàn)不一致和不可預測的狀態(tài)。你可能會遇到這樣一種場景,開發(fā)人員希望在表是空的時候測試邊緣情況,但其他開發(fā)人員需要一個表來記錄。
- 只有共享數(shù)據(jù)庫擁有系統(tǒng)工作所需的所有數(shù)據(jù)。隨著時間推移,團隊成員失去了更改的可追溯性,因此沒有人知道,他們該如何在他們的機器上復制相同的設置。唯一的方法是獲取完整的數(shù)據(jù)庫轉(zhuǎn)儲并使用它。
- 如果未連接到網(wǎng)絡,就很難開展工作。這種情況通常發(fā)生在你通勤時間過長或乘飛機的時候。
數(shù)據(jù)庫只是共享服務的一個示例,但它也可以是消息隊列、集中緩存(如 Redis)或任何其他服務可以發(fā)生改變的服務。
解決這一問題的最好方法是,讓開發(fā)人員可以輕松地在他們的機器上運行數(shù)據(jù)庫(作為 Docker 容器),并投資創(chuàng)建 SQL 腳本來設置模式和初始主數(shù)據(jù)。這些 SQL 腳本應該保存在版本控制中,并像維護任何其他代碼一樣進行維護。
4. 版本控制托管平臺缺乏可見性
我曾與一個客戶進行合作,當時,他們的版本控制系統(tǒng)中有 1000 多個倉庫。他們使用的是 Gitlab 版本控制平臺。他們有 5 個產(chǎn)品,每個產(chǎn)品都由多個微服務組成。
我問他們的第一個問題是幫助我們了解哪些服務及其各自代碼庫是產(chǎn)品 A 的一部分。他們的首席架構師不得不花一天時間弄清楚所有產(chǎn)品 A 的倉庫。一天過去了,她還是不能確定是否弄清楚了所有服務。
解決這個問題的最好方法是,從一開始就以某種方式對你的微服務進行分組,這樣,你就可以隨時了解產(chǎn)品的生態(tài)系統(tǒng)。Gitlab 提供一種方法來創(chuàng)建一個組,然后在其中創(chuàng)建項目倉庫。Github 并沒有組功能,因此你可以使用主題或命名約定來實現(xiàn)它。
我個人更喜歡 mono repos,因為我發(fā)現(xiàn)他們真的很方便。我遇到的大多數(shù)開發(fā)人員都認為它是一種反模式。我同意 Dan Lua 的觀點,他提到了 mono repo 的以下好處:
- 簡化的組織
- 簡化的依賴關系
- 工具
- 跨項目變更
5. 服務沒有明確定義
大多數(shù)團隊并不知道什么應該被視為服務。關于究竟是什么構成一個單一的微服務,人們對此存在很多混淆的認識和困惑的概念。
讓我們舉一個例子,假設你的應用程序具有類似插件的架構,在這個架構中,你集成了多個第三方服務。每個集成應該是一個微服務嗎?我看到很多團隊,都在為每個集成創(chuàng)建一個微服務。隨著集成數(shù)量的增加,這種情況很快就會失控,以至于無法管理。這些服務通常太小,以至于將它們作為單獨的進程運行,會增加更多的開銷。
我認為,哪怕只擁有少量的大型服務,總比提供太多的小型服務要好得多。我將從創(chuàng)建一個服務開始,該服務對業(yè)務組織中的整個部門進行建模。這也符合 DDD(領域驅(qū)動設計, Domain Driven Design)。我將一個域分為子域和有界上下文。有界上下文表示公司內(nèi)部的一個部門,如財務部門和營銷部門。你可能認為,這會導致大型服務的出現(xiàn),你是對的。
隨著知識經(jīng)驗越來越多,你可以轉(zhuǎn)向代表更小問題的細粒度微服務。你能應用單一責任原則(Single Responsibility Principle)來了解微服務是否變得過大,做的事情是否過多。
然后,你可以將它分解成更小的獨立服務。任何服務都不應該直接與其他服務的數(shù)據(jù)庫通信。他們應該只通過已發(fā)布的合同進行溝通。在 Microservices.io 網(wǎng)站上,你能了解更多關于按子域模式分解的內(nèi)容。
https://microservices.io/patterns/decomposition/decompose-by-subdomain.html
我也遵循了 Backendlore 文檔中提到的建議。
https://github.com/fpereiro/backendlore
這個建議可以幫助將服務限制在服務通信上,而服務通信是微服務系統(tǒng)性能低下的首要原因。如果兩條信息相互依賴,那么它們應該屬于同一個服務器。換句話說,服務的自然邊界應該是其數(shù)據(jù)的自然邊界。
6. 代碼重用策略不明確
我曾經(jīng)和一個客戶合作,該客戶在他們所有基于 Java 的微服務復制了四個與特定問題相關的 Java 文件。因此,如果在該代碼中發(fā)現(xiàn) bug 的話,就需要將其修復應用到所有地方。我們都知道,在時間緊迫的情況下,我們會錯過將更改應用于一個或多個服務。這樣會浪費更多時間,增加挫敗感。
這并非說開發(fā)團隊不懂正確的事情。但是,按照組織結(jié)構,人們總是默認采用簡單且容易出錯的做事方式。
正確的方法是,使用像 Bintray 或 Nexus 這樣的工件管理器,并在那里發(fā)布依賴項。然后,每個微服務都應該依賴于這個庫。你需要構建工具,以便在發(fā)布新版本的庫時,所有的微服務都應該進行更新和重新部署。
使用微服務并不意味著你不應該使用迄今為止對我們有用的最佳實踐。你需要對工具進行投資,使微服務的升級變得更容易,這樣人們就不必這樣做了。
在沒有適合的工具和自動化的情況下,使用微服務會導致災難。
7. 多語言編程設計
我發(fā)現(xiàn)團隊使用多種編程語言、多種數(shù)據(jù)庫、多種緩存,并以最佳工具的名義進行工作。所有這些都在項目初始階段起作用,但隨著你的產(chǎn)品投入生產(chǎn),這些選擇開始顯露“本色”。
原因就像我們在構建 JavaSpringBoot 應用程序,但是我們意識到 Java 占用更多的內(nèi)存,而且性能也很差,所以我們決定改用 Node.js。在我的上一次任務中,我向團隊解釋說他們的推理能力很弱。
(1)Note.js 比 Java 性能更好
如果你的工作負載是基于 I/O 的,Node.js 通常會表現(xiàn)的更好。但在任何計算密集型的工作負載上,Java 都勝過 Node.js。通過響應式范式(reactive paradigm),你可以使用 Java 為 I/O 工作負載提供更好性能。在 I/O 工作負載方面,Spring Boot Reactor 的性能相當于 Node.js。
https://benchmarksgame-team.pages.debian.net/benchmarksgame/fastest/javascript.html
https://blogs.sap.com/2018/08/03/spring-boot-reactive-vs.-node.js-in-sap-cloud-platform-reflection-on-throughput-measurement/
(2)Node.js 比 Java 消耗更少的內(nèi)存
在一定程度上,這是正確的說法。Java Spring Boot 應用程序并不像大多數(shù)想象的那么糟糕。我在一個 Spring Boot Java 微服務上運行了負載測試,內(nèi)存消耗仍然沒超過 1 GB。你可以通過 OpenJ9 JVN,限制對類路徑的依賴,并通過調(diào)優(yōu)默認的 JVM 參數(shù)來優(yōu)化 Java 內(nèi)存利用率。此外,在 Java 中還有 Spring Boot 的新替代品,如 Micronaut 和 Quarkus,它們消耗的內(nèi)存相當于 Node.js。
(3)Node.js 比 Java 效率更高
這取決于編寫代碼的開發(fā)人員。使用靜態(tài)類型和靜態(tài)分析工具的 Java 可以幫助在開發(fā)生命周期的早期發(fā)現(xiàn)問題。
大多數(shù)情況下,這完全取決于上下文。如果你的開發(fā)人員還不夠成熟的話,那么無論你使用什么編程語言,你開發(fā)的都將是糟糕的產(chǎn)品。
我建議一家組織要發(fā)布一個團隊可以使用的語言列表。我認為 2~3 就是個很不錯的數(shù)字。另外,要列出一種語言比另一種語言更適合的理由。
在選擇一門語言前,你應該考慮以下一些問題:
- 找到成熟的企業(yè)軟件開發(fā)人員有多容易?
- 重新培訓開發(fā)人員掌握新技術有多容易?我們發(fā)現(xiàn) Java 開發(fā)人員可以相對容易地學習 Golang。
- 初始團隊之外的開發(fā)人員貢獻、轉(zhuǎn)移和維護其他人編寫的代碼有多容易?
- 就工具和庫的方面而言,生態(tài)系統(tǒng)有多成熟?
這不僅僅局限于編程語言,也適用于數(shù)據(jù)庫領域。如果你的系統(tǒng)中已經(jīng)有了 MongoDB,那么你為什么要在生態(tài)系統(tǒng)中使用 ArangoDB 呢?它們都主要是文檔數(shù)據(jù)庫。
要始終考慮使用多種技術的維護和操作方面。
8. 人員的依賴性
這并非微服務特有的現(xiàn)象,但在微服務生態(tài)系統(tǒng)中卻變得更加普遍。原因是,大多數(shù)團隊專注于他們的特定服務,因此他們并不了解完整的生態(tài)系統(tǒng)。在我與不同客戶的工作中,我發(fā)現(xiàn),只有一群架構師了解整體情況。但是,這些架構師的問題在于,他們并不積極參與日常活動,因此他們對開發(fā)的影響力是有限的。
我認為最好的辦法是,確保所有團隊都有一個架構團隊的代表,這樣他們就可以使他們的團隊與整個架構團隊的路線圖和目標保持一致。要成為一個成熟的組織,你需要投資于建立一個輕量級的治理。
9. 文檔的缺乏
在過去幾年,我們接觸過的大多數(shù)組織都在文檔方面遇到困難。大多數(shù)開發(fā)人員和架構師要么不去編寫文檔,要么編寫的文檔毫無用處。即使他們想寫,他們也不知道應該如何記錄他們的架構。
我們至少應該記錄以下內(nèi)容:
- 設計文檔
- C4 模型中的上下文和容器圖
- 以架構決策記錄的形式跟蹤關鍵架構決策
- 開發(fā)人員入門指南
我建議在版本控制系統(tǒng)中維護所有的文檔。
https://c4model.com/
http://thinkrelevance.com/blog/2011/11/15/documenting-architecture-decisions
10. 功能超過平臺成熟度
在其他觀點中,我簡要地提到了這個原因,但我認為,它值得作為一個頂級原因來提及。微服務要比傳統(tǒng)的單體式應用(monolithic application)更為復雜,因為你正在構建一個包含許多活動部件的分布式系統(tǒng)。大多數(shù)開發(fā)人員還不了解系統(tǒng)的不同故障模式。大多數(shù)微服務在構建時都考慮了令人快樂的路徑。因此,如果你的管理層只想僅僅關注功能,那么你注定會失敗。因為在薄弱平臺上構建的功能是無法提供價值的。
組織需要有平臺思維。平臺思維可不僅僅意味著使用容器和 Kubernetes。它們是解決方案的一部分,但本身并非完整的解決方案。你還需要考慮分布式跟蹤、可觀察性、混沌測試、函數(shù)調(diào)用與網(wǎng)絡調(diào)用、服務間通信的安全服務、可調(diào)試性等等。這需要在構建正確的平臺和工具團隊方面付出認真的努力和投資。
如果你是一家資源有限的初創(chuàng)公司,我的建議是,你要重新考慮微服務戰(zhàn)略。了解你所面臨的問題是什么。
11. 缺乏自動化測試
大多數(shù)團隊都知道自動化測試對產(chǎn)品的整體質(zhì)量有多重要,但是他們?nèi)匀粵]有做到。
微服務架構為測試地點和測試方式提供了更多選擇。如果你不進行徹底的自動化測試,那么你將會失敗得很慘。關于這一點,我不會再贅述,因為網(wǎng)上很多人都寫過這方面的內(nèi)容了。
下圖是我從微服務測試的文章找到的,這篇文章來自 Martin Fowler 的網(wǎng)站,討論了基于微服務的系統(tǒng)的測試金字塔。
微服務測試金字塔
當前名稱:了解微服務失敗的這11個原因,預防和及時止損!
網(wǎng)頁網(wǎng)址:http://m.fisionsoft.com.cn/article/dheegjh.html


咨詢
建站咨詢
