憑啥修改代碼的是我?原來這就是耦合!
你有沒有遇到過這樣的場景?
- 硬件升級,要換一臺高配機器;
- 網絡重新規劃,若干服務器要調整機架;
- 服務器當機,要重新部署恢復服務;
- …
更具體的,如上圖:數據庫換了一個ip,此時往往連接此數據庫的上游需要修改配置重啟,如果數據庫有很多上游調用方,改配置重啟的調用方會很多,每次換ip的成本往往很高,成為大家共性的痛點。
由A的調整(數據庫換ip),配合修改和調整的卻是BCDE(改配置重啟),BCDE內心非常的郁悶:明明換ip的是你,憑什么配合重啟的卻是我?
根本上,這是一個“架構耦合”的問題,是一個架構設計上“反向依賴”的問題,本文將討論的是架構設計中常見的“反向依賴”的設計,以及對應的優化方案,希望對大伙有所啟示。
如何尋找不合理的“反向依賴”耦合?
方法論:變動方是A,配合方卻是BCDE。
(或者說需求方是A,改動方卻是BCDE。)
畫外音:想想“換IP的是你,配合重啟的卻是我”更好記憶。
如果系統中經常出現了這類情況,就是“反向依賴”的特征,往往架構上有優化的空間。
場景1:公共庫導致耦合。
三個服務s1/s2/s3,通過一個公共的庫biz.jar來實現一段業務邏輯,s1/s2/s3其實間接通過biz.jar耦合在了一起,一個業務s1修改一塊公共的代碼,導致影響其他業務s2/s3,架構上是不合理的。
優化方案1:業務垂直拆分。
如果biz.jar中實現的邏輯“業務特性”很強,可以拆分為biz1.jar/biz2.jar/biz3.jar,來對s1/s2/s3進行解耦。這樣的話,任何業務的改動,影響范圍只是自己,不會影響其他人。
優化方案2:服務化。
如果biz.jar中實現的邏輯“業務共性”很強,可以將biz.jar優化為biz.service服務,來對s1/s2/s3進行解耦。服務化之后,兼容性能更好的通過接口自動化回歸測試來保證。
基礎服務的抽象,本身是一種共性聚焦,是系統解耦常見的方案。
場景2:服務化不徹底導致耦合。
服務化是解決“業務共性”組件庫導致系統耦合的常見方案之一,但如果服務化不徹底,service本身也容易成為業務耦合點。
典型的服務化不徹底導致的業務耦合的特征是,共性服務中,包含大量“根據不同業務,執行不同個性分支”的代碼。
- switch (biz-type)
- case biz-1 : exec1
- case biz-2 : exec2
- case biz-3 : exec3
- …
在這種架構下,biz-1/biz-2/biz-3有個性的業務需求,可能導致修改代碼的是共性的biz-service,使其成為研發瓶頸,架構上也是不合理的。
優化方案:業務特性代碼上浮,業務共性代碼下沉,徹底解耦。
把swithc case中業務特性代碼放到業務層實現,這樣biz-1/biz-2/biz-3有個性的業務需求,升級的是自己的業務系統。
場景3:notify的不合理實現導致的耦合。
《究竟什么時候該使用MQ?》一文中有一類業務場景,消息發送方不關注消息接收方的執行結果,如果采用調用的方式來實現通知,會導消息發送方和消息接收方耦合。
如何新增消息接收方biz-4,會發現修改代碼的是消息發送方,新增一個對biz-4的調用,極不合理。
優化方案:通過MQ實現解耦。
消息發送方upper將消息發布給MQ,消息接收方從MQ去訂閱,任何新增對消息的消費,upper都不需要修改代碼。
場景4:配置中的ip導致上下游耦合。
即“緣起”中舉的例子,下游服務換ip,可能導致多個服務調用方修改配置重啟。上下游間接的通過ip這個配置耦合在了一起,架構不合理。
優化方案:通過內網域名而不是ip來進行下游連接。
如果在配置中使用內網域名來進行下游連接,當下游服務或者數據庫更換ip時,只需要運維層面將內網域名指向新的ip,然后統一切斷原有舊的連接,連接就能夠自動切換到新的ip上來。這個過程不需要所有上游配合,非常帥氣,強烈推薦!
總結
如何發現系統架構中不合理的“反向依賴”設計?
- 變動方是A,配合方卻是BCDE;
- 需求方是A,改動方卻是BCDE;此時往往架構上可以進行解耦優化。
常見反向依賴如何優化?
(1)公共庫導致耦合。
- 優化一:如果公共庫是業務特性代碼,進行公共庫垂直拆分。
- 優化二:如果公共庫是業務共性代碼,進行服務化下沉抽象。
(2)服務化不徹底導致耦合。
- 特征:服務中包含大量“根據不同業務,執行不同個性分支”的代碼。
- 優化方案:個性代碼放到業務層實現,將服務化更徹底更純粹。
(3)notify的不合理實現導致的耦合。
- 特征:調用方不關注執行結果,以調用的方式去實現通知,新增訂閱者,修改代碼的是發布者。
- 優化方案:通過MQ解耦。
(4)配置中的ip導致上下游耦合。
- 特征:多個上游需要修改配置重啟。
- 優化方案:使用內網域名替代內網ip,通過“修改DNS指向,統一切斷舊連接”的方式來上游無感切換。
【本文為51CTO專欄作者“58沈劍”原創稿件,轉載請聯系原作者】