讀【微服務設計】(四)分解單塊系統

1. 識別出接縫處(限界上下文)

單塊系統不具備高內聚、低耦合的特點,所以分解的第一步需要很謹慎,首先就是要識別出接縫的位置,我們可以從接縫處抽取相對獨立的一部分代碼,修改這部分不會影響系統的其他部分,並且能夠清理代碼庫以及成爲服務的邊界。

很多編程語言都有命名空間的概念,幫助我們把相似代碼組織到一起,如Python/Java/Go等都有package概念,當我們識別出限界上下文後就可以通過pkg將它們分開維護。

2. 更有效率的分解

如果要分解一個較大的單塊系統,那需要對分解的代碼做一些優先級劃分。

  • 如接下來的開發任務是針對庫存系統,那麼下一步就將庫存接縫抽出來作爲一個服務,使其成爲一個自治單元,就會大大加速後期開發速度
  • 團隊結構,假如一個系統是由不同團隊共同維護,那麼優先按團隊獨立服務會是一個好的做法,這樣單個團隊就能全權負責它們的代碼庫
  • 安全方面,若某個系統會對財務相關接口做安全審計和傳輸數據保護等措施,如果把這個服務分離出來,可以更好的對它做監控、傳輸數據保護以及靜態數據保護等
  • 技術方面,假如推薦系統團隊研究出一種新算法(使用另一種語言),如果能把這部分代碼分離出來,就很容易在出現問題時重構和測試

3. 共享靜態數據

假如系統要使用國家列表數據,那麼在微服務架構中如果共享呢,有幾種方式:

  1. 數據寫入數據庫一張表,所有服務都直接讀取此表
  2. 將數據放入一個單獨的服務中的靜態文件中,其他服務調用這個服務提供的接口來讀取

第一種方式在修改時不大方便,第二種是個人認爲比較合理的,它在更新時只需修改上線一個服務的靜態文件即可,因爲沒有更新服務代碼,所以其他服務不用更新pkg信息。

這裏你可能對更新靜態文件的具體方法有疑問,是這樣做的,我們將靜態文件放在/static目錄下,命名爲countries_202006270920.txt,後面的數字就是更改時間,在更新時我們將具有帶有最新更改時間的文件放到/static目錄下,服務在讀取時讀最新的文件。

4. 儘量不要共享表

通常我們多個服務都會需要讀取一個用戶的信息,比如是不是會員,是否註銷等等,最好的做好是獨立一個用戶服務,其他服務調用這個服務提供的接口來工作,這樣才能更好的做資源隔離,以及踐行單一職責原則。

5. 重構數據庫

這一步我們要實施分離了,那麼你想的是在某次發佈中把單塊系統直接變成兩個服務嗎?並且他們擁有各自的數據庫表?

事實上,我會推薦你先分離數據庫結構,暫時不對服務進行分離。

表分離後,對於原先的某個動作而言,對數據庫的訪問次數可能變多,因爲以前只需要一個SELECT就能得到所有數據,現在則需要分別從不同的地方拿到數據,然後在內存中連接。還有,分成兩個表結構會破壞事務完整性,這會對應用程序造成很大的影響,後面會繼續討論。先分離數據庫結構而不分離服務的好處在於,可以隨時選擇回退這些修改或是繼續這樣做,而不影響服務的任何消費者。我們對數據庫分離感到滿意後,就可以考慮對整個服務做拆分了。

6. 微服務下的數據一致性

很遺憾,對於這個部分我沒有看到作者提出具有較大可行性的方案,書中闡述了兩種辦法:

  1. 補償事務或操作,就是立馬重試或者通過定時任務來週期性的檢查和消除數據庫中的不一致,但補償事務仍然有失敗的可能性,而在需要同步的操作有兩個,三個甚至更多時,定時任務會非常難以理解,後期維護時可能是噩夢。
  2. 分佈式事務,這需要一箇中心化的事務管理器工具來統一編配系統中運行的事務。作者提到的一個算法是兩階段提交,也同時提到了這個算法的諸多缺點,比如事務管理器具有單點故障,投票結束後的提交也可能會失敗等等。

關於這個話題,我想還需要繼續探索。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章