傳統軟件項目交付中,各個角色分工明確,也暴露了不少軟件交付中的不少問題。 DevOps的工做方式恰如其分的解決了其中一些問題,那麼如何從傳統交付流程遷移到具備伸縮性,靈活性,以及快速響應的持續交付中來,這種新的交付部署方式會給團隊帶來哪些變革,以及如何在大規模團隊中落地。大規模團隊將如何標準化的進行持續交付,以及它帶來的便利和下一階段的挑戰是什麼?前端
本文的五個部分:程序員
傳統流程交付模式;編程
持續集成的交付模式;後端
微服務下的持續集成交付模式;緩存
標準化的演進案例;安全
下一階段的挑戰。服務器
首先,有這樣一個案例:客戶的IT部門剛剛成立,公司將這個部門交給了一個很是資深的產品經理(他原來是業務經理)。他負責整個IT部門的IT化構建,手下有一批業務人員,同時也是未來會是這批軟件的使用者。他在收集一些反饋信息後給出了一些大型的需求列表,而後交給了咱們研發團隊。架構
咱們研發團隊和設計師溝通了一下,獲得了一個設計版的結果進行了封閉式的開發,大概持續了6個月。產品作出來而後,研發團隊將它交給了測試團隊,並進行了大量的測試和全部的分支覆蓋。通過幾回測試不經過打回修改後,最後的結果是成功上線。框架
上述就是一個傳統瀑布式的開發。有不少的公司曾經經歷過相似的開發模式。這種傳統瀑布式開發有如下的特色:less
第一,交付週期很是長,從產品的需求和最後的部署大概經歷一年的時間;
第二,這整個過程當中沒有任何的交付,交互也很少,也就是產品的需求到最後的開發的整個過程當中只有銜接部分有必定的交流,並無太多需求上的修改、調整和反饋。
這種交付方式就是無持續集成的交付模式,有如下特色:
第一,它的代碼集成會很困難,由於全部人都在同一個倉庫上工做,那麼它天天就會有不少的代碼提交和衝突。
第二,測試難,依賴性高。當咱們的軟件部署到測試環節的時候,測試會將全部的需求進行一一測試,也就是測試會經歷漫長的時間和全部的需求進行對比,這對測試的壓力和測試難度也是很是高的。
最後,手動進行發佈,發佈對某些人的依賴性極高,並且風險大,易出錯,也就只有1、兩次成功發,這個軟件就算是完成了交付的一部分,達到了可用的狀態。
隨着如今敏捷宣言還有持續集成(持續集成是由2014年提出的概念)的提出,咱們在開發過程當中進行大量的,而且天天都要進行集成,這樣咱們能減小上線前集成所面臨的壓力。
上圖是Jef所寫的關於持續交付的書,它採用方法和理論是以迭代的方式將軟件交到用戶手上。那麼,再加上硬件條件的提高,讓持續集成在雲計算的發展下將變得觸手可及,即:虛擬環境容易獲取。這樣具有了硬件和軟件條件,因此大部分人就開始享用持續集成的交付模式。
持續集成的交付模式的特色:
第一,交付週期短。持續集成通常是迭代的方式交付,咱們通常兩週會有一個版本從端到端的構建、測試到發佈。而且,溝通很是頻繁,它的構建測試和溝通發佈流程中都會有不一樣的交互,好比說需求和開發人員的溝通,測試和需求人員一塊兒討論咱們的測試文檔和測試策略。
第二,測試完備。咱們開發過程當中會有測試金字塔的概念,它的底部是大量的單元測試,開發會把全部的功能進行單元測試,金字塔的中間層是集成測試,頂端是端到端測試或者是系統大集成測試。因爲手工測試成本很是高,有了大量自動化測試覆蓋後,,它的數量也會比較少。
然而,測試的迴歸,也就是每次構建一個軟件時,咱們怎樣保證原有的功能是正常工做的,那就有大量的迴歸測試。而在持續集成的環境中,由於有大量的自動化進行覆蓋,因此咱們迴歸測試的次數就會大大下降。
最後,自動化程度高。因爲咱們進行每兩週都會有一牆之隔迭代,就會有一個部署,那麼這些當中咱們哪些東西是要重複作重複作,咱們怎樣避免這樣重複的事情?咱們就要自動化這些事情,採用自動化構建、自動化測和自動化部署一套腳本步驟作下來,這樣能夠避免大量重複的工做,同時也加強對項目部署時的信心。
下來咱們來對比一下持續集成和瀑布式這二種開發模式,能夠看到持續集成是以4小步快跑的方式來進行迭代式交付,瀑布式是以時間爲軸的線性交付。
另外,持續集成和瀑布式相比還有些不一樣之處。第一,快速發佈。持續集成發佈更加快速,並且它可以及時獲得用戶的反饋,也就是我部署之後用戶可以提出一些反饋交給業務人員,業務人員跟開發溝通後,進行下一個版本的迭代,調整優先集,調整咱們的需求。而後,它的速度更加頻繁,也保證軟件的質量更高。
第二,由於在整個的測試過程當中,包括自動化測試和人工測試。測試介入也是比傳統的測試介入提早好久,因此它能保持測試的穩定性。
第三,對於進度把控來說,持續集成模式,因爲咱們可以持續地看到咱們所產生的產品是什麼樣的,這樣它對項目的管控可能更有直觀的感覺。
最後,團隊協做的提升。由於在持續以前的環境中,不一樣的角色溝通更加頻繁,因此持續集成的團隊協做相對於瀑布式的任務交接的方式會有更好地提升。
首先講一下微服務,微服務爲何誕生?爲何會有這樣的架構演進?
微服務是相對於單體架構和麪向服務的架構,也就是傳統的單體架構。一個服務器接受全部的請求和處理,那麼它就會面臨一些問題。第一業務複雜的時候代碼量變得很是大,咱們可能經過一些模塊的方式進行劃分,可是仍是難以具體去分功能的模塊。
第二就是若是面臨大量的訪問請求的話,傳統單體架構會面臨一些瓶頸,複雜的業務和數據查詢會使系統卡死。面臨這樣的問題,咱們須要進行緩存處理或者下降業務複雜度。微服務的出現,恰如其分的解決了這樣的問題
下面我來說講微服務架構的一些特色。微服務有5個特色:
領域建模;
去中心化;
服務隔離;
獨立部署;
高度可監控。
對於單體架構而言,業務分離通常是採用模塊劃分的方式,好比把xxx,把用戶做爲一個模塊,訂單做爲一個模塊,支付做爲一個模塊。而對於微服務咱們能夠將不一樣的模塊作得更極致,能夠將它成爲一個單體的運行服務,能夠經過協議的方式進行溝通。
這種服務的分割方式能夠採用DSL,不一樣服務的性能要求和不一樣服務的需求要求,咱們會採用不一樣的領域語言。而後咱們這種拆分更加貼近業務原型,好比說支付模塊面臨支付有漏洞安全性的問題,咱們怎樣解決,以後回滾,失敗時怎樣處理,對於這種領域性的問題,會創建更加貼切的模型。
再來說講去中心化。原來單體架構一箇中心,它須要處理全部的請求,一個錯誤或者異常可能致使整個軟件崩潰。對於微服務而言,每個服務高度自治,這樣的結構使得軟件更加健壯,由於一個服務包宕掉不影響其餘的工做,這樣的服務架構可以表明組織結構。
由於目前而言,每5我的能夠管理4—5個服務,因此我們公司一百個服務,那就有十幾個Team,每一個Team都是扁平的結構,這種團隊的架構就跟微服務是同樣的。
接下來談談服務隔離。由於每個服務都有獨立的服務器,因此服務經過契約溝通,咱們是經過Swagger來描述API的規範和參數返回值,給其餘服務消費。另外就開發隔離而言,不一樣的服務採用不一樣的編程語言。
每個服務都分離開發,失敗也能隔離,當一個服務宕掉其餘的可以正常工做。
獨立部署就是咱們能夠想要選擇本身須要的版本部署,也能夠選擇何時部署。因此微服務的部署是獨立的,能夠自主的靈活的部署,並且不一樣的部署不會相互干擾。咱們在部署一個支付模塊時,不用部署從主頁獲取信息的服務,因此主頁部署也是隔離的。
最後說一下高度可監控。高度可監控與原來的監控性能狀況不一樣。
對於微服務來說,咱們要對每個服務進行性能監控,這樣帶來的好處是能準確地進行監控服務的運行時間的消耗。
這是咱們本身公司的一個頁面,這是監控其餘微服務的健康情況,來查看不一樣服務是否可以正常工做。並且你能獨立地監控每個服務的性能消耗,這時咱們就能更加有效地進行擴展,由於咱們知道哪些服務是瓶頸,哪些服務的性能CPU瓶頸高,咱們就會根據實時數據進行服務擴展。
接下來咱們分享一下澳洲的IT公司,爲何會有這樣的標準化,統一化的持續交付模式。當咱們談論標準化時,咱們談論的是怎樣將它規模化,因此當咱們把服務從10個上升到100個,咱們怎樣解決這些重複,這裏面可能存在的一些問題。
我來介紹一下咱們公司的業務場景,可能接下來說實踐時更有一些感覺。咱們公司是一家澳洲最大的博彩公司,當歐洲和澳洲有這些體育賽事時就會有大量的訪問,尤爲是比賽前半個小時,一分鐘的訪問量高達十幾萬的下注率,性能要求很是高。
咱們以前開發了一個軟件是單體架構,花了兩年的時間,最後投放到市場上,當這種大型比賽出現時,好比世界盃、歐冠,性能瓶頸和服務器響應能力很是慢,不能知足市場需求,致使了其餘的競爭對手,原本咱們是澳洲最大線下門店巨頭,如今線上咱們並未作的第一。
由於那個時候咱們用了單體架構的軟件,並無有效地佔領市場,用戶的體驗很是差致使用戶選擇了其餘的品牌進行下注。公司痛定思痛,決定花重金從新開發一套全新的IT系統,也就是我要給你們介紹的微服務下持續交付的軟件。每當這種大型的體育賽事,它的處理響應能力還有Devops對於監控咱們的性能問題,是徹底沒有任何性能瓶頸,也就是如今是比較成功的案例。
接下來我要給你們講一下持續交付流水線的構建圖。上圖中每個小方塊就是一個服務,每一個服務都有不一樣的部署階段,好比UAT是給開發集成代碼的部署版本。
而後,還有一個給測試用的集成平臺,就是自動化地triger一下,就能夠把代碼分離部署到下一個環境,最後一個是產品環境的產品的部署。因此這些都是自動化的,每個服務都是獨立部署。
標準化的持續集成的建設包含:
先後端分離架構;
Docker做爲容器來提供微服務;
Api gateway;
AWS ECS;
服務發現;
日誌;
監控;
Lambda。
首先講的是先後端分離架構。由於咱們的業務需求是要有網站、PC端、手機端和Pad端;換句話說全方位讓你們接觸到業務。同時這也比較尷尬,由於在大多數國家是不容許這項業務存在的;可是在澳洲、歐洲博彩是稅收的大頭。
因此咱們要將先後端分離開來。先後的框架使用的語言都不一致,也是分離讓合適的人作更合適的事情。先後端經過契約(Swagger)描述本身的接口,經過Rest API進行溝通來溝通。這種分離方式能夠下降服務器壓力。
咱們前端部署在兩個Nginx服務器上。訪問Server前端的頁面,也就是每一個人只是訪問了靜態服務器頁面。這個頁面加載時會發不少的請求來獲取數據。
在這個靜態服務器被訪問以前,咱們會有 load-balance 來決定哪一個服務器Server裏的靜態頁面被訪問。在這以前,咱們有CDN來給前端頁面作緩存。也就是說一個區域的人訪問前端頁面,是由緩存提供給的。因此,前端服務器的壓力會減小,而且大部分都是緩存起來了。
可是,緩存的前端並未減小後端服務器的壓力。舉個例子,好比說10萬人要訪問賽事信息,這是很是大的性能要求。10萬人同時訪問賽事信息和賠率時,10萬人是平均數字,到了峯值最高,那麼怎樣解決呢?下面的小節來揭曉。
對於上述的問題,咱們首先採用Docker的部署和開發方式。Docker的好處是水平擴展性好,全部的容器都是能夠隨機調整個數和數量。
第二,它的服務是隔離的。關於Docker開發,我剛纔提到了它和微服務的架構是互相不干擾,服務的健康情況不會影響到其餘的服務。在構建服務的時候,咱們須要重複構建100多個服務。從0到1須要花不少的時間,從1到100先須要想到怎樣構建通用的模板,由於每個服務咱們都要構建。
首先,咱們構建Docker Image;而後打包怎樣作單元測試;最後上傳到Docker HUB中去。這些工具都成一個模板,只要把這些模板應用到Docker,Docker會自動打包上傳到DockerHUB裏面去。咱們採用的一個SaaS的平臺工具(Buildkite)幫助來作這個事情。
Docker也會涉及不一樣服務之間的通信。由於某一個服務的變化可能影響到其餘的服務,因此大家在交付過程當中可能有一些規範不同,這就須要的數據不同。咱們經過Swagger定義這些規範。
當一個服務的Swagger發生變化,它的信息發生變化,就會通知其餘的服務,看那些服務會受到契約變化的影響。若是一致,就經過。若是不一致,就會及時告訴你兩個服務之間有變化,並要求你必須解決。
服務之間能夠經過Stub進行測試。可是,有這麼多的依賴我怎樣進行集成測試?這個須要用戶的信息。但是這些模塊沒有信息,就要經過Stub進行交互。
最後,不一樣服務能夠採用不一樣語言實現。其中最重要的一個模塊就是下注的模塊;就是說怎樣把一個訂單最後支付而後讓它成功地下單。
以前,咱們用JS。它是一個單線程的動態語言,性能不是特別好(Node是單線程)。而後,咱們也是參考了Uber,採用大量的微服務架構,而且它有不少不一樣服務轉型的案例。接下來,咱們採用了Google出來的一款語言,它有大量的指針概念,你不用建立不少的對象,以下降內存消耗的方式來提升語言的性能。
因此,咱們微服務90%的是用JS,有些消耗更大的採用性能更高的語言。另外,咱們還採用Lambda,這不是一種語言是一種架構方式,和其餘服務並列在一塊兒使用。
當前端有大量的請求訪問到服務器端時,因爲咱們服務器端的性能不是很好,那麼服務器端怎樣處理壓力?以及,怎樣作這些請求?
API Gateway是解決這一方法的重要手段。當有大量的請求時,它會把請求導到咱們信息服務中去。可是,訪問服務以前會有一個緩存,即訪問同一個賽事信息,就直接把這個緩存給到前端。那麼這些信息沒有直接進行查詢,而是緩存返回給了前端。因此,緩存是用來解決大部分靜態信息獲取壓力的方法。
再則就是作統一的認證。在不一樣的服務間,80%的服務是須要登陸信息,就是說登陸之後才能操做。怎樣解決不一樣信息之間的登陸問題?難道須要每一個服務在訪問時必須訪問登錄認證服務?解決方式就是你的訪問不是訪問服務,而是網關。由於它儲存了用戶信息,也有token過時時間。
API Gateway全部請求訪問網關時,咱們就能夠記錄下全部的訪問信息和全部的日誌。在不一樣的服務之間的接口是不規範而且不一致,API能夠幫助咱們作請求格式的轉換。
上面咱們提到有一些服務須要進行大量的擴容。這個擴容過程當中咱們怎樣肯定新起服務的端口?咱們採用的是Consol的服務發現的工具。
這個服務工具的大概工做原理是:每個ECS hosts 上都有一個Consol的service。由於全部的Docker都部署在ECS上,ECS上不只部署一個服務,還能夠同時擴容3個、5個、8個。可是,這些服務都是隨機端口,你不知道地址在哪裏。
這個時候,每個ECS上都有一個 Consul 的實例。這個 Consul 實例會將ECS上全部的服務的地址、IP和端口記錄下來上傳到中央控制服務發現區。而後,API Gateway直接訪問Console Master來知道哪一個服務佈置在哪一個端口上、哪一個IP上。這樣就解決擴容的時候,服務器在隨機端口的應用狀況。
監控日誌對於產品性能是很是重要的。對於傳統單體結構,多是全部的CPU都在對應的服務器上,一旦擴容全部的都擴容了。可是,咱們想精確地知道這些服務的瓶頸,並實現定向地擴容來有效地解決瓶頸問題。對於日誌而言,它知道咱們產品的問題,能夠進行準確地定位。
因此,日誌是直接的手段也是常常用的手段。於是對不一樣的服務咱們會採用統一規範的日誌,好比說記錄用戶的IP,記錄用戶訪問的時間,記錄請求的數據以及記錄一些錯誤。
Lambda的特性是:
計算服務
無服務器
自動擴展
日誌和監控
因爲咱們有的服務不須要任何存儲,只須要計算資源。好比說一個生成隨機數,咱們須要給用戶賠率隨機翻倍的功能。這樣的話,你能夠天天有一個權利來得一個隨機翻倍的次數。這個服務只須要產生一個隨機數給下注的服務使用,因此隨機數不必單獨開一個ECS來單獨服務這個服務。
Lambda就是無服務器的功能。而後,它能夠自動擴容。上圖是Lambda的狀況,藍色的是次數,紅色的是規模,因此是很是吻合的。它對於business是很是適合的,並且這種場景是很好的。
具體某個服務的架構圖
這是咱們的一個小的微服務的架構:用戶訪問一下Gateway,而後訪問你的服務,服務和性能記錄到不一樣的雲平臺上,Ops就能夠監控如今的雲平臺的狀況。
最後,講一下面臨的挑戰,主要是人的挑戰,還有一些技術的挑戰。
人的挑戰是咱們如何管理咱們的組織。由於大型的傳統金融保險公司都是金字塔式的結構,就是經理、職員、小組。這種結構就會對傳統的人員架構產生衝擊。每個小組都是一個微服務,有一百個就是二十個、二十個小的團隊。這些小的團隊怎樣組織在一塊兒。不一樣的服務之間都有不一樣的小組,那這些小組之間的溝通怎樣解決他們之間面臨的問題的。這就產生了孤島效應,你們不知道對方在作什麼,也不知道對方面臨的問題是什麼。
因爲不一樣小組之間有本身的優先級,每個都認爲本身作的優先級是最高的,這就面臨資源競爭。咱們是否是要招最好的程序員,用最好的資源。
還有技術債,不一樣團隊面臨的技術債不同,怎樣解決一些別人已經解決過的問題。這就須要團隊信任。雖然,不一樣的團隊之間進行交互的頻率很是少,可是可能會存在信任問題,即:我怎樣使用,你的API是否是不穩定,前端獲取數據是否跟你不一致等問題。
總之,微服務只是爲了解決問題的手段,不必把全部的事例都以微服務實現。只要解決本身的問題,它就是一個正確的方式。
http://mp.weixin.qq.com/s/4famcSoL-ObEBdfJ4Z0ckw