模塊化還是微服務?
我們的業務由一個大型應用轉向微服務的時候,除了很好展示漂亮的PPT,提升KPI之外,實際操作時將整個業務切成微型服務似乎也不費吹灰之力。但這種方法真的是我們的最佳選擇嗎?確實,維護凌亂的單片應用程序有許多缺點。但是有一個令人信服的替代方案經常被忽視:模塊化應用程序開發。 在本文中,我們將探討這種替代方案的含義,并展示它與構建微服務的關系。
什么是微服務?
微服務現在越來越火爆,但是到底什么是微服務?Sam Newman在《構建微服務》中提供了對微服務的簡潔定義是:“微服務是一種小型,自主的服務,且相互之間可以協同工作。”
在《微服務架構》這本書中,作者Mike Amundsen,Irakli Nadareishvili,Ronnie Mitra和Matt McLarty通過概述微服務應用程序共享的特征說明微服務的細節:
- 體積小
- 啟用消息
- 以上下文為界
- 自主開發
- 可獨立部署
- 分散
- 使用自動化流程構建和發布
一、模塊化的微服務
“通過微服務,我們最終可以讓團隊獨立工作”,或者“我們的應用太復雜,這讓我們放慢腳步”。這些表達只是導致開發團隊走上微服務道路的眾多原因中的一小部分。另一個問題是需要可擴展性和彈性。開發人員似乎總是渴望的是系統設計和開發的模塊化方法。
軟件開發中的模塊化可以歸結為三個指導原則:
1.1,強大的封裝
隱藏組件內部的實現細節,導致不同部件之間的低耦合。團隊可以在系統的分離部分上獨立工作。
1.2,定義良好的接口
您無法隱藏所有內容(否則您的系統不會做任何有意義的事情),因此組件之間定義良好且穩定的API是必須的。組件可以由符合接口規范的任何實現替換。
1.3,顯式依賴
擁有模塊化系統意味著不同的組件必須協同工作。你最好有一種表達(和驗證)他們關系的好方法。
上述原則可以通過微服務實現。而微服務可以用任何方式實現,只要它為其他服務公開定義良好的接口(通常是REST API)即可。其實施細節是服務的內部細節,可以在沒有全系統影響或協調的情況下進行更改。但微服務之間的依賴關系在開發時通常不是很明確,導致運行時可能的服務編排失敗。
因此,微服務實現了重要的模塊化原則,從而帶來了實實在在的好處:
- 團隊可以獨立工作和擴展。
- 微服務規模小,重點突出,降低了復雜性。
- 服務可在內部更改或替換,而不會產生全局影響。
當我們從一個(雖然有點臃腫)應用程序轉變為分布式微服務系統,這其實帶來了大量的操作復雜性。突然間,您需要不斷部署許多不同的(可能是容器化的)服務。出現了新的問題:服務發現,分布式日志記錄,跟蹤等。現在更容易出現分布式計算下的錯誤了。接口和配置管理的版本控制也會成為一個主要問題。而且問題清單會一直增長下去。
事實證明,微服務之間的連接與所有單個微服務的組合業務邏輯一樣復雜。雖然整體代碼庫中的“意大利面條代碼”存在問題,但在這兩者之間存在網絡邊界會使這些糾纏問題升級為徹頭徹尾的痛苦。
ps:意大利面條代碼是非結構化和難以維護的源代碼的貶義詞。可能由多種因素引起,例如易變的項目要求,缺乏編程風格規則以及能力或經驗不足。
二、模塊化替代方案
這是否意味著我們要么被降級為凌亂的大型應用,還是必須淹沒在微服務瘋狂的復雜性中?模塊化也可以通過其他方式實現。重要的是我們可以在開發過程中有效地繪制和強制執行邊界。但我們也可以通過創建一個結構良好的大型應用來實現這一目標。當然,這意味著我們往往會從編程語言和開發工具中獲得幫助,以實施模塊化原則。
例如,在Java中,有幾個模塊系統可以幫助構建應用程序。 OSGi是最著名的一個,但隨著Java 9的發布,Java平臺本身就添加了一個本機模塊系統。模塊這種特性作為一流的結構現在是語言和平臺的一部分。 Java模塊可以表達對其他模塊的依賴關系,并在強大地封裝實現類的同時公開導出接口。甚至Java平臺本身(一個龐大的代碼庫)也使用新的Java模塊系統進行了模塊化。
其他語言提供類似的機制。例如,JavaScript從ES2015開始獲得了一個模塊系統。在此之前,Node.js已經為JavaScript后端提供了一個非標準的模塊系統。但是,作為一種動態語言,JavaScript對實施接口(類型)和模塊之間的封裝的支持較弱。可以考慮在JavaScript之上使用TypeScript再次獲得此優勢。微軟的.Net Framework確實具有類似Java的強類型,但它在強大的封裝和程序集之間的顯式依賴性方面沒有直接等同于Java即將推出的模塊系統。盡管如此,通過使用在.Net Core中標準化的Inversion-of-Control模式以及通過創建邏輯相關的程序集,可以實現良好的模塊化體系結構。甚至C ++也在考慮在未來的版本中增加一個模塊系統。許多語言對模塊化越來越感興趣,模塊化本身就是一個引人注目的發展。
當我們有意識地使用開發平臺的模塊化功能時,您可以實現我們之前歸因于微服務的相同模塊化優勢。從本質上講,模塊系統越好,在開發過程中獲得的幫助就越多。不同的團隊可以在不同的部分上工作,其中只有明確定義的接口才是團隊之間的接觸點。但是,在部署時,模塊在一個部署單元中聚集在一起。這樣,您可以防止與遷移到微服務開發和管理相關的實質復雜性和成本。當然,這意味著無法在不同的技術棧上構建每個模塊,不過對大多數公司和開發團隊而言,真的能掌控好多個技術棧?
三、設計模塊
創建好的模塊需要與創建良好的微服務相同的設計要求。模塊應該模擬業務域的單個有界上下文。選擇微服務邊界是一項架構上重要的決策,如果做錯了,會產生代價高昂的后果。而模塊化應用程序中的模塊邊界更容易更改。類型系統和編譯器通常支持跨模塊的重構。重新劃分微服務邊界需要進行大量的人際交流,以免在運行時爆炸。
在許多方面,靜態類型語言中的模塊為定義良好的接口提供了更好的結構。通過另一個模塊公開的類型化接口調用方法對于更改比在另一個微服務上調用REST端點要強大得多。 REST + JSON無處不在,但在沒有(編譯器檢查的)模式的情況下,它不是良好類型的互操作性的標志。更重要的是,許多模塊系統允許表達對其他模塊的依賴性,當違反這些依賴項時,模塊系統會禁止這樣做,至少會有個明確的提示,但微服務之間的依賴關系僅在運行時實現,導致難以調試的系統。
模塊也是代碼所有權的自然單位。團隊可以負責系統中的一個或多個模塊。與其他團隊共享的唯一事情是其模塊的公共API。在運行時,與微服務相比,模塊之間的隔離更少。畢竟,一切仍然在同一個進程中運行。
沒有理由為什么單塊中的模塊不能像一個好的微服務那樣擁有它的數據。然后,模塊化應用程序內的共享可以通過模塊之間定義良好的接口或消息進行,而不是通過共享數據存儲區。微服務的最大區別在于一切都在進行中。不應低估最終的一致性問題。通過模塊,最終的一致性可以是一個深思熟慮的戰略選擇,而不是無法避免的選擇。對于微服務,沒有選擇:只能選擇最終的一致性。
四、微服務什么時候適合您的組織?
那么什么時候應該轉向微服務?到目前為止,我們主要專注于通過模塊化來解決復雜性問題。為此,微服務和模塊化應用程序都可以。但除了迄今為止提出的挑戰之外,還有不同的挑戰。
-
當公司有Google或Netflix的規模時,完全有理由接受微服務。這意味著,有能力構建自己的平臺和工具包,并且工程師的數量也已經足夠。但是大多數組織并沒有以這種規模運作。哪怕是公司有一天會成為價值10億美元的獨角獸,從模塊化的大型應用開始也不會造成什么問題。
-
啟動單獨的微服務的另一個好理由是,不同的服務本質上更適合于不同的技術棧。也就是鎖,必須擁有足夠的規模來吸引這些不同的技術棧中的人才,并保持這些平臺的正常運行。
-
微服務還可以獨立部署系統的不同部分,這在大多數模塊化平臺中很難(甚至不可能)。隔離部署增加了系統的彈性和容錯能力。此外,縮放特性對于每個微服務可以是不同的。可以將不同的微服務部署到匹配的硬件上。模塊化的整體也可以水平縮放,但是更細微的就很困難。但是在一般實踐中,模塊化這種方式可以支持很久的業務發展。
五、結論
如何選擇?其實取決于環境,組織和應用程序本身。我們可以從模塊化應用程序開始,然后隨時選擇轉移到微服務,還可以使用模塊在內部構建微服務。
如果我們追求模塊化的好處,請確保我們不要落入只能使用微服務的思維模式。盡可能的在最喜歡或者最擅長的技術棧使用內置的模塊化功能或框架。
作者:享學課堂Mark
轉載請注明出處。