微服务开发的 10 个最佳实践
作者 | Md Kamaruzzaman
譯者 | 冬雨
策劃 | 萬佳
隨著軟件系統越來越復雜,大型的軟件系統變得難于開發、增強、維護、現代化和規?;?。為解決這一問題,人們嘗試過模塊化軟件開發、分層軟件架構、SOA?,F在,微服務架構成為解決現代軟件應用復雜性的新“利刃”。但正確設計微服務架構非常具有挑戰性和困難,因此本文作者提出一些最佳實踐,這些實踐有助于開發有效的微服務應用程序。
軟件系統是復雜的。由于人腦只能處理一定程度內的復雜性,大型軟件系統的高復雜性導致許多問題。大型復雜的軟件系統難于開發、增強、維護、現代化和規模化。
多年來,為解決軟件系統的復雜性做過許多嘗試:
19 世紀 70 年代,David Parnas 和 Edsger W. Dijkstra 引入模塊化軟件開發,來解決軟件系統的復雜性;
19 世紀 90 年代,引入分層軟件架構來處理業務應用程序的復雜性;
20 世紀初以來,面向服務的架構(SOA)成為開發復雜業務應用程序的主流。
而微服務架構則是處理現代軟件應用復雜性的最新方法。它將軟件系統分解成可獨立部署的自治模塊,這些模塊通過輕量級的、語言無關的方式通信,共同實現業務目標。
有人可能會問:為什么我們突然需要一種新的軟件開發方法?簡單說,與軟件開發相關的整個生態系統在過去十年發生巨大變化。如今,軟件使用敏捷方法開發,使用 CI/CD 在容器 + 云上部署,在 NoSQL 數據庫上持久化,在現代瀏覽器或智能手機上展現,機器通過高速網絡連接。這些因素的出現催生出微服務架構。
正確設計微服務架構非常具有挑戰性和困難。與單體架構為所有問題提供一個解決方案相反,微服務架構需要為不同問題提供不同的解決方案。
這里,我提出一些最佳實踐,這些實踐將有助于開發有效的微服務應用程序。在這些應用程序中,目標項目應該存在超過 6 個月的時間,并且團隊規模從中等到大型(6+ 開發人員)。
?
??
1. 領域驅動設計
開發微服務的首要挑戰是將大型、復雜的應用程序分割成小型、自主、獨立的可部署模塊。如果微服務沒有以正確的方式進行分割,將會出現緊耦合的微服務,這些微服務將具有單體架構的所有缺點,并具有分布式單體架構的所有復雜性。
幸運的是,已經有解決方案可以在這方面提供很大幫助。Eric Evans 當時是一名軟件工程顧問,他在不同公司的業務應用程序中遇到了關于軟件復雜性的反復出現的問題,于是在 2004 年出版的《領域驅動設計:處理軟件核心的復雜性》一書中總結了他的寶貴見解。該書概述了三個核心概念:
軟件開發團隊應該與業務部門或領域專家密切合作;
架構師 / 開發人員和領域專家應該首先進行戰略設計:找到有界的上下文和相關的核心域以及普遍存在的語言、子域、上下文映射;
然后,架構師 / 開發人員應該進行戰術設計,將核心域分解為細粒度的構建塊:實體、值對象、聚合、聚合根。
領域驅動設計的詳細討論超出了這篇文章的討論范圍,但是你應該讀一下起初的 DDD 書籍 Eric Evans 的《領域驅動設計:處理復雜的軟件(藍皮書)( Domain Driven Design:Tackling Complexity in the Heart of Software ?(Blue Book))》,或者更現代一點兒的 DDD 書籍 ?Vaughn Vernon 的《實現領域驅動設計(紅皮書)( Implementing Domain Driven Design (Red Book))》。
如果將一個大型系統劃分為核心域和子域,然后將核心域和子域映射到一個或多個微服務,那么我們將得到理想的松耦合微服務。
??
??
2.?每個微服務一個數據庫
在將復雜的應用程序拆分為多個微服務模塊之后,下一個挑戰出現了,如何處理數據庫?我們是否應該在微服務之間共享數據庫?這個問題的答案是一把雙刃劍。一方面,在微服務之間共享數據庫將導致微服務之間的強耦合,這與微服務架構的目標正好相反。即使是數據庫中的一個小更改也需要團隊之間的協調同步。
此外,在一個服務中管理數據庫的事務和鎖就已經足夠具有挑戰性了。而在多個分布式微服務之間管理事務和鎖更是一項艱巨的任務。另一方面,如果每個微服務都有自己的數據庫或私有表,那么在微服務之間交換數據就打開了挑戰的潘多拉盒子。因此,許多著名的軟件工程師都提倡在微服務之間共享數據庫,將其作為一種實用的解決方案。
然而,在我看來,微服務是關于可持續和長期的軟件開發的。因此,每個微服務都應該有自己的數據庫(或者私有表)。
??
??
3. 微前端
不幸的是,大多數的后端開發人員對前端開發有一種過時的看法,認為前端開發很簡單。由于大多數軟件架構師都是后端開發人員,他們很少關注前端,而前端在架構設計中往往被忽視。通常在微服務項目中,后端與它們的數據庫被很好地模塊化,但只有一個整體前端。
在最好的情況下,他們考慮用最熱門的單頁面應用(React、Angular、Vue)其中之一來開發獨體前端。這種方法的主要問題是,前端的單體架構和后端單體架構一樣糟糕,正如我前一篇文章所述。
另外,當前端因為瀏覽器的變化而需要更新時,它就需要一個大的更新(這就是為什么那么多公司仍然使用過時的 Angular 1 框架的原因)。網絡是簡單的,但非常強大,并天生提供了穿透力。開發基于單頁面應用的微前端有很多方法:使用 iFrame、Web 組件或借助于(Angular/React)元素。
??
??
4.?持續交付
微服務架構的關鍵賣點之一是每個微服務都可以獨立部署。如果你有一個系統,例如 100 個微服務,并且只需要更改一個微服務,那么你可以只更新一個微服務,而不需要修改其他 99 個微服務。但是,在沒有自動化的情況下獨立部署 100 個微服務(DevOps、CI/CD)是一項艱巨的任務。
要充分利用微服務的這一特性,需要 CI/CD 和 DevOps。使用沒有 CI/CD、DevOps 的微服務架構,自動化就像購買最新的保時捷,然后用手剎去駕駛它。難怪微服務專家 Martin Fowler 將 CI/CD 列為使用微服務架構的三個先決條件之一。
?
??
5. 可觀察性
微服務架構的主要缺點之一是,軟件開發變得簡單,而犧牲了運維。使用單體架構,監視應用程序要簡單得多。但是許多微服務在容器上運行,整個系統的可觀察性變得非常重要和復雜。甚至日志記錄也變得很復雜,要將來自許多容器 / 機器的日志聚集到一個中心位置。
幸運的是,市場上已經有很多企業級的解決方案了。例如,ELK/Splunk 提供微服務的日志記錄。Prometheus/App Dynamics 提供工業級監控。微服務世界中另一個非常重要的可觀察性工具是 Tracing。通常,對一個微服務的一個 API 請求會導致對其他微服務的幾個級聯調用。要分析微服務系統的延遲,需要測量每個微服務的延遲。Zipkin/Jaeger 為微服務提供了出色的跟蹤支持。
?
??
6. 統一技術棧
微服務架構告訴我們,對于一個微服務,采用最適合該微服務的編程語言和框架。這種說法不能照字面理解。有時,一個微服務可能需要一個新的技術棧,例如 CPU 密集 / 高性能任務,可能會選擇如 c++ /Rust 之類的編程語言。如果微服務與機器學習一起工作,那么 Python 可能是更好的選擇。
但是在沒有任何理由的情況下使用不同的編程語言 / 框架會導致過多的編程語言和框架而沒有任何實際的好處。思考這么一個應用場景,一個微服務是使用 Spring Boot + Kotlin+ React + MySQL 開發的,另一個用的是 JakartaEE + Java + Angular + PostgreSQL,下一個是 Scala + Play Framework + VueJS + Oracle,則需要大量的工作去維持這些不同的編程語言、數據庫、框架,而沒有太多的收益。
?
??
7. 異步通信
微服務架構中最具挑戰性的設計決策之一是服務之間如何通信和共享數據。當每個微服務都有自己的數據存儲時,這一點就更為重要了。通常,一個微服務可以單獨存在,但是它不能單獨實現所有的業務目標。
所有微服務為了實現業務目標而在一起工作,為了在一起工作,它們需要交換數據或觸發其他微服務來執行任務。在微服務之間進行通信的最簡單和最常見的方式是通過同步的 REST API,這是一種實用但臨時的解決方案。如果服務 A 同步調用服務 B,服務 B 同步調用服務 C,服務 C 同步調用服務 D,那么延遲就會增加。
此外,由于微服務主要是分布式系統,它們有可能會失敗。通常,同步微服務會導致級聯失敗,即一個服務的失敗會導致其他服務的失敗。微服務之間的同步通信也導致了微服務之間的緊密耦合。對于長期解決方案,微服務應該異步通信。微服務之間的異步通信有很多方式:通過消息隊列,例如 Kafka,通過異步的 REST(ATOM)或 CQRS。
?
??
8. 微服務優先
許多專家認為,對于新項目,最好從松耦合的單體架構開始,因為微服務架構需要大量的初始工作來設置運維。在他們看來,一旦項目變得足夠成熟,“漂亮的”設計就可以很容易地轉化為微服務。然而,在我看來,這種方法在大多數情況下都會失敗。
實際上,實體內部的模塊將是緊耦合的,這將使其很難轉換成微服務。而且,一旦應用程序投入生產,在不破壞應用程序的情況下將其轉換為微服務將變得更加困難。因此,我的建議是,如果最終有使用微服務架構的計劃,那么就從微服務開始。
?
??
9. 基礎設施優于類庫
在微服務軟件開發的早期,Netflix 主要使用 Java 編程來開發微服務。他們還開發了許多類庫(Netflix 的 OSS 棧,包括 Hystrix、Zuul)。許多公司通過 Netflix 跟進并開始使用 Netflix OSS。
后來,許多公司(包括 Netflix)發現,Java 實際上并不是開發微服務的語言,因為它體積龐大,而且冷啟動問題嚴重。Netflix 后來轉向 Polyglot 微服務范式,并決定不再進一步開發 Netflix OSS,這導致了追隨者公司陷入困境。因此,與其大量投資于特定語言的類庫(如基于 Java 的 Netflix OSS),不如使用框架(如服務網格、API 網關)。
?
??
10. 組織考慮
大約 50 年前(1967 年),Melvin Conway 觀察到公司的軟件架構受到組織結構的限制(Conway 定律)。盡管這一觀察發現已有 50 年歷史,但麻省理工學院(MIT)和哈佛商學院(Harvard Business School)最近發現,這一法則在當今仍然有效。如果一個組織計劃開發微服務架構,那么它應該使團隊規模更為恰當(兩個“美國”比薩團隊:7±2 人)。
此外,團隊應該是跨職能的,最好有前端 / 后端開發人員、運維工程師和測試人員。微服務架構只有在高層管理者也相應地改變他們的觀點和愿景的情況下才能發揮作用。
有道無術,術可成;有術無道,止于術
歡迎大家關注Java之道公眾號
好文章,我在看??
總結
以上是生活随笔為你收集整理的微服务开发的 10 个最佳实践的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: hdu 1087 Super Jum
- 下一篇: hdu 2191 悼念512汶川大地震遇