良好的微服務設計可使後期的升級維護更加輕鬆,不然將會使人很是頭疼。數據庫
下面幾個設計原則強烈建議採用:服務器
低耦合網絡
這三大原則是面向對象設計中的核心,一樣適用於微服務設計。架構
每一個微服務只應擔負一個職責。
好比一個微服務中有兩大功能:異步
把它們放在一塊兒看起來問題不大,由於使用的技術相同、功能和數據上會有比較緊密的聯繫,在組織結構上,一般是由同一個開發小組負責。微服務
可是,這會形成兩個功能有大量的代碼耦合。測試
時間長了以後,會帶來和單體架構同樣的問題,維護難、測試難、部署難 ……spa
因此,按照「單一職責」原則,應該分爲兩個微服務。設計
關係緊密的行爲應放在一塊兒。
好比有2個微服務:對象
「訂單金額統計」 服務須要請求 「訂單管理」 服務,以獲取所需數據。
例如價格、稅、服務費 ……
剛開始一切安好,但忽然某一天上頭增長稅種了,須要更改新的計算規則。
那麼,訂單服務就要提供新的數據,金額統計服務也須要更改計算方式。
也就是說,每次變動基本都須要兩個服務一塊兒改,是緊耦合的。
由於訂單金額統計服務的邏輯只與訂單相關,因此應該併入訂單服務。
把緊密相關的行爲放在一塊兒,實現高內聚。
一個服務的變動不要影響其餘服務。
此原則涉及到多個方面。
好比上一節 「高內聚」 中,把金額統計服務併入了訂單管理服務,那麼,以前金額統計服務中的 「統計接口」 還須要對外暴露嗎?
如今已是訂單服務的內部功能了,統計結果能夠做爲訂單對象中的數據,因此無需對外暴露,防止誤操做和形成沒必要要的耦合關係。
共享代碼的確很是方便,可是會形成底層代碼關聯度太強。
對於之後的升級很是不便,例如某個服務想把語言版本升級,但共享庫使用的是低版本,其中某些用法在高版本中是過時的,這就很尷尬了。
想要完美的避免也是不現實的,只能儘可能規避。
例如不共享,各服務從新造輪子,這樣服務之間就有邊界了。
但這個方式只適用於須要共享的庫是很是穩定的,不怎麼須要改了,不然的話相關服務都須要改。
再好比把共享庫的粒度縮小,避免造成功能特別全的大庫。
大庫必然致使被引用的範圍很是廣,影響面大。
若是粒度很小的話,涉及的服務也就少。
例如用戶服務有一個獲取用戶詳情的接口,返回用戶全部信息。
購物車服務獲取用戶信息時,就會拿到很全的數據,例如包括支付信息。
這是不必的,只須要返回用戶的基本屬性便可。
特殊的屬性應經過另外的接口提供。
過分暴露會增長服務間的耦合度。
一個服務想獲取另外一個服務的數據時,只應該經過接口,而不是直接從對方的數據庫中拿。
不然,這種數據層面的耦合會帶來噩夢。
好比訂單服務建立訂單的時候須要調用不少其餘服務,例如用戶、商品、支付、庫存、物流。
直接同步調用各個服務的接口嗎?
不現實,若是其中有一個服務接口調用失敗,那麼建立訂單就失敗了。
最好使用事件驅動的異步調用。
同步調用會產生網絡的阻塞,對被調用服務的可用性要求極高,因此要慎重使用。
服務設計得很好,但若是硬件部署沒有規劃好,同樣很是痛苦。
例如兩個服務部署在一臺服務器上,服務B 很是消耗資源,那麼服務A可能就無法用了。
因此,不能忽略硬件這個關鍵點,要根據各個服務的特色作好均衡部署。
例如 Java RMI 作遠程調用不錯,但它是平臺特性,要求服務雙方都用一套技術,這種高耦合就不如平臺獨立的 REST 更自由了。