天天看點

互金平台灰階釋出的三段式探索與實踐【轉載】

本文将從某網際網路金融平台的線上版本釋出工作出發,介紹了整個釋出過程的優化及改造,以及對于灰階釋出的探索及最終實踐。

先要說明一點,任何脫離實際業務的技術工作都是耍流氓,技術需要服務于業務。是以,本文盡量淡化了業務方面的因素,聚焦于技術層面,建議在實際運用中還是要根據各自的業務場景去變化和調整。

其次,本文重點描述了線上釋出的實施改造思路及演進過程,但對于其它相關聯的一些點,比如釋出規範流程、配置管理、監控、自動化工具的實施等不做過多涉及,如有興趣可後續交流。

應用邏輯架構

圖1 應用邏輯架構圖

用戶端  

包含手機APP、Web頁面(主站/營銷站等)、H5頁面等,即通路發起方,來自于真實使用者。

WEB  

主要實作轉發功能,利用Nginx實作,同時包含一些業務政策和跳轉設定。

BFE  

Business Front End,業務前端,實作接入和業務聚合功能,有點類似于API網關,但和業務有一定耦合,用Tomcat war包釋出。

APP  

業務應用層,實作具體業務功能,目前幾十個APP子產品,用Tomcat war包釋出。

Data  

資料層,如資料庫、緩存、分布式檔案系統等。

公共元件  

包含配置中心,任務排程中心,服務注冊發現中心,消息隊列等(這4個公共元件和灰階釋出有一定關系,後續會單獨介紹)。

注意:

WEB->BFE:通過Nginx反向代理轉發流量,HTTP請求;

BFE->APP和各APP間調用:通過在服務注冊中心内注冊,進行RPC調用,由BFE統一傳回。

公共元件介紹

公共元件各家公司差異較大,有自研、純開源或二次開發,我廠綜合各方面因素後,選型如下:

配置中心

Disconf,百度的開源産品,用起來一般,更新較慢,基本滿足配置管理需求。各APP啟動時會從Disconf中擷取配置資訊,也支援熱更新。

任務排程

Light task scheduler,簡稱LTS,用于Job類的統一管理排程,相當于統一管理的Crontab,業内相似的有當當網開源的Elastic-Job,不過LTS相對來說比較輕量級。各APP啟動時會在lts中注冊為任務節點,執行計劃任務。

服務注冊發現

Dubbo,阿裡開源産品,有一定年數了,經受過考驗。如果重度依賴Spring的,可以考慮Spring Cloud系列。各APP啟動時會在Dubbo中進行注冊Provider和Consumer 的Service接口,用于互相調用。

消息隊列

RocketMQ,也是阿裡的産品,性能不如Kafka,但用在金融行業應該沒問題。各APP啟動時會連接配接到RocketMQ中,進行後續消息的消費。

釋出實踐1.0及問題

介紹完基本背景後,我們來聊聊核心問題:線上釋出。

這裡的線上釋出指上文中的BFE和Service服務,都是基于Java開發,部署方式是war包,容器是Tomcat。

原始釋出方式如下:

互金平台灰階釋出的三段式探索與實踐【轉載】

圖2 BFE釋出流程

互金平台灰階釋出的三段式探索與實踐【轉載】

圖3 APP釋出流程

大家可以發現,BFE隻是多了一部分切換Nginx的操作,是以後續重點對APP的釋出進行說明。

上述APP的釋出方式實施不久後,就遇到了幾個問題,而且對業務造成了一定影響,總結有如下幾條:

APP釋出時,直接重新開機Tomcat,導緻節點正在處理的請求會受到影響,嚴重時會有資料異常。

APP釋出時如果節點正在作為task_tracker運作lts任務,會導緻任務失敗并retry。

APP釋出時如果節點正在消費RocketMQ中的消息,會導緻消息消費異常,甚至進入retry或dlq隊列。

APP釋出完成後沒有即時驗證機制,直接暴露給使用者,如有異常影響面很廣。

線上無法同時存在新老版本的APP來用于長時間的驗證。

竟然有這麼多問題,淚崩~~

仔細分析上述問題,可以歸結為兩類:

平滑釋出問題:即以上問題前三點。釋出時要盡可能平滑,對使用者及業務影響最小(補充一句,當然也可以通過幂等及自動或人工補償機制去完善,這是另一個次元)。

釋出驗證問題:即以上問題最後兩點。釋出完成要能小範圍的即時驗證,最好是能定位到個體,且如有需要,驗證時間可以延長。

接下來就結合實踐,介紹下如何解決這兩個問題。BTW,在過渡期間内,大家隻能熬夜停服釋出或者在晚上低峰期釋出,苦不堪言。

釋出實踐1.1—平滑釋出

平滑釋出,即釋出時盡量減少對業務的影響,能夠柔和地對服務進行下線。為做到這一點,必須要結合現有公共元件的特點,在代碼部署前先對服務進行平穩下線,确認下線完畢後再進行釋出工作。

1

  Dubbo

