技術乾貨 | 微服務架構軟件的持續集成與交付(轉自樹人云)

 

技術乾貨 | 微服務架構軟件的持續集成與交付

美好的五一假期結束啦,你們玩得怎麼樣?今天小數給你們帶來的是數人云架構師周偉濤在CSDN作Mesos生態圈系列技術分享的第二期,討論他在微服務架構方面的經驗心得以及一些具體問題的解決。
Mesos生態圈系列第一期傳送門:    暢談Mesos生態圈
微服務架構概述

今天是 Mesos 生態圈系列的第二次分享,此次分享的內容是微服務架構軟件的持續交付,我首先解釋下標題與 Mesos 生態圈的關係。微服務架構是近幾年討論比較多或者說比較受歡迎的一種軟件架構風格,可是該架構有一些缺點,譬如運維複雜度提升,交付次數頻繁等,咱們能夠利用 Mesos 配合一些工具搭建持續交付平臺來彌補這些缺點。這裏我將以具體實踐爲例,討論微服務架構的一些經驗心得,而後着重介紹如何利用 Docker,Jenkins 來解決一些具體問題,實現微服務軟件的持續交付。
 
首先介紹下微服務架構的優點與劣勢。相較於單體應用來講,微服務架構有這麼幾個優勢:
  • 易於開發、理解。 因爲每一個服務只負責單一功能,開發者能夠聚焦於本身負責的幾個服務模塊,對於其餘服務,只須要理解接口便可。固然,單體應用通過良好設計也能夠達到這個效果,可是,與單體應用的進程內通訊或單機內的進程間通訊不一樣的是,微服務的各服務之間通常採用 RESTfulAPI或者異步消息隊列進行通訊,不管 RESTful接口仍是異步消息隊列都是開發語言無關的,極易理解的通訊方式。
 
  • 全局穩定性提升。因爲每一個服務負責的功能單一,各服務的資源需求也相對更低。從而能夠選擇將服務分散的部署到多臺中低配的服務器上,而不是一臺高配的機器上。若是某個機器上的服務故障,譬如說內存泄漏,故障只會影響該機器上的某一個或幾個服務,對全局影響不大。
  • 不受限於任何技術棧,極大的提升團隊搭建的速度。這一點對初創公司尤其重要,組建開發團隊對初創公司來講原本就是個頭疼的問題,如何還要求團隊的技術棧一致,招聘難度可想而知。可是,若是產品架構採用微服務架構,那麼咱們能夠容許不一樣的服務模塊採用不一樣的技術棧,只須要定義好對外接口便可。
  • 局部的修改很容易部署,從而大大的提升了功能的交付效率。
 
說完了微服務架構的優勢,咱們再來討論下其缺點或者說複雜的地方:
  • 如何肯定軟件功能切分的粒度,邊界。太多的微服務模塊會致使服務間通訊成本和運維成本的增長,過猶不及;可是若粒度過大,又違背了微服務的初衷。
  • 多種技術棧(譬如 C,Java,Python,Scala 等)咱們須要爲每種語言準備編譯環境,運行環境等,增長了維護成本。這個能夠經過Docker 隔離來解決,咱們後面會詳細展開。
  • 微服務模塊多了,會致使全局的上線次數變多,從而須要更復雜的版本管理和 Bug跟蹤等,間接致使項目管理成本增長。

1.webp_.jpg


持續交付

持續集成和交付(CI/CD)是一種軟件開發實踐,使用得當,它會極大的提升軟件開發效率並保障軟件開發質量;持續集成和交付分爲持續集成和持續交付兩部分,這裏咱們再也不具體探討這二者的區別,統一按持續交付來處理。Jenkins是一個開源項目,它提供了一種易於使用的持續集成系統;除 Jenkins 外,常見的持續集成系統還有:

Travis:  https://travis-ci.com/
Codeship:  https://codeship.com/
Stridercd:  http://stridercd.com/
 
