從0開始搭建一個微服務的持續交付系統,教你如何快速搭建

本文介紹瞭如何利用開源軟件快速搭建一套微服務的持續交付系統。本文假設的環境是Linux操作系統,用到的軟件包括Git、Jenkins、Salt、ZooKeeper、Apache等。開始之前,我先簡單介紹下持續交付和微服務的概念,以便大家更好的理解本文的精華。

什麼是持續交付?我們先舉個物流的例子,現在各大電商都非常重視物流的自動化建設,在實現包括運輸、裝卸、包裝、分揀、識別等作業過程的設備和設施自動化的同時,更在研究無人機和自動駕駛汽車送貨,達到物流的全自動。

那麼軟件開發呢,從開發人員check in代碼到代碼倉庫,到代碼的構建、部署、測試、發佈,我們可以形象地把這個過程稱為“軟件物流”,現實世界的物流實現了相當的自動化,“軟件物流”也應如是,實現從開發人員check in代碼(客戶下單)到生產系統上線(送貨上門)的自動化。

說到這裡,我們可以給持續交付下一個“非專業”的定義,持續交付就是實現“軟件物流”的自動化。

從0開始搭建一個微服務的持續交付系統,教你如何快速搭建

圖1.持續交付流水線

圖1摘自《持續交付:發佈可靠軟件的系統方法》,展示了持續交付具體包括的內容。本文重點討論如何實現微服務的持續交付流程,所以會忽略掉整個流程的一些細節(如代碼分析、單元測試等等)。

那什麼是微服務呢?微服務的概念最初由Martin Fowler與James Lewis於2014年共同提出,微服務架構風格是一種使用一套小服務來開發單個應用的方式途徑,每個服務運行在自己的進程中,並使用輕量級機制通信,通常是HTTP API,這些服務基於業務能力構建,並能夠通過自動化部署機制來獨立部署,這些服務使用不同的編程語言書寫,以及不同數據存儲技術,並保持最低限度的集中式管理。目前微服務的主流實現方式有兩種:RESTful API和消息隊列。

從0開始搭建一個微服務的持續交付系統,教你如何快速搭建

圖2 RESTful微服務

從0開始搭建一個微服務的持續交付系統,教你如何快速搭建

圖3 message queue微服務

圖2、圖3是兩種典型微服務架構的簡略圖。當然現實中的系統會複雜的多,比如會有微服務聚合,多級緩存,註冊中心等。

微服務相對單體式應用來說有明顯的好處:

  1. 解決了單體式應用的複雜性問題,單個微服務很容易開發、理解和維護。
  2. 每個微服務都可以由獨立的團隊來開發,可以自由選擇開發語言。
  3. 每個微服務可以獨立部署,系統可以快速演進。
  4. 可以對每個微服務進行獨立擴展,極大的提高系統伸縮性及資源利用率。

但在一個單體式應用拆分成數十個乃至上百個微服務,由於服務數量的增加,以及微服務支持多種編程語言的特性,對軟件的構建,部署,測試,監控都帶來了全新的挑戰。本文將討論如何通過持續交付來降低微服務構建,部署的複雜度。

微服務的持續交付:統一方法