由于所有APP的接口都有在Dubbo中進行注冊,是以需要有辦法能夠對其Provider Service接口進行下線或屏蔽,使其不提供服務,即其它服務無法調用它的接口。

Service接口下線後,此APP機器自然無任何流量流入,是以也無流量傳回,達到下線APP機器的目的,然後即可部署代碼。

官方有提供Dubbo-Admin工具,用于對Dubbo中各APP及其Service接口進行管理,裡面自然也包含有實作下線的功能,可以有3種方法:

屏蔽,貌似一直沒有效果;

禁用,可以成功禁用;

權重調節,可以設定0-100的權重,設定為0時即不提供服務。

經過選型,我們選用更靈活的權重調節方案,通過Dubbo-Admin對需要下線機器的APP應用接口權限設定為0。

互金平台灰階釋出的三段式探索與實踐【轉載】

 圖4 Dubbo權重調節

 2  RocketMQ

同理,如果要被重新開機的APP機器正在消費消息隊列中的消息,也需要等消費完成後才能進行釋出,是以需要查詢該APP機器所對應的Consumer Group及綁定的Queue,然後下線,即解除綁定。在RocketMQ的web-console中我們增加了對應接口,進行下線。

互金平台灰階釋出的三段式探索與實踐【轉載】

 圖5 RocketMQ控制台

 3  LTS

對于任務排程這一塊,我們也必須要讓APP機器不再接受任何新任務,以免重新開機釋出時任務執行失敗。

我們的做法是在ZooKeeper裡對需要停止跑Job任務的APP機器,增加一個Znode,比如”機器ID=offline”,當JobTracker去排程TaskTracker執行任務時,一旦檢測到包含有此Tag的機器,就不會再給這些APP機器配置設定任務,以此達到任務解耦。

 4  檢查機制

為了平滑釋出的順利進行,檢查确認機制不可或缺,即確定Dubbo/Rocketmq/Lts中的下線都已生效,并且無流量發生,我們從以下兩個次元去檢查:

接口檢查,調用Dubbo、RocketMQ、LTS的API接口,檢查APP機器狀态,是否為已經下線。當然,在做了下線功能的同時,我們也有檢查功能和上線功能,可供調用。

監控檢查,調用CAT、ELK的API接口,檢查APP機器的請求通路數和日志流量是否都已經為0,已經處于下線狀态。

經過上述改造後,我們新的釋出流程如下,基本解決了平滑釋出問題,釋出時對業務的影響降到了最低;

互金平台灰階釋出的三段式探索與實踐【轉載】

圖6 釋出流程圖解

釋出實踐1.2—灰階釋出及驗證

這一章主要解決釋出驗證的問題,即如何驗證以確定線上釋出的準确性,有問題時確定影響面最小。

 1  停服後如何小範圍驗證

這裡先來個小插曲,不知道各位有沒有碰到過類似情況,大版本釋出時通常會挂停服公告,把請求切斷在Web層,然後運維小夥伴會進行APP釋出,此時通常會把所有APP都進行代碼部署,因為是大版本,十分兇殘。

互金平台灰階釋出的三段式探索與實踐【轉載】

圖7 停服頁面

下面問題來了,等釋出完成後,産品經理通常會說,能不能先不要開服,對外還是保持停服頁面,但讓我們幾個人能夠驗證下功能,以肯定确定以及确認這次釋出沒有遺漏或漏測的坑。

如果你是運維的小夥伴,會怎麼搞,大家可以腦洞下~~

先分享下我們的做法,我們會在辦公網絡單獨申請一個HDFB的wifi(灰階釋出),然後當你連上這個wifi出公網解析時,所有和我們業務相關的域名會解析到另一個入口,這個入口對應一個灰階釋出的WEB層,配置和線上一模一樣,限制隻能辦公網絡通路,所有人員在辦公室通過這個入口即可通路和驗證新版本,但公網使用者不可達。

互金平台灰階釋出的三段式探索與實踐【轉載】

圖8

 2  灰階釋出實踐

通過之前的平滑釋出和小範圍驗證的摸索,開始進行灰階釋出實踐之路。

灰階釋出,我相信大家對這個詞都有各自的了解和體會,它也有很多相似的概念或變體。比如分組釋出,藍綠釋出,金絲雀釋出,甚至于A/B測試。這裡不想糾結于某個具體的名詞或概念(需要煩請自行百度),還是緻力于解決實際中碰到的兩個問題:平滑釋出和釋出驗證。

平滑釋出問題前文中已有描述,至于釋出驗證問題,前文介紹了在停服情況下通過HDFB WEB層進行驗證,但有兩個問題:

一是隻适用于停服釋出,如果某次隻釋出幾個APP子產品,無法單獨驗證。

二是驗證時間有限(停服視窗一般不會太大),如果需要長時間驗證,無法滿足。

為了解決上面的問題,思考過程如下:

BFE,接入彙聚層,可以通過Nginx反向代理進行分組,即可區分流量,進行分組;

APP,由于會在多個公共元件中進行注冊,是以需要在公共元件中對接入的APP及其Service接口進行分組,具有互相隔離的能力,即可區分驗證;

針對公共元件的優化,又有以下兩種做法:

多搭建幾套公共環境,用于不同分組,但很快被否定,維護成本太大。

在一套公共環境中,支援多個分組,在APP中引入對應的framework jar包,支援灰階分組參數GROUP。

是以,按照這個思路,如果需要進行灰階釋出及長時間驗證時,會是下面的架構圖:

互金平台灰階釋出的三段式探索與實踐【轉載】

圖9

此處以GROUP=BLUE及GROUP=GREEN為例來進行說明(當然也可以分成更多的組),描述APP機器灰階釋出流程(BFE類似,隻是增加一步切換Nginx操作,不單獨描述)。

正常情況下,各APP機器啟動時,引入framework.jar包,并指定自己所屬GROUP,假設初始時為BLUE。

當需要釋出及進行驗證時,平滑下線所有APP的一部分機器,然後對需要部署代碼的APP進行釋出,啟動時修改所有下線APP機器的所屬GROUP=GREEN。

釋出完成後,可以通過單獨的HDFB WEB入口,進行驗證,此時線上仍可正常提供服務。

确認無誤後,重複上述步驟,增加GROUP=GREEN機器比例,當超過一半時,GROUP=GREEN直接提供線上服務,即把線上WEB層直接指向BFE(GROUP=GREEN)的分組。

随即把GROUP=BLUE機器再全部進行代碼釋出。

釋出完成後,線上APP統一運作在GROUP=GREEN的環境。

通過這種方式,我們即完成在不需要停服的情況下,對線上APP進行灰階釋出及驗證,對應的各基礎元件截圖如下:

配置中心Disconf:通過版本來對應GROUP的功能

互金平台灰階釋出的三段式探索與實踐【轉載】

 圖10 Disconf

注冊中心Dubbo:通過在Service的名稱前加上GROUP以分組

互金平台灰階釋出的三段式探索與實踐【轉載】

圖11 Dubbo

消息隊列RocketMQ:通過在Topic的後面加上GROUP以分組

互金平台灰階釋出的三段式探索與實踐【轉載】

圖12 RocketMQ

任務排程中心lTS:通過給每個task id加入灰階分組資訊,以區分不同的TaskTracker執行節點,新的task隻在新代碼的機器上運作。

互金平台灰階釋出的三段式探索與實踐【轉載】

圖13 lts

釋出實踐--後續探讨

下面,我們談一談灰階釋出的前提條件、應對思路以及後續的優化改善。細心的同學一定發現了,前面講的灰階釋出流程,應該是有一定先決條件的,展現在以下幾個方面:

資料層的變化導緻新老版本無法相容的,不能使用灰階釋出。

問題詳述:灰階釋出最終的資料落地還是一份,是以如果資料庫的表結構變更或者分布式緩存資料結構存在差異及不相容的情況,就不能使用灰階釋出。

應對思路:這個沒有特别好的辦法,隻能從研發層面去規範,比如APP通路資料時,盡量别出現select * from table的操作,而且架構設計時要及早考慮這點。

APP層中各APP的新老Service接口無法相容的,不能使用灰階釋出。

問題詳述:舉個例子,比如APP1和APP2,APP1和APP2各自内部的接口,要能新老版本相容.APP1和APP2之間互相調用的接口,也要能互相相容。

應對思路:這個原則上要求一般的程式都要滿足,比如至少要求跨一個版本的相容,多個版本間就不需要了。但實際操作時會略困難,牽涉到開發流程規範問題,需要開發測試同學一起配合,能做到單子產品級别的測試,且各子產品間要互相保持相容和一緻。

日常流量對灰階釋出的影響有多少。

問題詳述:灰階釋出過程中,需要逐漸切走部分線上機器,用于驗證;如果線上請求量較大,需要慎重,選擇在低峰段進行。

應對思路:這個目前的解決辦法是通過增加機器來解決,我們目前采取雙機房四區域,4倍的流量備援,每次按照25%的流量依次進行灰階釋出。

關于灰階釋出的後續優化及改善,目前有考慮到幾個方面,總結如下,後續會逐漸改進:

首先,當然是一個效率問題,目前雖然已經實作自動化,但釋出過程中還是需要一定的人為介入,而且驗證周期較長,後續要考慮如何更流暢的使用。

其次,是不是每個釋出都要走灰階進行,還是平滑釋出後就能直接對外提供服務,比如一個Hotfix的修改,要不要灰階?這個需要有一定的标準。

再次,如果需要長時間來驗證灰階環境,線上會同時存在兩個甚至以上的版本,不利于運維維護,且監控方面需要加強。

最後,能否利用灰階釋出的方式,線上上進行流量回放及全鍊路壓測,也是一個後續摸索的話題。

本文轉自 lirulei90 51CTO部落格,原文連結:http://blog.51cto.com/lee90/1957210,如需轉載請自行聯系原作者

繼續閱讀