另外,常見的交付方式通常有:
  • 源代碼交付: 源代碼交付須要將源代碼以 tar 包等方式 download 到服務器,而後在服務器上藉助程序的構建腳本去構建可執行程序,顯然這種方式會常常因服務器環境差別,構建環境初始化失敗等問題致使沒法構建可執行程序。嚴重依賴於構建腳本的完備程度。
  •  Linux 標準包交付:  將項目的依賴經過 Linux deb 或者 rpm 來管理,因爲這種方式更符合 Linux 規範,間接的提升了項目在服務器上部署的成功率,可是有些時候仍然須要解決包衝突問題。
  • 虛擬鏡像交付: 虛擬鏡像交付指的是咱們將項目在虛擬機裏測試成功後直接將該虛擬鏡像部署到服務器上。顯然,這種方式部署成功率接近100%並且隔離性好。可是隨之而來的問題就是虛擬鏡像自己對服務器資源的消耗。
  • docker image 交付: docker image 交付是虛擬鏡像交付的進一步演進,在保證系統隔離的同時,docker image 對服務器的資源消耗更低。固然,docker 的隔離機制是進程級別的,可能不適合一些強隔離場景。咱們團隊目前正在使用這種方式進行交付。


2.webp_.jpg


上圖(圖片來自於網絡)展現了圍繞 Docker 鏡像倉庫的持續交付流程:
  • 首先開發者將代碼推送到代碼倉庫,譬如github
  • 代碼倉庫的更新會觸發新的代碼構建,生成新的 docker 鏡像並推送到 docker 鏡像倉庫
  • 接下來會基於新的 docker 鏡像進行集成測試
  • 測試經過後,docker 鏡像被交付到公有或者私有云上
 
經過上述持續交付的方式交付微服務架構的軟件,可以很好的解決前面提到的第二與第三個問題,即
  • 結合 Docker 解決多技術棧的環境維護問題;
  • 按微服務模塊交付來提升軟件的交付效率
  • 引入「版本服務」來可視化各微服務的版本信息
  • 引入「ReleaseNote服務」來發布各微服務的 feature 更新

實踐

微服務架構有多種,數人云的微服務架構有以下特色:
  • RESTAPI 與 消息隊列 結合使用。微服務與外部用戶經過 RESTAPI 通訊,內部微服務之間經過消息隊列通訊。
  • 所有 Docker 交付,這解決了多技術棧的環境維護問題。
  •  一個微服務對應於一個持續交付的 Job,這保證了各服務在交付環節無相互依賴,單獨觸發。同時能夠利用不一樣的 Docker 鏡像爲不一樣的 Job 提供相應環境。
  • 版本信息自動更新
  • ReleaseNote 自動發佈
  • 構建環境 Docker 化,與底層隔離,保證宿主機環境的一致性,下降運維成本
  • 利用 Docker-compose 維護本地開發環境,從而實現開發環境與生產環境的邏輯一致性

3.webp_.jpg


數人云的架構設計模式如圖所示。用戶經過瀏覽器或者直接經過 RESTAPI 與後臺通訊,後臺是一個微服務集合,對外服務的接口一概採用 RESTAPI, 內部服務之間的接口採用消息隊列。各微服務負責維護自身的狀態集,有本身獨立的緩存和 DB (若有必要)。微服務自己儘可能無狀態化,以保證橫向擴展能力。

4.webp_.jpg


上圖是咱們目前採用的持續交付架構圖。A, B, C, D 四個 github 代碼庫分別存儲着四個微服務的源代碼,相應的咱們爲每個代碼庫建立了獨立的構建做業,代碼更新觸發構建時,構建做業將執行以下的大體步驟:
  • 從 Docker 私有鏡像倉庫拉取相應的構建鏡像
  • 從 github 源碼庫拉取相應代碼並掛載到構建容器裏,觸發特定腳原本執行構建
  • 若構建成功,馬上從 Docker 私有鏡像倉庫拉取相應的 runtime 鏡像,將構建成功的可執行程序 Docker 化成新一版的微服務鏡像
  • 將上述微服務鏡像推送到 Docker 私有鏡像倉庫

若已經設置了自動交付
  • 則經過 Marathon 的 RESTful API 接口觸發線上微服務的更新
  • 更新版本服務裏面對應微服務的版本信息
  • 自動更新 ReleaseNote 服務裏面對應微服務的 ReleaseNote。 開發者在實現了相應功能時已經將對應的 ReleaseNote 放在了代碼庫特定目錄下面(這個後面會詳細提到) 
 


5.webp_.jpg


另外,從架構圖中咱們能夠看出,程序的構建環境和運行環境正在共享同一個 Mesos 資源池,提升了資源利用率。
 
把 Jenkins 運行在 Mesos 上有以下幾個考慮:
  • 把Jenkins運行到 Apache Mesos上,或者說利用 Apache Mesos 向 Jenkins 提供 slave 資源,最主術棧的軟件狀況下尤爲重要,能夠極大下降運維成本。
  • Marathon會對發佈到它之上的應用程序進行健康檢查,從而在應用程序因爲某些緣由意外崩潰後自動重啓該應用。這樣,選擇利用Marathon管理 Jenkins Master 保證了該構建系統的全局高可用。並且,Jenkins Master 自己也經過 Marathon 部署運行在 Mesos 資源池內,進一步實現了資源共享,提升了資源利用率。



關於怎樣將 jenkins 運行在 mesos 上,你們能夠參考我之前在csdn發佈的一篇文章 http://www.csdn.net/article/2015-06-18/2824998
Docker 承擔了什麼角色
Docker 在整個體系中承擔了以下幾個角色:

各代碼庫的編譯載體: 咱們已經提早將各代碼庫的編譯環境製做成了 docker 鏡像
交付介質: 編譯成功的可執行程序將被打包成 docker 鏡像, 鏡像的 tag 對應於程序版本信息
Runtime 環境: 運行環境已經被打包到 docker 鏡像中了,啓動的 docker 容器將做爲微服務的 runtime 環境
資源隔離: docker 自己支持進程級別隔離,已經知足內部應用需求
爲了保證單機開發環境與線上環境的配置/架構一致,咱們在單機開發環境利用 docker-compose 來編排整個微服務環境,以便於調試

版本調試

在實踐微服務架構時,咱們碰到了這麼一個問題:各微服務模塊頻繁交付,如何確認線上各微服務的版本, 即咱們須要對各微服務進行版本控制。

目前團隊迭代出了以下解決方案:交付成功後,交付 job會截取 docker 鏡像裏相應的 tag(表明着版本信息),並把該信息推送到一個 NginxServer 的靜態文件裏面, 前端頁面訪問該靜態文件來獲取相應微服務的版本信息。另外,同一個微服務會部署到開發,測試和生產三個環境上,因此基於不一樣的環境,咱們會維護三個不一樣的靜態文件 。
 
ReleaseNote 服務

在多人協做的微服務項目開發中,因爲多人頻繁的 merge 代碼,ReleaseNote 的管理也會成爲團隊的負擔。我這裏推薦的作法是這樣:

文檔規約:團隊達成一個 agreement: 對重大 feature 或 bug-fix 的提交都須要在目錄 pending-release 裏面建立相應的 markdown 文件,並將改動添加到裏面。這樣,咱們能夠控制交付 Job 在交付時掃描 pending-release 目錄並將其中的文本 merge 到一塊兒生成此次交付的 ReleaseNote。
git pre-commit-hook:同時,爲了不團隊成員忘記這個agreement,咱們還能夠在本地的 git-precommit-hook 中添加相應的掃描提醒。

配置中心服務

目前網絡上關於配置管理的解決方案已經很是成熟,我這裏就不過多解釋了。惟一須要提到的就是, 咱們的配置中心服務尚未徹底融入到整個交付過程當中來,微服務的配置文件仍然須要手工介入。

持續集成的消息通知

顯然,團隊但願 CI 服務器在執行了持續集成後可以及時的將集成結果通知團隊成員, Jenkins 自己是有 irc notification 插件的,可是國內開發者可能使用 IRC 的並很少;微信是小團隊使用比較多的溝通工具,咱們可使用微信公衆號進行消息通知;或者使用國內的 LessChart 等交流工具,它們自己支持 webhook 調用。

開發環境的搭建

微服務架構致使軟件模塊增多,增長了開發環境搭建的難度,同時也致使了團隊新成員上手門檻的提升。咱們目前是利用 docker-compose 維護本地開發環境來解決這個問題的。它不只實現了開發環境與生產環境的邏輯一致性,同時也可讓相應模塊的開發者聚焦於本身的業務,沒必要糾結於如何啓停其它微服務。下面是咱們的 docker-compose 文件的一部分。

6.webp_.jpg


問題及解決
在具體實踐中,還有以下幾個難題。
 
MQ 消息格式統一的困境
微服務間的消息傳遞須要根據業務變更而頻繁改動,尤爲是前期,這帶來了極大的溝通成本,目前沒有好辦法解決。
 
微服務的功能粒度切分問題
如何界定各微服務承擔的功能,每一個微服務的功能粒度切分,微服務間的邊界定義,這也是咱們團隊一直在摸索的問題。
 
參考連接:
1.  http://microservices.io/
2. http://www.infoq.com/cn/news/2 ... cture
 
 0
 分享 2016-05-05

0 個評論

 

要回覆文章請先登陸註冊前端

相關文章
相關標籤/搜索