由於微服務的特性,微服務的持續交付會比單體式應用的持續交付複雜的多。本節列出了為了降低微服務持續交付的複雜度,我們遵循的一些原則:

  1. 統一方法。這裡有兩個層面的含義,第一是流程的統一,有很多公司對運維自動化非常重視,但在開發,測試階段沒有采用自動化的方法
    。隨著DevOPS運動的興起,大家逐漸意識到需要在開發,測試階段採用與生產環境相同的交付方法,這樣在系統部署到生產環境的時候,這一交付流程已經經過多次的檢驗,出錯的概率大大降低了。第二層含義與微服務相關,各個微服務可能用不同的語言實現,如Java、Python、C++、Golang、純前端(JavaScript),我們要對採用不同語言實現的微服務使用統一的交付方法。
  2. 在版本控制系統中,每個微服務應該對應一個獨立的倉庫。以Git為例,一個Project下面,每個微服務對應一個獨立Repository。這樣各個微服務可以獨立check in代碼,而不會在持續構建的時候互相影響。
  3. 設計持續交付系統時要考慮實現軟件交付的全自動化,雖然在現實中,會存在提交測試,生產變更審核等人工環節。但在理想情況下,開發人員check in 代碼之後,能夠自動觸發構建,多套環境的部署及測試。
  4. 支持單個微服務升降級,這要求持續交付系統,對每個可部署的單元(微服務)要有獨立的版本號。
  5. 程序與配置分離。要支持一套程序(可執行包+配置文件包)多處部署,這裡強調了一套程序,是指在開發人員check in代碼後,構建系統只生成一份程序(可執行包+配置文件包)。不管是部署到開發環境,測試環境,還是生產環境我們要用同一套程序,而不是對每個環境單獨打包。我們知道Java war包會要求把配置文件包含在裡面,這會造成不同的環境要求提供不同的war包,這就違反了我們說的這個原則,後面我們會討論如何處理這個問題。
  6. 在應用程序部署時,不得依賴外網資源。我們把部署過程獨立為兩個階段:環境準備階段和應用程序部署階段。環境準備包括操作系統,JDK或其他語言運行時系統級依賴庫的安裝,得益於IaaS的相對成熟,我們把這一階段獨立出來。而應用的部署需要定製化,也是本文討論的部分。在部署應用時,要求所有的資源從內網獲得,這樣可以保證應用部署過程的快速、穩定、可重複。

快速搭建微服務的持續交付:持續構建

下面我們結合一個虛構的項目來介紹持續交付的實現細節,假設我們有一個項目BetaCat,由ms1、ms2…msN,n個微服務構成。下面我們重點介紹ms1微服務如何實現持續交付,其它微服務可以類推。

本節討論下如何實現持續構建,下一節會探討持續部署。

從0開始搭建一個微服務的持續交付系統,教你如何快速搭建

圖4 Jenkins處理倉庫代碼流程

如圖4所示,開發人員check in 代碼到Git倉庫後,Jenkins會自動地進行構建工作,並把打好的包上傳到Repo server上。

從0開始搭建一個微服務的持續交付系統,教你如何快速搭建

圖5 配置文件示例

作為統一方法的一部分,我們在每個微服務倉庫上創建了CI目錄,用於配置文件的打包,在CI目錄裡,只放入需要參數化的配置文件,執行腳本等,並會嚴格遵循原有系統的目錄結構,如圖5所示,我們要求有start.sh、stop.sh及service(用於Linux的init啟停該微服務)。

圖5中配置文件參數化內容,參數部分用”{{“與”}}”包圍起來,在持續部署的時候會根據傳入的參數替換為特定的值。

我們還定義了持續構建的統一輸出,對每個微服務採用tgz的打包格式,微服務ms1持續構建的輸出文件示例如下:

  • ms1-1.0.7.tgz (可執行包)
  • ms1_config-1.0.7.tgz(配置文件包)

在可執行包裡面要求把所有的依賴庫(除了系統lib庫)都包含在裡面,對不同編程語言的微服務的構建工具沒有強制要求,統一由Jenkins調用。C/C++我們推薦使用CMake,Java一般用Maven,Python直接打包。

配置文件包就是前面GIT倉庫的CI目錄直接打包而成。

從0開始搭建一個微服務的持續交付系統,教你如何快速搭建

圖6 Bundle示例

同時為了在部署時不用具體指定每個微服務的版本號,我們引入了bundle的概念,如圖6。在任何一個微服務構建之後,會觸發bundle,sha512校驗文件生成,並上傳到Repo Server。

最後讓我們看下持續交付上傳到Repo Server的目錄結構:

從0開始搭建一個微服務的持續交付系統,教你如何快速搭建

圖7 目錄結構

這樣持續構建的工作就完成了,接下來就需要進行持續部署了。

關注我:轉發+私信回覆“架構資料”獲取往期Java高級架構資料、源碼、筆記、視頻

Dubbo、Redis、設計模式、Netty、zookeeper、Spring cloud、分佈式、

高併發等架構技術

快速搭建微服務的持續交付:持續部署

在開始持續部署的討論之前,我們先描述一下軟件運行注入配置的三個時點:

從0開始搭建一個微服務的持續交付系統,教你如何快速搭建

圖8 配置注入的三個時間點打包時點,典型的是Java的war包,會把配置文件打包在一起。部署時點,在部署的時候利用專門的部署工具更新配置文件,這也是我們採用的方法;運行時點,程序運行時通過環境變量或註冊中心/配置中心獲得配置信息,如用Docker部署微服務時就要考慮通過這種方法來獲得所需要的配置信息。

從0開始搭建一個微服務的持續交付系統,教你如何快速搭建

圖9 採用salt進行部署

圖9顯示了我們對不同的環境統一採用salt進行部署。由於我們支持用戶只輸入bundle的版本信息來實現部署,這就要求在持續部署的時候,部署系統能自動獲取每個微服務的版本號,為此我們對salt/foreman做了一點小改動,修改後返回的pillar格式包含各個微服務的版本,同時下載並解壓對應的配置文件包到salt master的相應目錄,以及關閉salt master file_list緩存:fileserver_list_cache_time: 0。

從0開始搭建一個微服務的持續交付系統,教你如何快速搭建

圖10 foreman web界面以及Salt格式

圖10左邊表示我們在foreman web界面上設置的參數,右邊表示通過salt pillar.items取得的格式,可以看到多了每個微服務的版本號信息。

下面我們按照部署三部曲(安裝、配置注入、服務運行)來介紹部署規則文件(saltstate、sls文件)的編寫:

1、betacat_ms1.sls 第一部分:安裝

從0開始搭建一個微服務的持續交付系統,教你如何快速搭建

在這一部分,檢查並創建安裝目錄,下載需要的可執行包,並解壓到正確的位置,可執行包直接從Repo Server獲取,並通過sha512驗證文件的完整性。

2、betacat_ms1.sls 第二部分:配置注入

從0開始搭建一個微服務的持續交付系統,教你如何快速搭建

配置注入部分,讀取配置文件包,通過salt master轉換後下發給目標機。這裡用紅框標出了設計的核心。通過salt的file.recurse和之前持續部署中打好的配置程序包,並把所有的配置項傳入。可以做到不用對多個配置文件單獨編寫部署邏輯,完全參數化。

3、betacat_ms1.sls 第三部分:服務運行

從0開始搭建一個微服務的持續交付系統,教你如何快速搭建

在這一部分,確保微服務在運行狀態,並在必要的時候重啟。這裡需要特別指出的一點,在整個sls文件中,對不同的微服務來說,只有3個元參數:項目名稱(BeatCat)、微服務名稱(ms1)以及sig(ms1, 微服務進程的唯一識別字符串)。那麼我們可以通過簡單的腳本來自動生成sls文件,而不需要手工編寫。大大降低持續部署的開發維護成本。

快速搭建微服務的持續交付:全自動化

為了支持持續交付流程的全自動化,我們引入了ZooKeeper,如圖14。

從0開始搭建一個微服務的持續交付系統,教你如何快速搭建

圖14 引入ZooKeeper後的流程

  1. 代碼check in 到Git後,觸發構建,Jenkins會把打好的包上傳到Repository Server,並更新ZooKeeper的本次及latest包版本信息。
  2. 偵聽到ZooKeeper的latest包版本信息變動後,會觸發saltstack的部署命令向各個環境部署最新的程序。
  3. 部署完畢,會更新ZooKeeper上的目標機部署版本信息。
  4. 偵聽到ZooKeeper上的目標機部署版本信息變動後,會觸發一套或多套自動化測試腳本的運行。
  5. 自動化測試通過後,會更新ZooKeeper上的包版本的測試信息。
  6. 通過測試的包,可以自動上傳到生產環境的repo server,並更新生產環境ZooKeeper的包版本信息。
  7. 生產環境,偵聽到ZooKeeper的包版本信息變動後,會觸發生產環境的部署。
  8. 生產環境部署完畢,會更新ZooKeeper上的目標機部署版本信息。

關注我:轉發+私信回覆“架構資料”獲取往期Java高級架構資料、源碼、筆記、視頻

Dubbo、Redis、設計模式、Netty、zookeeper、Spring cloud、分佈式、

高併發等架構技術


分享到:


相關文章: