已經準備好向容器遷移了嗎?如果你正考慮從現有非容器化的系統上將服務遷移到基於容器的環境中,那麼你一定想知道該如何實現它。有什麼正確的方法?有沒有最好的方法?或者說,有沒有某種直接遷移過程(lift-and-shift process)可以適用於所有的應用程序?

通常來講,上述問題都有肯定的答案。雖然因各公司的具體情況不同,遷移到容器和微服務的具體細節會各有差異,但是對於實現應用程序從傳統基礎設施到容器環境的無縫遷移來說,還是有一些普適性原則和最佳實踐經驗值得大家遵循。

這篇博文將簡要介紹成功將傳統應用程序遷移到容器的指導原則。

微服務——它們是什麼?

在處於項目遷移的最初規劃階段,關於容器化,最需要注意的是容器系統架構是基於(或應該基於)微服務的。那麼,微服務是什麼?

實際上,界定什麼是微服務、什麼不是微服務,這其間的標準是有些模糊的。這種情況其實是一種必然,因為不同的設計容器化應用程序的方法(我們稍後會提到),正是基於不同的定義微服務的方法。

從總體上來說,微服務可以描述為一個基本的、功能分離的服務,它由應用程序的其他部分調用。我們可以把從資料庫中檢索數據的服務看作是一個微服務,既可以將數據發送到存儲設備,也可以處理用戶輸入。

例如,在線上商店中,訪問庫存資料庫是由一個微服務處理,客戶的購物車由一個微服務更新,交易再由一個微服務完成,並且還有一個微服務處理信用卡的授權,而這些微服務都是獨立的。

而對於同一家店,可以由多個微服務工作,一個微服務處理所有的資料庫訪問(庫存、客戶和銷售),一個微服務處理購物車和交易,而第三個微服務用做運輸物流。這種特定的微服務結構,在很大程度上是一種設計選擇,它取決於系統整體架構。

你當前的架構是什麼?

不過,在開始構建容器化應用程序之前,還需要著留意一下你當前的架構。宏觀上,非容器化的應用程序可以大體分為兩類:單體架構和SOA架構(服務導向架構)。當前架構不同,進行容器化重構的方法就不同,因此我們先將它們區分開來,再討論設計選擇以及整體的重構策略。

單體架構

大多數傳統設計的應用程序都是單體架構。它們可能由單個包含了支持的庫、服務以及配置文件的程序,或者少量帶支持資源的程序組成。然而,在這兩種情況下,大部分甚至全部的核心功能都包含在一個或幾個二進位文件中,其中服務就包含於這些在二進位文件定義的應用程序邊界內進行操作和通信的功能中。桌面級的應用程序傳統上講是單體的,大多數基於網路的應用程序也是如此。

在桌面或區域網環境中,單體架構通常是十分有效的。它的安裝和更新相當容易,並且單體的設計能夠輕鬆地監控組件,而且桌面/LAN的使用一般不會對應用程序的資源造成太大的壓力。然而,在雲或互聯網的環境中,單體應用程序可能相對過於龐大、笨拙、緩慢,它們不僅難以更新,且不能夠處理大量的流量。另外,它們也不適用持續交付以及大多數構成DevOps的實踐。

如果想重構容器的單體架構應用,那可能需要在概念層面上進行全盤的重新設計。即便應用程序的架構已經相當清晰地定義了其內部服務,並且保證了它的離散性,實際拆分成微服務時可能還需要對這些服務的邊界以及它們彼此通信的方式進行大規模的更改。對於大多數的單體應用程序,許多服務都需要重新定義,甚至需要從頭開始定義。

SOA架構

有一些大型的非容器應用程序可能已經具有了基於服務的架構。例如,銷售點的應用程序可能包含了獨立的程序用來處理銷售、庫存、客戶記錄、訂單、運輸、差異、稅收、應收賬款以及應付賬款。每一個模塊都是一個單獨的程序,具有明確的應用程序邊界,而且這種跨邊界的模塊間通信和基於容器的應用程序十分相似。

如果有進行細分的需要,這種架構(假設它是令人滿意的)可以作為進一步分解成微服務的基礎。進一步分解可以是基於現有的模塊分解成更小的服務,也可以是基於抽象的廣義服務(比如訪問單個資料庫或列印收據的微服務),或者兩者都是。另一方面,如果現有模塊已經是小容量、功能分散且組織良好的,那麼只需要進行極少的修改就可以將其遷移到容器中。

對於單體應用你要怎麼做?

在這一點上,應該弄清楚的是,將單體應用程序分解成微服務通常是一個複雜而極具挑戰的工作。就像之前說的那樣,首先是根據微服務重新定義架構。這裡的重新定義以及實際細分成微服務本身的過程通常稱為分解(decomposition)。關於分解有一些基本的模式。在很多情況下,了解這些模式的基礎和基本性質比選擇哪種模式更重要,而在實際生產中,根據系統的功能要求,將單體應用程序分解成微服務時常常涉及到多種模式。

根據用例分解

用例是指用戶在執行任務時通常會採取的一組操作。用戶既可以是實際的人,可以是應用程序的另一部分,也可以是外部的應用程序。用例的關鍵要素是它是與任務相關聯的一組可定義的動作。在線上商店的例子中,一組客戶操作(如選擇和購買商品)就可以是一個用例,單純的內部操作也可以是用例,例如在銷售之後更新庫存、客戶信息以及交易資料庫。

根據功能分解

根據功能分解是分解的另一種常見模式。例如,銷售交易可以是一個由功能定義的單元,而信用授權可以作為由功能定義的另一個服務。你可以根據諸如差異跟蹤、運輸和自動補貨這些功能來定義功能域。功能分解和用例分解非常相似,不過它的定義更多的是由需要執行的行為決定而非執行的對象。

根據資源分解

在多數情況下,根據資源定義特定的微服務無疑是最好的方案。例如,你可以定義一個單一的微服務來處理所有與具體某個資料庫或一組資料庫的交互,或者處理所有與持久存儲器的交互。在許多方面,設備驅動程序是基於資源的微服務。如果通過某種類似於設備驅動程序的通用服務來和資源進行交互是有意義的,那麼將該服務定義為微服務也可能有實際價值。

分解途徑

確定了分解單體應用的整體模式後,就可以開始將其分解成微服務。你的最終目標應該是將整個應用程序縮成一組微服務層級的容器,它們和原始的單體應用一樣,提供相同的一組服務(能夠根據需要添加或改進功能),可以根據需要進行管理和部署,而且相比之下有更出色的速度、流量以及靈活性。

比較好的一點是,你並不需要一下子把它拆散。可以將前面說的大型SOA架構作為中間階段。你可以在開始的時候將單體應用程序拆成大型的基於服務的塊,然後再將其細分成越來越小的服務,直到最終達到期望目標級別的微服務。而這裡還有另一種方案,你可以從定義明確的服務入手,先將這些服務拆分成基於容器的微服務,然後再以類似先前的方法,分幾次拆分應用程序的其餘部分。

無論採取哪種方法,一定要牢記一點,那就是要明確定義微服務,而且這些定義在應用程序的整體功能和架構上都應該是有實際意義的。只要你遵循了這些原則,相信你的遷移工作就會成功。


推薦閱讀:
相关文章