導語
6月23日,蘑菇街技術專家蔣志強在GITC全球互聯網技術大會上發表了題為《持續集成和發布在美聯的實踐》的演講,介紹了蘑菇街和美麗說合并成立的美聯發布系統的演進和特色。
演講嘉賓介紹
蘑菇街
發布作為應用上線前的最后一個步驟,一直以來都是運維做的比較頻繁也是風險比較高的操作,發布系統不僅要做到提升發布效率,更重要的是保障發布過程中系統的穩定,減少因發布導致的故障。本次演講主要包括三個部分。一是發布系統的演進,二是美聯發布系統的實踐之路,三是發布系統的特色。
智能運維 系統做決策
發布系統主要可以分成三個階段,首先就是人肉運維,什么都要靠自己。然后進化到自動化運維。自動化運維分兩個階段,首先是使用一些開源的工具,搭建一套運維體系、運維工具。但是隨著公司業務的繼續發展,慢慢的會發現,雖然開源軟件功能非常強大,但這些用開源軟件搭建的運維工具不一定能適應公司自己的需求。但是如果要進行二次開發或者功能的增加,成本也很大,因為不了解它具體的實現邏輯。慢慢的就會進入到一個自研運維系統的過程。
最后,智能運維,我個人理解,智能運維跟自動化運維最大的區別就是,智能運維可以自動做一些決策。自動化運維,所有的操作還是要手動觸發,但是智能運維,系統會自動對各種數據進行分析,做出合適的決策。
舉個最簡單的例子,應用擴容。雖然現在有一套比較完善的擴容系統,但是還是需要由PE自己去決定擴容的時間和臺數。但如果是智能運維,把智能的擴容系統做好以后,系統就可以自己根據監控的數據或者其他系統的數據,自動的決策是否需要進行擴容。當然,這是我們的目標,我們正在朝這個目標努力。
蘑菇街技術架構演進
蘑菇街創業初期的技術架構,開發語言用了PHP,運行環境用了非常流行的四件套:Liunx、PHP、MySQL、Nginx。技術架構很簡單的分成三層,用的基本上全是開源。只支持PHP的發布。PHP發布,整個邏輯比較簡單,只需要把代碼打包放到服務器上解壓。有了這個發布系統,至少可以做到可以選擇需要發布的文件,并且知道需要發布的這個文件的版本號是多少。把運維從發布上解放了出來。這個過程中參與發布的主要是開發而不是運維。
中期,蘑菇街從一個單純的導購網站變成了一個電商的平臺。作為一個電商平臺,就必須要有的詳情頁、購物車、下單、支付這些子系統,包括一系列用來支撐的后臺的運營系統和基礎服務。臃腫的PHP工程在一個代碼倉庫里面,如果把這么多電商業務都放在PHP這一個倉庫里面的話,上百個開發對于同一個倉庫進行開發,不可想象。所以要把業務進行拆分,JAVA服務化。
我們把應用逐漸拆成JAVA一個一個的服務化。為了適應這個需求,就有了第一版的JAVA的發布系統。JAVA的發布系統和PHP有很大的不同,PHP只要解壓,而JAVA還要重啟容器,這就涉及到在重啟之前要關閉報警、切走流量,否則應用一重啟一發布,就會收到一大堆的報警短信,影響用戶的訪問,這些都是不可接受的。發布系統的發布邏輯就會有很多的步驟。
但是隨著時間的進步,公司業務持續的發展,蘑菇街和美麗說合并,雖然兩家都是電商公司,但是在底層的運維基礎上,還是有比較大的不同。多了很多不同類型的應用,這些應用都要納入到發布的管理里面來。
發布系統的構建之路
首先要做運維工具,最重要的一點就是要把標準化做好。標準化跟發布相關的,主要有兩點,一個是基礎環境,和基礎環境的配置需要標準,OS、JDK、TOMCAT等等。另外,應用要支持標準。為了支持這些標準化的落地,有一個應用的配置管理中心會管理應用最基礎的信息,人員角色、應用類型、啟停的命令、軟件包的信息。雖然在應用規范里面定義了這個應用的一些啟停的命令是有標準和默認的模板的,但是為了兼容性更好,功能更強大,我們開放了自定義的功能,它是可以修改默認的。如果是完全標準的應用,可以不做任何的修改可以用。
發布系統的依賴是什么?如下圖所示。
架構主要是兩塊,一塊是前端的,發布流程的控制、用戶的界面等,下面是Python寫的Worker,用于構建、部署,中間通過MQ進行解耦的操作和任務隊列,中間通過DB進行數據的交換。
研發流程,首先是發布的流程,先線下進行發布,然后預發進行發布,最后到線上進行發布的時候,之前還有Beta發布,確認沒問題了才最終進入線上的發布。線上的發布和預發的邏輯是一致的,但是從預發到線上就比較不一樣了,會有一個Check List檢查,只有通過了才允許進入線上發布。提交完以后會有一個審批流程,審批流程會根據時間的不同、硬件的不同,發布流程不一樣。
默認主干都是Master。假如有一個需求需要進行開發,就會從Master拉出一個開發分支,進行需求的開發。開發完成后上線,開發系統就會從Master上拉出一個release分支進行發布,最后合并到Master,完成代碼合并操作。
新建變更操作也是在發布系統中完成的,我們希望開發可以不直接操作gitlab,因為操作gitlab風險比較大。另外,我們提供了兩種變更創建的方法,一種是新建分支,還有一種是導入分支,從現有的開發分支中再創建一個分支出來,這時候可以用導入變更的功能。
而集成,部署環境有三個,線下、預發、線上。中間發布的基礎的信息,下面是發布的過程,大致可以總結成三個,一個是代碼合并,一個是編譯構建,第三是部署。對于特殊的應用類型,可能中間還會多幾個其他的操作,比如Docker的發布,那么就在編譯構建完成以后,多加入一個Docker鏡像的構建完成。如果帶有前端的文件,在代碼合并之后會有合并前端的操作。
最下面一個是集成區,一個是待集成區。集成區就是當前發布,待集成區就是變更開發完成以后,提交發布就在待集成區,可以隨時加入集成區也可以隨時退出來。
不允許把變更拖入線上環境中,所有的線上發布都是預發過去,而且線上的release分支都是預發的release分支。首先保證預發都是成功的,然后預發右邊集成區的Check List全部通過,這也是為了保證業務的穩定性,最后才能拖到線上。
這時候我們遇到兩個問題,第一個,你往上合的時候難免會遇到一些沖突,有可能是兩個Feature分支之間發生了沖突,也可能是Feature分支和Master之間發生了沖突。怎么解決這個沖突?沖突依靠自動化系統來解決,現在看來還是不太可能。我們提供了一個思路,就是如果發生沖突,還是強制合,但是會告訴這個分支沖突了,手動把這個release分支check out出來,本地解決了再上去。但是,這樣解決一次沖突還可以,下次再沖突了怎么辦?這涉及到release分支的更換策略,解決過的沖突不會再造成沖突。只有撤下一個release分支的時候才會更換這個release分支。這個辦法也能很好的解決經常發生沖突的問題。
我們希望每一次的構建環境都是干凈的,都是統一的。可能在一臺構建的機器上,同時會構建十幾個甚至是幾十個任務,我希望它們之間是互相獨立的,互不影響的。所以我們用Docker來進行構建,每次構建都會起一個Docker鏡像,把代碼掛在這個鏡像里面,在鏡像里面執行構建的命令。最后把產出拿出來。
部署的流程里面有很多的步驟會依賴到OpsAgent,要在目標服務器上進行操作。機房那么多,不可能把所有機器都跟這臺發布機器進行通道打通。首先通過Agent檢查目標機器的環境,應用機器在SA交付以后,是不是安裝上了應用需要的東西,應用的初始化環境,用戶有沒有創建,部署的目錄有沒有創建,基礎的環境要進行檢查。然后下載更新報,關閉監控,Tesla下線、Web下線,然后停止應用,更新應用,再啟動。這時候有一個健康檢查的邏輯,最后就是兩個上線,把流量引進來,把監控打開。
如果發布的發布策略是分批發布,這一個應用有好多分組,在分批策略的時候不會把所有分組的所有機器放在同一批。后面的不自動開始,就是構建完成之后,到了發布界面就停住了,需要手動的點發布按鈕進行這一批次的發布。正常的JAVA的應用,一臺機器發布在一分半到兩分鐘左右。分十批發的話,這么一次也只需要十五到二十分鐘。
每個應用在規范里面都會強制要求有檢查健康。這個機器需要做一些操作,通過返回值是否Success,來判斷是否成功。首先檢查核心依賴是不是能夠連上DB或者Cache,依賴的其他應用是不是能夠正常的調用到。還有一些特殊的應用需要預熱數據,不管是緩存中的數據,或者是編譯器的預熱。有了健康檢查以后,基本上可以保證應用不會有太大的問題。
我們在不同的時間審批鏈是不一樣的,最普通的日常發布,周一到周四。如果是非工作時間,下班以后或者是節假日,就需要緊急發布,這時候需要研發D進行審批。最特殊的,例如6·16大促,為了保證穩定,原則上除非是緊急bug,否則不允許做發布的,這時候要做發布需要CTO進行審批。這些時間都是在系統中可以調整的。回滾主要分成兩種,一種是基于基線的回滾。發布完成之后,會向基線插入一條數據,里面記錄了本次發布的master分支的版本。想回滾到哪一次,就按后面的按鈕幫你回滾到這個版本。
還有一個回滾的功能就是緊急回滾,在發布過程中發現應用有問題,需要進行緊急的回滾。每次都會把上一次的war包保存一份,直接把上次的替換過來重啟應用,這就是緊急的回滾。
蘑菇街發布系統的特色
首先,實現研發流程的閉環,研發流程從需求到發布,只有在變更創建開始到發布那一段是在發布系統里面的。之前的需求、項目管理等等,都是在另外一個項目管理的PMO系統中實現。這兩個是獨立的系統,開發的時候要在這兩個系統中來回切換,非常不方便。我們把它和項目管理系統進行了整合。項目管理系統中可以創建關聯變更,在變更發布后更新需求、項目狀態,這樣就完成了項目管理的閉環。這樣的好處就是,在需求管理系統中可以很明確的看到,某一個需求是哪一天什么時候發布上線的,在發布系統中又能很清楚的看到,某一次的發布是發布了哪些需求。
第二,多機房多分組的構建。因為我們有一個需求,同一個應用部署在不同的機房,可以按照不同的機房不同的分組創建不同的參數,部署的時候會根據應用機器所在的機房或者分組使用對應的包。
第三,多套環境。我們可以根據分組只發布到某一個分組,就相當于變相提供了多套環境的功能。
第四,Jar包檢測和Diff。Jar包沖突會有很多的問題,明明寫的時候是好的,部署上去就是不正常。原則上我們不允許使用Snapshot的包,因為它不可控。Jar包的Diff,會告訴他哪些Jar包有沖突,哪些版本不能再使用。基線和哪些Jar包的版本不一致。
第五,二方庫的發布。有兩種,一種是某個應用的子模塊,還有一種是像中間件的產品。發布系統能為線上的穩定性做哪些保障?目前四個,前端掃描,前端應用,JS的文件的掃描,對接了前端團隊的系統,對這些前端文件進行掃描。安全掃描,我們對接了一個安全的系統,對JAVA應用進行靜態的代碼掃描。集成測試,我們有一個測試系統,在發布的時候同時對發布代碼進行單元測試、接口測試。性能監控和壓測,這些系統不是發布系統本身提供的,都是對接了我們內部團隊的系統,把它集成到系統中。我們的Cobra系統會對代碼進行掃描,如果掃描不通過也是不能發布的。