案例分享〡三拾衆籌持續交付開發流程支撐創新業務

本文來自三拾衆籌系統架構師陳曉輝的演講,題爲「持續交付開發流程支撐創新業務」,介紹了三拾衆籌基於網易蜂巢的系統開發實踐。現將分享內容整理以下:前端

三拾衆籌項目介紹

圖片描述

三拾衆籌是一個創新型的業務,咱們的理想是作不同的衆籌平臺:nginx

  1. 基於內容產品提供衆籌服務git

  2. 專一探尋最有創意的想法、最有溫度的故事程序員

  3. 深耕影視、遊戲、音樂、傳媒、動漫等泛文娛領域web

從2016年7月份項目籌備以來,通過兩個多月的開發,10月份平臺正式上線運營。目前的團隊規模不大,屬於內部創業的狀態,可是咱們的口號是:再小的力量,也能擲地迴響。spring

圖片描述

今天的分享是從技術角度介紹一下咱們如何構建這個持續開發的流程,來支撐咱們的創新業務。docker

在運行一個創新業務的時候,咱們的技術會面臨很大的挑戰,這和咱們創新業務的特色是相關的:數據庫

  1. 業務是快速變動的,不可能想好全部的事情纔開始啓動咱們的項目,因此剛開始的時候,所謂的創新更多的是在試錯。咱們但願項目在作的時候,不斷地收集反饋,不斷地調整方向,最終找到突破點。而在不斷調整方向的過程當中,技術必須作到及時響應。當業務須要技術提供彈藥的時候,技術不能說咱們還在調研,咱們還在建廠房,功能不能變動。後端

  2. 業務爆發式地增加。前面咱們說去找方向,那什麼是正確的方向,其實很難去判斷,可是至少咱們不是爲了維持某種狀態去作的,由於咱們是一個從無到有的過程。一旦咱們找到了正確的方向,接下來業務就會出現一個提高或者擴張,可是時間是沒法預期的,每每是爆發式的,很難線性地去判斷。可是對於技術來說,如何可以不拖業務爆發的後腿,是一個棘手的問題。當業務有很大流量導入的時候,咱們的系統不能撐不住,掛了。緩存

  3. 資源成本投入。全部的創新項目資源都是有限的,若是資源不少,每每就沒有了創新的土壤。資源很少就必須將有限的資源用在刀刃上。

圖片描述

面對這三項挑戰,咱們的技術團隊必須具有三項技術能力:

  1. 快速迭代:產品要快速交付,快速部署。

  2. 可擴展:系統可以經過橫向擴展的方式,支撐更大的流量。

  3. 技術有按需的能力,只擴展應該擴展的模塊。

這讓咱們這個創業團隊想要藉助雲的力量,藉助網易雲容器平臺的力量。

對於雲來說,按需的能力是自然的,在網易雲上,咱們是按需按時分配的;而快速迭代和可擴展,是雲的潛力,使得咱們不須要採購機器,安裝系統,部署環境。

那三拾衆籌如何才能發揮雲的潛力,如何設計咱們的系統,使用什麼樣的開發過程,才能讓雲真正的幫助咱們的業務?

這裏有一個重要的概念,就是 Cloud Native。以前有人翻譯爲雲原生應用,我以爲比較直白,我起了一個小清新的名字,叫作向雲而生。

這表示咱們的應用應該設計爲面向雲和容器平臺去應用的。

設計目標

  • 使用標準化流程自動配置(declarativeformats for setup automation),從而使新的開發者花費最少的學習成本加入這個項目。

  • 和操做系統之間儘量地劃清界限,在各個系統中提供最大的可移植性。

  • 適合部署在現代的雲計算平臺,從而在服務器和系統管理方面節省資源。

  • 將開發環境和生產環境的差別降至最低,並使用持續交付實施敏捷開發。

  • 能夠在工具、架構和開發流程不發生明顯變化的前提下實現擴展。

另外還有12原則

三拾衆籌很是相信12原則,把整個系統按照12原則進行設計。

12 Factors
I. Codebase-One codebase tracked in revision control, many deploys
II. Dependencies-Explicitly declare and isolate dependencies
III. Config-Store config in the environment
IV. Backing services-Treat backing services as attached resources
V. Build, release, run-Strictly separate build and run stages
VI. Processes-Execute the app as one or more stateless processes
VII. Port binding-Export services via port binding
VIII. Concurrency-Scale out via the process model
IX. Disposability-Maximize robustness with fast startup and graceful shutdown
X. Dev/prod parity-Keep development, staging, and production as similar as possible
XI. Logs-Treat logs as event streams
XII. Admin processes-Run admin/management tasks as one-off processes

系統架構

如圖是三拾衆籌的系統概覽,也是咱們當前系統的部署架構

圖片描述

三拾衆籌的架構採用的是服務化的架構,是由一系列相互協同的服務組成的。服務之間有協做的過程,服務對外也提供了統一的界面。每個服務自己有本身的存儲,有本身的緩存。

全部的服務分兩個區域,也即服務分兩種類型。第一是應用的服務,第二是基礎服務。

在應用服務裏面,對外有一個主站服務,同時承擔了 API網關的職責。它會把前臺的請求分發到後臺,而且根據規則進行路由。

服務與服務之間都是經過 Restful API也即 HTTP的方式,服務之間會有明確的依賴關係,並且依賴關係的強弱在這裏用實線和虛線作區分。經過這些依賴關係來構成和編排咱們的服務。

咱們最初上線的平臺也不是這樣的,而是隻有一個衆籌平臺。是隨着功能的豐富,應對更快的變化,而逐漸拆分的,例如對於支付模塊,當咱們須要接入更多的支付方式,針對支付有更多的優化需求的時候,咱們須要獨立出一個收銀臺的模塊,進行服務拆分。包括會員,包括訂單的部分。

爲了支撐應用服務的環境,咱們還有一些基礎設施服務。

好比註冊中心,服務之間有自動的服務註冊與服務發現的機制。咱們的全部服務是經過註冊中心進行相互關聯的,不須要人工的編排,是能夠自動地發現服務。

咱們能夠經過服務的控制檯去管理服務。個人服務狀態是什麼,對應的版本就是什麼。

每一個應用都涉及到一些配置參數,若是配置參數扔在每一個服務上的話,對於運維來講代價就比較高了。對於微服務架構來說,必然須要一個集中化,可分發的配置中心,也是在基礎服務中的。

咱們會使用 Git倉庫做爲配置的後端,經過配置中心去分發 Git倉庫中的配置,同時後面咱們還會提到,有一個流程來管理整個過程。

在這個架構裏,全部的組件都在容器裏面。每一個服務構建的結果就是鏡像,在運行期就體現爲容器。

這裏面的每一個服務都使用的是網易雲的無狀態服務,除了構建服務。構建服務是從代碼構建爲鏡像,是在咱們本身的服務器上運行,也是一個容器。

設計要點

接下來我分享一下咱們設計時的考慮及實現要點:

Cloud Native的設計

  1. 從設計開始,咱們就隔離了基礎設施和後端服務依賴,這個隔離一方面是由容器來作的,隔離了應用和服務器之間的關係。另外一方面,應用層咱們用了不少的框架,例如後面提到的 springboot和 springcloud,咱們使用公共的開源框架和工具,把一些面向服務化,容器化的基礎功能進行實現,對於應用自己不須要關心這些過程,只須要關注中間層,根據 spring的規約來進行開發。

  2. 從一開始,就把配置和代碼進行分離。將配置和鏡像進行分離。

  3. 對於編排的問題,經過 springcloud和 consul進行服務發現的功能,來實現服務的自動編排。

  4. 咱們實現了持續集成和持續交付的開發過程,顯式地分離了構建,發佈,運行的整個過程。這也是今天分享的一個主題。

容器化的實踐

  1. 普遍使用了容器,在咱們看來,容器就是服務。當咱們實現一個新功能的時候,首先要考慮需不須要單獨拆分爲一個新的服務。

  2. 經過提供一批基礎鏡像,來簡化服務的開發,能夠說是應用開發的模板

  3. 使用了網易雲基礎設施平臺,由於他很是開放,技術導向,對程序員友好。提供了豐富的 API,經過這些 API能夠實現自動化,實現自動交付。另外蜂巢提供了不少基礎 PaaS服務,包含數據庫,緩存,CDN,對象存儲,負載均衡等,下降構建服務的難度,提升開發效率。咱們幾乎用了全部的 PaaS服務,使得咱們沒必要過多關心平臺層面的東西。

