微服務:如何拆分服務?
在微服務的落地中,第一步就需要進行微服務的拆分,服務的拆分很困難也很重要,本文就講講怎么進行服務的拆分。
技術發展到現在,還沒有一個具體的,設計完善的標準方法來完成服務的拆分,服務的拆分是一門技術更是一門藝術。
對于服務的拆分,有兩種情況 :
1、從零開始開發新的產品,采用微服務架構,進行服務拆分。
2、將現有的單體架構的產品重構成微服務架構,進行服務拆分。
如果做的是 ToB 業務,最終在企業內部私有化部署落地,那么在大多數的場景下,微服務拆分后系統的復雜度和引發的新問題會大于帶來的好處。
隨著業務的發展,產品需要進行 SaaS 化改造,團隊也引入多種技術棧,進行微服務的拆分應該就是勢在必行了。所以下面介紹的是怎樣將現有單體架構拆分成微服務。
服務的拆分不是看代碼量或是工程的大小,而是要根據當前業務的情況、團隊的情況綜合考慮,還是拿零代碼平臺作為例子。
零代碼平臺中有菜單、流程、表單、頁面等模型,這些模型各自都能獨立成一個服務,但前期為了快速交付,可以都放到一個工程中,但在代碼組織和架構層面,為了后續的拆分,可以在邏輯和上進行隔離,物理文件可以用目錄來區分,整體還是在一個大的工程中,如下圖:
服務的拆分的一個最大的作用就是解耦,但并不是說一定要拆開才是解耦,在一個工程中,合理地使用面向對象的一些原則,比如依賴倒置、接口隔離等,也能做到解耦。
平臺的功能在不斷地迭代,現在需要添加 BI 模塊,整個架構也調整為支持多租戶模式,同時也需要開發應用商城,將零代碼平臺推上互聯網,構建一個應用生態,用戶可以直接安裝應用或者將自己的應用發布到應用商城中。這里添加的 BI 和應用商城就可以作為一個單獨的服務,而原來的整個零代碼平臺可以先作為一個大的服務存在,修改后的架構圖如下:
上面的例子是從全局的維度來考慮應該怎樣去拆分,不一定對,但以我目前的認知和現有的場景來看,我認為是適合的。
具體到一個特定的服務,最基本的要求是具有能訪問的 API , 并且可以獨立部署,至于數據庫是獨立還是跟其他服務共用,也是需要具體問題具體分析,如果存在較多的跨服務的查詢操作,建議多服務共用一個數據庫。
服務與服務之間需要做到高內聚低耦合,如果因為其他服務的變更導致需要頻繁更新你的服務,或者說你的服務的一個小的改動會導致很多其他的服務要進行同步修改,那么說明服務之間的耦合性太高,拆分了享受不到微服務帶來的好處,反倒是將缺點無限放大了。所以在拆分服務時要遵循兩個原則:
1、通用功能,使用共享庫,比如工具類,提取成 NuGet 包或者 Maven 包,在服務中進行引用;
2、業務相關的公共部分,使用單獨的服務,提供 API 的方式供其他服務調用。
每個服務都可以使用不同的架構和技術棧來實現,有一種推薦的做法就是使用六邊形架構,六邊形架構在一些 DDD 的書籍和微服務的書籍中都有提到,下面是一張六邊形架構的架構圖:
六邊形架構也稱為端口適配器架構,可以替代傳統的三層,解決三層架構的一些弊端。端口和適配器都分為入站和出站。
- 入站適配器:通常就是對外的 RestAPI,通過調用入站端口來處理外部的請求,也可以是消息隊列的消費者,進行一些事件的監聽,來處理異步業務,當接收到消息時也是調用入站端口來進行處理。
- 入站端口:業務服務對外暴露的公有方法。
- 出站適配器:出站適配器實現出站接口,調用外部的服務來實現一個完整的業務邏輯,出站適配器也可以是消息隊列的生產者。
- 出站端口:出站端口是一組方法的接口定義,提供一種規范,供出站適配器來實現。
舉一個例子:在零代碼平臺中,表單上拖一個控件保存后,最后的效果是列表上也會有這一列了,而表單和列表屬于兩個獨立的服務,按照六邊形架構,調用關系如下圖:
六邊形架構一個最大的好處就是將業務邏輯和適配器中包含的展示層和數據訪問層的邏輯分離開,實現了解耦。
學習微服務,我覺得有必要同時學習領域驅動開發(DDD),微服務是一種架構風格,DDD 是具體的架構設計方法,互相配合能夠更好地落地,因為:
1、DDD 中子域和限界上下文的概念可以對應到微服務中的服務。
2、微服務中一個服務可以由一個團隊進行開發,DDD 的一個領域模型也是建議由一個獨立的團隊負責。
進行服務拆分后,之前在一個進程內就能完成的事情,現在需要在進程間進行通信了,有關進程間通信后面再繼續分享。
零代碼現在越來越火熱,通過高度的抽象,將基礎設施、重復性的工作作為平臺本身的能力提供,讓用戶只用關注業務,這其實也是另一個層面的解耦和拆分。