Shopify 是如何遷移到模塊化單體架構(gòu)的?

來源:  InfoQ
作者:Andrew Morgan
時間:2021-05-10
16931
Shopify 高級工程師 Kirsten Westeinde 在 Shopify Unite 2019 大會上討論了 Shopify 向模塊化單體架構(gòu)的演變。這包括使用設(shè)計收益線( design payoff line )來決定何時進(jìn)行此更改,如何實現(xiàn)更改,以及為什么將微服務(wù)排除在目標(biāo)架構(gòu)之外。

Shopify 高級工程師 Kirsten Westeinde 在 Shopify Unite 2019 大會上討論了 Shopify 向模塊化單體架構(gòu)的演變。這包括使用設(shè)計收益線( design payoff line )來決定何時進(jìn)行此更改,如何實現(xiàn)更改,以及為什么將微服務(wù)排除在目標(biāo)架構(gòu)之外。

一個關(guān)鍵的結(jié)論是,單體不一定是一個糟糕的架構(gòu),它具有許多優(yōu)點,比如單個測試和部署管道。在項目開始時,當(dāng)必須快速交付新特性時,這一點特別有用。只有在跨越了“設(shè)計收益線”時,也就是糟糕的設(shè)計阻礙特性開發(fā)的那一點,才應(yīng)該開始改進(jìn)架構(gòu)。就 Shopify 而言,改進(jìn)其架構(gòu)并不意味著轉(zhuǎn)向微服務(wù),而是轉(zhuǎn)向模塊化單體架構(gòu)。這結(jié)合了單體(例如單個測試和部署管道)和微服務(wù)(例如代碼模塊化和解耦)的優(yōu)點。

Westeinde 認(rèn)為,單體架構(gòu)是一個很好的項目起點,他說:“其實,我建議新產(chǎn)品和新公司開始時使用單體架構(gòu)?!彼信e了其中的一些優(yōu)點:

  • 一個項目包含所有代碼;

  • 只有一個代碼庫,測試和部署都很簡單;

  • 所有數(shù)據(jù)都可用,無需跨服務(wù)傳遞;

  • 一組基礎(chǔ)設(shè)施。

由于這些優(yōu)點,Shopify 一開始只是一個小型的 Ruby on Rails 單體,隨著時間的推移,逐漸發(fā)展成為一個非常大的代碼庫。當(dāng)這種情況發(fā)生時,它意味著 Shopify 開始變得不可維護(hù),并且因此很難交付新特性。例如,更改一段代碼會對看似無關(guān)的代碼造成意想不到的副作用,并且構(gòu)建和測試應(yīng)用程序花費的時間太長。

Westeinde 援引 Martin Fowler 的設(shè)計耐力假說( design stamina hypothesis )解釋說,是時候重構(gòu)他們的架構(gòu)了——一旦功能開發(fā)被糟糕的設(shè)計所阻礙,設(shè)計收益線就會被跨越,這意味著投入資源來修復(fù)它是有意義的。

最初,Shopify 將微服務(wù)視為一種可選的、更易于維護(hù)的架構(gòu)。然而,由于分布式系統(tǒng)的復(fù)雜性,它被排除在外,取而代之的是更易于維護(hù)的單體架構(gòu):

我們意識到,我們喜歡單體所有的東西,代碼都在一個地方,而且向一個地方部署。我們遇到的所有問題都是由代碼中不同功能之間缺乏界限所直接導(dǎo)致的。

Westeinde 解釋說,他們意識到他們的設(shè)計目標(biāo)是提升系統(tǒng)的模塊化,比如使用微服務(wù),同時保持一個單一的可部署單元,像一個單體。為了實現(xiàn)這一點,Shopify 采用了模塊化的單體模式。這使得代碼之間有了邊界,但要使代碼都在同一個位置并且部署到同一個位置。遷移路徑如下:

  • 代碼重組:最初,代碼的組織方式類似于典型的 Rails 應(yīng)用程序,頂層部件以技術(shù)組件命名,如控制器。這被更改為基于業(yè)務(wù)功能進(jìn)行組織,如“賬單”和“訂單”,從而更容易定位代碼。

  • 隔離依賴關(guān)系:每個業(yè)務(wù)組件彼此隔離,然后通過公共 API 供外部使用。他們內(nèi)部開發(fā)了一個名為 Wedge 的工具,它跟蹤每個組件的隔離情況。它構(gòu)建一個調(diào)用圖,然后計算出哪些調(diào)用(比如跨組件的調(diào)用)違反了規(guī)則。

  • 強(qiáng)制邊界:一旦每個組件都實現(xiàn)了 100% 的隔離,它們之間就有了強(qiáng)制的邊界。其思想是,當(dāng)代碼試圖訪問它沒有顯式依賴的組件的代碼時,就會出現(xiàn)運行時錯誤。以這種方式聲明依賴關(guān)系也將使它們在依賴關(guān)系圖中可視化。

最后,Westeinde 解釋說,這個例子很好地說明了架構(gòu)如何根據(jù)業(yè)務(wù)需求發(fā)展:

良好的軟件架構(gòu)是一項不斷演化的任務(wù),而應(yīng)用程序的恰當(dāng)解決方案完全取決于你的操作規(guī)模。

立即登錄,閱讀全文
版權(quán)說明:
本文內(nèi)容來自于 InfoQ ,本站不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。文章內(nèi)容系作者個人觀點,不代表快出海對觀點贊同或支持。如有侵權(quán),請聯(lián)系管理員(zzx@kchuhai.com)刪除!
優(yōu)質(zhì)服務(wù)商推薦
更多
掃碼登錄
打開掃一掃, 關(guān)注公眾號后即可登錄/注冊
加載中
二維碼已失效 請重試
刷新
賬號登錄/注冊
個人VIP
小程序
快出海小程序
公眾號
快出海公眾號
商務(wù)合作
商務(wù)合作
投稿采訪
投稿采訪
出海管家
出海管家