微服務基礎設施

  1. 服務的註冊,發現和負載均衡機制。這個機制目前是經過 spring cloud來作的。Spring cloud是一個很是完整的微服務開發的框架,他的主要做用是在應用和設施之間提供一個抽象層,讓咱們用一致的 API去使用不一樣的服務發現機制,好比基於 Java開發的 eureka,包括咱們使用的 consul。

  2. 咱們實現了配置中心

  3. 咱們實現了服務控制檯,能夠查看各個服務的狀態,以及獲取服務狀態變動的消息通知,還有對於服務端點 Endpoint自己進行管理。對於微服務架構來講,每個服務的端點 Endpoint應該更加智能,這是和 SOA的區別。咱們也是這樣的,對於每個服務,咱們藉助 springcloud提供的一系列管理端口,咱們的服務控制檯能夠經過這些管理端口去控制它,包括去查看和修改某一個服務節點的配置,查看某個節點的日誌,這都是能夠經過服務控制檯去實現的。

  4. 持續交付的過程,後面會詳細描述協做流程和自動化交付的機制。

技術清單

蜂巢
• 集羣和容器、鏡像倉庫
• RDS、緩存
• 負載均衡、對象存儲

服務模板
• consul
• spring boot/cloud
• Rest RPC: spring mvc, feign, ribbon,(客戶端的負載均衡)
• nginx (外部 HTTP請求的轉發), consul-template (配置和配置中心打通)
• dumb-init (Docker裏面運行服務的工具)

持續集成
• Gitlab-CE (私有代碼倉庫,協做流程和配置管理的入口)
• docker、maven
• flyway, junit, h2, mockito, spring test (持續集成的關鍵點是自動化的驗證)

鏡像構建

爲了儘可能下降服務自己和基礎設施之間的關聯,在構建基礎鏡像的時候,分紅幾個層次去考慮。

  1. 最裏面的一層,是OS和系統工具的一層,咱們是基於 Debian系統進行構建的。

  2. 應用環境的部分是和應用分離開來的,包括 JDK,consul服務發現的機制等,這裏有個小工具 dumb-init,能夠在一個 Docker裏面實現多進程。若是在 Docker裏面使用多進程會有一個比較大的坑:若是某個進程死掉,他的子進程就會變成殭屍進程,沒有辦法收回,致使咱們關閉 Docker容器的時候是須要強制殺掉的。這對於程序須要優雅關機來講是頗有問題的,Dumb-init能夠解決這個問題,另外 dumb-init還能夠實現信號的重寫。好比有些應用是須要接收一些信號,好比 ctrl+C才能結束的,爲了響應 SIGINT信號,能夠經過 dumb-init進行轉發。

  3. 在應用層的 Dockerfile會很是簡單,選擇一個正確的基礎鏡像,而後把包打進去就能夠了。
    圖片描述

基於 Gitflow代碼管理和協做流程

Gitflow是一個代碼管理的流程,咱們基於它實現了一個協做的流程。這個協做的流程體如今咱們如何去發佈咱們的新版本,若是修改線上的 Bug,若是進行開發,怎麼集成測試,最重要的是怎麼去驗證,驗證什麼東西。整個過程都須要自動化,且都是經過 gitlab-ce提供的界面。最重要的兩個界面是 Merge Request和自動化 Pipeline來作的。

全部的問題修改,全部的提測,都是經過 gitlab-ce的 Merge Request界面進行操做的。一旦 Merge Request接受以後,都會有一個跟在後面的 Pipeline,一個持續集成或者持續發佈的任務來完成後續工做,這些後續工做就是咱們交付的流程。

咱們使用蜂巢的兩個環境,來做爲開發和測試環境以及線上環境。對於特定的環境,咱們自動構建和發佈以後,會自動地進行部署,對於開發人員,QA人員,甚至線上預發環境的運維人員來講,他們只須要在 Gitlab裏面操做完了,相應的版本就構建上去了,這些版本都會在鏡像倉庫中,會對應咱們的分支,會有獨立的版本。咱們還能夠按需去部署更多的環境,去進行檢驗,好比線上的擴展驗證。

