好的微服務,有兩個最重要的概念:高內聚與低耦合。架構
其實不僅有微服務,軟件設計的追求也在此,對於這個概念,相信在學習開發的初始階段就會據說,但並非全部人據說後就會理解,咱們在研發經驗逐步累積到必定程度後,就會真正想清楚這兩個概念背後的含義。微服務
把相關的行爲彙集到一塊兒,把不相關的行爲放在別處。這個說法與SRP很像,由於若是你想要改變某個行爲的話,最好可以只在一個地方進行修改,而後就能夠儘快發佈。學習
好的微服務要基於這一點,將相關的業務集中到一個微服務中實現。要作到準確內聚,就要找到需求邊界,而這個邊界有多是慢慢摸索出來的。測試
若是你的微服務作到了低耦合,那麼修改一個服務就不須要修改另外一個服務。spa
那麼什麼會致使高耦合呢?一個典型的錯誤是,在作服務之間的集成時,修改一個服務會致使其消費者也進行修改。一個號的服務應該儘量少的知道與之協做的那些服務的信息,應該儘可能限制服務之間不一樣形式的調用,過分通訊會致使高耦合。這個說法與Law of Demeter很像,其實,設計六大原則就是將高內聚低耦合完整的抽象出來了。設計
任何一個特性的行業業務,都包含着多個上下文邊界,所謂的上下文邊界,就是各個業務模塊之間的交互點,在程序中就是模塊的接口。 接口
一個業務模塊,正常來講有兩部分模型(實體)組成,一部分不須要與外部通訊,另外一部分則須要。
讓咱們來看一個具體的例子:開發
圖中,財務與倉庫兩個模塊是兩個獨立的界限上下文,他們都有明確的對外接口(存貨報告、工資單),也有隻須要本身知道的細節(剷車、計算器)。軟件
財務模塊不須要知道倉庫模塊的內部細節,但它須要知道庫存水平,以便於更新帳戶,爲了算出公司的估值,須要知道庫存信息。程序
在日常,設計者會將庫存信息做爲對外接口的模型,將其變成模塊間的共享模型,這種作法實際上是不太可取的,不要盲目的把庫存信息內容所有都暴露出去。倉庫模塊應該設計暴露給財務模塊的庫存信息(庫存項),有時候,同一個名字在不一樣的上下文中有着徹底不一樣的含義。
總結起來就是,應該共享特定的模型,而不該該共享內部模型。
作到上述事情,能夠大量避免高耦合,並且在明確了各個邊界,能夠實現高內聚。因此,一旦你發現了業務模塊的邊界和模型,一旦要對其進行建模,同時使用共享模型和內部模型。
對於一個新系統或新業務領域來講,能夠先使用一段時間單體架構,由於若是服務之間的邊界搞錯了,會付出很大的代價,因此最好可以等到系統穩定下來、熟悉業務後,在對單體架構進行微服務的拆分。
當你在思考業務邊界時,不該該從共享數據的角度來考慮,而應該從這些業務邊界可以提供的功能來考慮。好比,倉庫的一個功能是提供當前的庫存清單,財務可以提供月末帳目或者爲一個員工建立工資單。爲了實現這些功能,可能須要交換存儲信息的模型。若是隻考慮模型,你有可能只設計出一個貧血服務(只基於CRUD的服務)。
新項目開始階段,你會識別出一些粗顆粒度的業務邊界,而這些業務中可能會包含另外一些業務。好比,能夠把庫存模塊分解爲不一樣的子模塊:訂單模塊,庫存管理模塊,貨物接收等。
在被外部服務調用時,這些嵌套的子模塊對外部是不可見的。例如:
但有時候你會認爲,高層次的業務模塊不該該被顯示地建模成一個服務,應該把子模塊拆分出來:
一般很難說那種規則更合理,可是應該根據組織結構來決定,若是訂單、庫存等由不一樣的團隊或者我的維護,那麼他們大概都會但願這些服務是頂層服務。單若是他們由一個團隊或我的來維護,那麼使用嵌套結構會更合理。
另外一種傾向於嵌套方法的緣由是,它可使得架構更方便的測試,當測試倉庫的消費者時,不須要對倉庫中的每一個服務進行打樁,只專一於粗粒度的API測試便可。
基於行業業務的軟件建模不該該止步於業務邊界的拆分,在組織內部共享的那麼相同的術語和想法,也應該被反映到服務的接口上。溝通、通訊形式在整個組織範圍內都很是重要。
總結了什麼是好的服務,以及如何作到高內聚與低耦合。
而且聊到了在進行微服務的拆分時,應該先基於業務功能去拆分,這樣天然而然會得出一個正確的共享模型,然後,對服務的拆分顆粒度進行了建議。
若想進一步瞭解如何準確的拆分業務功能,能夠讀一讀Eric Evans的《領域驅動設計》一書。