模塊化還是微服務-為什麼說大部分團隊微服務化都走入了陷阱
在服務內部實現良好的模塊化。 下面我們來探討這種替代方案,並展示它與微服務的關係。
為了模塊化的微服務
強封裝:隱藏組件內部的實現細節,讓不同部件之間的耦合度較低。團隊可以在系統的解耦的部分單獨工作。
明確定義的介面:我們無法隱藏所有內容(否則系統將無法做任何有意義的事情),因此組件之間必須有定義良好且穩定的 API。組件可以被符合介面規範的任何實現所替代.
顯式依賴:具有模塊化系統意味著不同的組件必須一起工作,需要有一個表達他們的關係的好方法。
這些原則大部分情況是可以通過微服務來實現,一個服務只要有公開明確定義的介面(通常為 REST API),就可以以任何方式實現微服務。實施細節對服務來說是內部問題,可以在沒有系統範圍的影響或協調的情況下進行更改。微伺服器之間的依賴關係在開發時通常不是很明確,從而導致可能的運行時服務編排失敗。
因此,微服務實現了重要的模塊化原則,帶來實質效益:
團隊可以獨立工作和規模不同。
微服務小而專註,降低複雜度。
服務可以在內部進行更改或更換,而不影響全局。
儘管如此,從一個單一的(雖然輕微肥胖的)應用程序進入到一個分布式的微服務系統,這帶來了巨大管理複雜性。突然間,您需要持續部署許多不同的(可能是容器化的)服務。新的關注點開始出現:服務發現、分布式日誌記錄、跟蹤等。你現在更容易出分布式服務各種錯誤。介面和配置管理的版本控制也成為新的需要關注的地方,問題的列表還會繼續增長。(高可用架構小編註:以學習「新技術」為己任的工程師未必會這麼想)
模塊化的替代方案
這是否意味著我們要麼必須維護混亂的單體服務,要麼就需要淹沒在微觀服務的複雜性之間?其實,模塊化也可以通過其他方式實現,我們只要在開發過程中有效地制定和實現邊界,也可以通過創建一個結構良好的單體應用來實現這一點。而且如果只考慮模塊化,我們可以從已有的編程語言和開發工具比如 IDE 中獲得很多開發的便利,以實現模塊化的原則。
在 Java 中,有幾個可以幫助應用模塊化的系統。 OSGi 是最知名的,隨著 Java 9 的發布,本地模塊系統被添加到 Java 平台本身。模塊現在是 Java 語言及平台的一部分,作為一級結構,Java 模塊可以表達對其他模塊的依賴關係,並在強制封裝實現類的同時公開導出介面。甚至 Java 平台本身(一個巨大的代碼庫)已經使用新的 Java 模塊系統進行了模塊化。在即將出版的 Java 9 Modularity 一書中,您可以了解使用 Java 9 來實現模塊化開發的更多信息。
其他語言提供類似的機制。例如,JavaScript 獲得了 ES2015 的模塊系統。在此之前,Node.js 已經提供了一個用於 JavaScript 後端的非標準模塊系統。然而,作為一種動態語言,JavaScript 對於實現模塊之間的介面(類型)和封裝有較弱的支持。您可以考慮在 JavaScript之上使用 TypeScript 來再次獲得這一優勢。
Microsoft 的 .Net 框架確實具有像 Java 這樣的強類型,但是它沒有類似 Java 即將到來的模塊系統,也沒有程序集之間的顯式依賴。儘管如此,通過使用 .Net Core 中標準化的 Inversion-of-Control 模式和通過創建邏輯相關的程序集,可以實現良好的模塊化架構。即使 C++ 也正在考慮在將來的版本中添加模塊系統。
綜上所述,許多語言正對模塊化表示重視,這本身就是一個驚人的發展。
當你使用開發平台的模塊化功能時,就可以實現微服務相同的模塊化優勢。基本上,模塊系統越好,在開發過程中獲得的幫助越多。不同的團隊可以在不同的部分工作,只要明確定義團隊之間交互的介面。
在部署時,所有模塊組合在一個單獨的單元中部署,這樣可以防止微服務開發和管理帶來的巨大複雜性和成本。當然,這也意味著您不能在不同的技術棧上構建每個模塊。但是貴公司真的打算好使用異構技術棧來搭建同一個系統嗎?
設計模塊的哲學
設計模塊需要與設計微服務一樣保證設計的嚴謹性。模塊應該對域的單個有邊界的上下文建模。選擇微服務邊界是一個具有重要架構意義的決策,選擇錯誤時會產生昂貴的後果。模塊的邊界更易於更改,它的重構通常由類型系統和編譯器支持。重新劃分微服務需要涉及到大量的開發人員之間的通信,以便不會摧毀線上系統。老實說,你需要經歷多少次嘗試才能得到微服務合適的界限?
在許多方面,靜態類型語言中,模塊為明確定義的介面提供了更好的結構支持。通過另一個模塊公開的類型化介面調用方法比在另一個微伺服器上調用 REST 介面更加魯棒。REST + JSON 是無處不在的,但是在沒有(編譯器檢查)模式的情況下,它不是良好類型互操作性的標誌。補充一點,通過網路進行(反)序列化仍然不是沒有成本的。此外,許多模塊系統允許您表達對其他模塊的依賴。當試圖違反這些依賴關係時,模塊系統將不允許如此。微伺服器之間的依賴關係只在運行時實現,導致難以調試系統。
模塊也是代碼所有權的自然單元。團隊可以負責系統中的一個或多個模塊。與其他團隊分享的唯一的東西就是模塊的公共 API。在運行時,相比微服務來講,模塊之間的隔離較少。畢竟,一切仍然運行在相同的進程中。
沒有任何理由,在單體應用中,模塊不能像微伺服器一樣擁有它的數據。模塊化應用程序之間通過定義良好的介面或模塊之間的消息來共享數據,而不是通過共享數據存儲,與微服務的巨大差異在於一切都在同一個進程中。最終的一致性問題不應低估,使用模塊,最終的一致性可以是一個策略的選擇。或者,您只需「邏輯」地將數據分開存儲在同一數據存儲區中,並且仍然使用跨域事務。對於微服務,則沒有選擇:最終的一致性是必須的,您需要適應這點。
微服務什麼時候適合您的組織?
那麼什麼時候應該轉向微伺服器?上面描述的都是如何通過模塊化來解決複雜性。對於這一點,微服務和模塊化應用都可以做到。但到各有不同的挑戰。
當您的組織處於 Google 或 Netflix 規模時,擁抱微服務是完全有道理的。您有能力建立自己的平台和工具包,而且工程師的數量也不允許任何單體服務的可能。但是大多數組織都沒有在這個規模下運作。即使你認為你的組織有一天將成為一個十億美元的獨角獸,開始使用模塊化也不會有太多的危害。
微服務另一個好的理由是,不同的服務可以使用不同的技術棧。但是前提是你必須擁有足夠規模來吸引開發人員跨越這些不同的棧,並保持這些平台的運行。
微服務還可以獨立部署系統的不同部分,這在大多數模塊化系統中很難(甚至是不可能)。隔離部署增加了系統的彈性和容錯能力。此外,對於每個微伺服器,伸縮能力可以不同。可以部署不同的微服務來匹配硬體。模塊化整體式服務也可以水平縮放,但您需要將所有模塊放在一起。儘管在實踐中,你可以用這種方法得到很多好處,但是這可能並不是最好的方式。
結論
跟所有架構思路相似,最好的選擇是找到一個折衷的位置。兩種方法都有適合的地方,需要根據環境,組織和應用程序本身來做選擇。
在大部分情況何不考慮從模塊化單體應用開始?您隨時可以選擇轉移至微服務。如果您已經有明確的模塊界限,您也不必手術肢解您的單體應用,它甚至不是一個排他選擇:您也可以在微服務內部使用模塊。因此也許問題就變成了,為什麼微服務必須「微」?
即使從模塊化應用程序中脫離出來,服務也不必變「微」才可維護。在服務中應用模塊化的原則使他們能夠超越通常微服務那種複雜性。在這裡有模塊化和微服務共存的地方。通過減少您的架構中的服務數量,可以實現實際的成本節約。模塊可以幫助構建和擴展服務,就像它們可以幫助構建單個整體式應用程序一樣。
如果您希望獲得模塊化好處,請確保不要欺騙自己進入僅限微服務的心態。探索您最喜愛的技術堆棧中模塊化功能或框架,就可以獲得模塊化設計的支持,而不必僅僅依靠約定來避免「意麵一樣的代碼」。仔細考慮是否需要引入微服務帶來的複雜性,有時你需要(但往往可以)找到更好的方法。
Sander Mak 是一名荷蘭 Luminis 的研究員。 在 Luminis,他開發了系列模塊化和可擴展的軟體,大部分是基於 JVM 的。 他是即將出版的 O"Reilly Java 9 Modularity 的作者,他喜歡通過博客 http://branchandbound.net來分享知識。 可以通過 Twitter @Sander_Mak 聯繫。
TAG:高可用架構 |
※大部分公司並不需要微服務
※為什麼集成微服務是一種更靈活的微服務架構方法?
※沈劍聊微服務:先做好你的服務拆分
※恆豐銀行微服務架構優化實踐
※三分鐘讀懂TT貓分散式、微服務和集群之路
※人工智慧應用微服務化:從模型到線上系統搭建的最佳實踐
※阿里雲基於 Go 的微服務架構分享
※微服務的安全挑戰和處理
※微服務應用容器化場景中常見問題總結
※網易企業服務:奇碩基於網易雲的微服務與大數據實戰
※業務視角下的微服務架構設計實例
※B站高性能微服務架構
※微服务简介——微服务从设计到部署
※輕量級微服務架構及最佳部署
※如何快速搭建一個微服務架構?
※Spring技術佈道師眼中的微服務:事件驅動型微服務詳解
※微服務架構中 API 的開發與治理
※實施微服務應該具備哪些先決條件?
※從SOA到微服務