圖片描述

如圖所示,左上角爲提交的 Merge Request,右面爲 Merge Request的詳情,若是點擊 Accept Merge Request就會觸發左下角的 Pipeline進行整改發佈流程。

整個交付流程如圖所示:

圖片描述

  1. 開發有一個主分支稱爲 develop,可是全部功能的開發都不在 develop上開發,而是新開分支進行開發,能夠根據發佈的時間點肯定某個功能是否是要上線,例如圖中在這一版中,feature x, y能夠上線,因而 Merge到 develop分支,而 feature z趕不上這一版,會在之後的版本上線,因此暫且不 Merge到 develop分支。

  2. Feature x,y合併 develop分支須要通過 Code Review,一旦合併後,會觸發自動構建鏡像的 Pipeline,而後自動部署 develop環境。開發須要在這個環境裏面作集成和基本的測試,包含單元測試和冒煙測試,當集成和基本的測試遇到缺陷的時候,須要回到 feature所在的分支進行缺陷修復,修復後從新 Merge到 develop,從而從新部署 develop環境。當開發任務代碼質量能夠達到的時候,方纔提測到 QA。

  3. 有一個 Release分支用於作測試驗證,提測的發起是由 develop分支 Merge到 release版本實現的。每次作 release的時候,首先會從 Master分出一個版本到 release,Master分支的版本是當前的線上版本,則 Develop Merge到 release,實際上是和線上版本的一個合併,保證當前的開發版本和線上版本能夠兼容。此次 Merge會觸發 Pipeline構建鏡像,而且自動發佈 release環境, QA能夠對這個環境進行自動化測試,或者手工測試,保證代碼能夠達到發佈的質量。若是測試出現缺陷,則須要回到 feature所在的分支進行缺陷修復,修復後從新 Merge到 develop,從而從新部署 develop環境,在 develop環境測試完畢後,再次 Merge到 release,而後 QA再測試,如此反覆,直到能夠達到上線標準。

  4. 一個 release分支能夠達到上線標準,則將 release分支合併回 master分支,此次 Merge會觸發 Pipeline自動構建鏡像,自動部署預發環境。線上運維人員能夠對預發環境進行測試。

  5. 若是預發環境沒有問題,線上運維人員能夠從鏡像手工部署兩套線上環境中的一套,如圖中 Online A和 Online B,作灰度發佈,新老版本先更新其中一套環境,而後前端經過負載均衡器將請求不斷的從老版環境切換到新版環境。

  6. 若是須要性能測試,性能測試人員能夠手工從鏡像部署一套性能測試環境進行測試。

  7. 若是線上發現缺陷,則須要從 Master上分出一個分支到 hotfix,hotfix修復完畢進行測試後須要合併到 Master分支,同時須要合併代碼到 develop分支。

配置管理

圖片描述

如圖是一個配置管理的流程。

全部的配置文件都放在代碼倉庫 Gitlab裏面,進行代碼級別的管理。

編輯配置文件 app.properties和 app-A.properties,而後提交,經過 Merge Request提交到 Gitlab裏面。

在 Gitlab界面裏面,點擊 accept進行代碼合併,合併後觸發 webhook,調用配置中心。

Git2Consul從 Gitlib中 pull全部的配置文件,而且將配置文件的內容經過 consul的客戶端同步到 consul中。

Profile=A的 app和 Profile=B的 app經過 consul的客戶端將配置從 consul中配置到服務中,完成配置的管理。

總結

最後總結一下就是:

  1. 最大化利用開源工具和雲端技術創建微服務和敏捷基礎設施,構建 Cloud Native 應用,充分釋放雲的潛力。

  2. 其次,基於容器技術自動化構建、發佈和配置流程,改進敏捷交付環境和產品快速迭代能力,及時有力支撐業務。目前三拾衆籌基於網易蜂巢平臺,重新系統設計到上線僅需1 ~ 3周;

  3. 最後,經過實踐打磨的方案才能適合本身,開放性是選擇雲平臺關鍵評估因素

相關文章
相關標籤/搜索