構(gòu)建可回滾的應(yīng)用及上線checklist實(shí)踐

一泡垃、背景

在互聯(lián)網(wǎng)分布式應(yīng)用中析珊,如果上線的新版本有bug又不能回滾止損,帶來(lái)的后果將是災(zāi)難性的蔑穴。因此做到上線可回滾以及上線前的checklist是保證服務(wù)穩(wěn)定性的基本要求忠寻。

在簡(jiǎn)單的場(chǎng)景里直接回滾到上一版?zhèn)€版本即可,但是如果涉及多個(gè)上下游和組件存和、考慮多版本兼容奕剃,就需要有好好設(shè)計(jì)下如何構(gòu)建可回滾的代碼,充分驗(yàn)證后還需要仔細(xì)檢查上線checklist捐腿,最大程度保證線上服務(wù)的穩(wěn)定性纵朋。

二、構(gòu)建向前兼容的代碼

回滾指的是程序或數(shù)據(jù)處理錯(cuò)誤叙量,將程序或數(shù)據(jù)恢復(fù)到上一次正確狀態(tài)的行為倡蝙。在回滾之后,程序依然能夠正常處理绞佩,稱為可回滾寺鸥。

不可回滾原因大多是舊程序不能處理新數(shù)據(jù)猪钮,同時(shí)新數(shù)據(jù)又不能丟棄,代碼回滾導(dǎo)致舊業(yè)務(wù)邏輯出錯(cuò)胆建。

保證向前兼容的手段:

1烤低、數(shù)據(jù)庫(kù)變更

新加字段:設(shè)置默認(rèn)值,默認(rèn)值要保證新舊代碼邏輯的語(yǔ)義一致性笆载。比如用戶表添加了用戶狀態(tài)扑馁,默認(rèn)值要設(shè)置為默認(rèn)有效。

刪除字段:新版本全量發(fā)布后凉驻,最后迭代2-3個(gè)版本后腻要,再刪除無(wú)用字段,同時(shí)要做好數(shù)據(jù)庫(kù)備份涝登。

新加唯一約束:首先要確保原有的數(shù)據(jù)值沒(méi)有重復(fù)的雄家,再添加唯一索引,可使用以下SQL驗(yàn)證:

select field,count(1) from table group by field having count(1) > 1

復(fù)雜數(shù)據(jù)庫(kù)字段變更:
復(fù)雜數(shù)據(jù)庫(kù)字段變更:

  • 通常做法是:雙寫讀舊 -> 新字段離線驗(yàn)證 -> 舊字段全量拷貝至新字段 -> 雙讀舊為主diff -> 雙讀新為主diff -> 寫新讀新 -> 移除舊字段和邏輯胀滚;

  • 出問(wèn)題之后趟济,只回滾程序,不回滾數(shù)據(jù)咽笼。

2顷编、對(duì)外提供服務(wù)API變動(dòng)設(shè)計(jì)

(1)對(duì)外提供RPC服務(wù)

入?yún)⑿录幼侄危涸O(shè)置為可選的,如果沒(méi)設(shè)置值剑刑,要有老業(yè)務(wù)邏輯兼容代碼

返回值字段:設(shè)置為可選的媳纬,如果是新版本肯定有值字段,需要在字段描述文檔里做好備注

如果入?yún)⒑头祷刂到Y(jié)果差異較大叛甫,建議新建一個(gè)RPC方法层宫,逐漸把業(yè)務(wù)方調(diào)用遷移到新方法

(2)對(duì)外提供HTTP服務(wù)

HTTP接口和RPC接口的不同是沒(méi)有強(qiáng)制的約束,數(shù)據(jù)交換大多采用Json形式其监,雖然靈活性強(qiáng)萌腿,但是約束力低給管理帶來(lái)很大的成本。因此HTTP接口文檔必須給出類似RPC一樣的規(guī)范抖苦,比如Swagger等工具毁菱,比如給指定字段名、類型锌历、是否必填贮庞、不填寫的默認(rèn)值等。

3究西、多版本發(fā)布

對(duì)于客戶端API服務(wù)或者基礎(chǔ)服務(wù)來(lái)說(shuō)窗慎,用戶升級(jí)會(huì)有很大的延遲,對(duì)于服務(wù)提供方來(lái)說(shuō)則需要盡量保證多版本同時(shí)可用。最好在最開(kāi)始設(shè)計(jì)接口的時(shí)候就添加version字段遮斥,保證以后的擴(kuò)展峦失。

4、靜態(tài)資源發(fā)布

因?yàn)殪o態(tài)資源一般放在CDN上緩存時(shí)間設(shè)置的比較長(zhǎng)术吗,比如1個(gè)月尉辑。這樣假設(shè)發(fā)布的版本有問(wèn)題,需要清理CDN緩存较屿,并且也需要清理瀏覽器緩存隧魄,而且因?yàn)榇嬖诎姹靖采w的問(wèn)題,即使覆蓋了也不一定保證是操作正確了隘蝎。

現(xiàn)在的工具默認(rèn)都會(huì)把md5設(shè)置到j(luò)s购啄、css文件名中,可有效的避免以上問(wèn)題嘱么。

image-20211120215947571

三闸溃、上線checklist

盡管準(zhǔn)備工作做的再好,難免也會(huì)出現(xiàn)疏漏拱撵,因此指定上線前checklist,組內(nèi)同學(xué)交叉評(píng)審表蝙,保證上線前的最后一步拴测,是很有必要的。

發(fā)布策略一般是從下游逐步向上部署府蛇。而回滾方案相反集索,一般是從上游往下回滾。

通用的checklist需要考慮以下幾方面:

1汇跨、依賴

(1)存儲(chǔ)(數(shù)據(jù)庫(kù)务荆、分布式緩存)

是否有數(shù)據(jù)庫(kù)變更需要代碼上線前先提交,并且驗(yàn)證執(zhí)行成功穷遂。

(2)動(dòng)態(tài)配置

首先需要確認(rèn)代碼中的動(dòng)態(tài)配置有無(wú)默認(rèn)值函匕,沒(méi)有默認(rèn)值需要先在動(dòng)態(tài)配置系統(tǒng)上添加相關(guān)的配置。

(3)下游

確認(rèn)下游jar包版本是否正確蚪黑,線上最好使用release包盅惜。

確認(rèn)下游的業(yè)務(wù)方是否已經(jīng)上線。

(4)鑒權(quán)

美團(tuán)內(nèi)部的服務(wù)調(diào)用都有鑒權(quán)忌穿,檢查鑒權(quán)是否已經(jīng)添加并且已生效

2抒寂、上游

(1)Nginx層

確認(rèn)路由策略,在發(fā)布過(guò)程中會(huì)不會(huì)造成用戶不斷刷新頁(yè)面命中不同代碼邏輯掠剑,給用戶帶來(lái)用戶體驗(yàn)上的問(wèn)題和困擾屈芜。

(2)上游業(yè)務(wù)方

確保和上游業(yè)務(wù)方溝通好,等當(dāng)前服務(wù)全量發(fā)布后且觀察、驗(yàn)證沒(méi)問(wèn)題再通知上游發(fā)布井佑。

3属铁、業(yè)務(wù)內(nèi)部

通過(guò)代碼review,QA測(cè)試等方式保證上線對(duì)現(xiàn)有業(yè)務(wù)邏輯沒(méi)有影響毅糟。

如有必要可建設(shè)業(yè)務(wù)的checklist規(guī)范

  • 代碼review:重點(diǎn)查看代碼規(guī)范红选、業(yè)務(wù)邏輯的正確性、對(duì)相關(guān)功能的影響

  • 測(cè)試用例:測(cè)試相關(guān)代碼的正常邏輯姆另、邊界條件喇肋、其他功能不受影響,如果寫好測(cè)試用例請(qǐng)參考其他專業(yè)的文檔

  • 自動(dòng)化測(cè)試:有條件的團(tuán)隊(duì)建議添加自動(dòng)化測(cè)試迹辐,來(lái)保證核心業(yè)務(wù)流程的正確性

四蝶防、可回滾發(fā)布

1、回滾方案

需考慮以下幾方面:

  • 是否有動(dòng)態(tài)開(kāi)關(guān)明吩、流量控制可以一鍵恢復(fù)到舊版本邏輯

  • 回滾代碼會(huì)不會(huì)導(dǎo)致上游調(diào)用失敗

  • 回滾代碼:根據(jù)docker鏡像间学、Git commitId、Git tag回滾

2印荔、可回滾驗(yàn)證

方案設(shè)計(jì)要考慮可回滾性低葫;通常要在test或預(yù)上線環(huán)境驗(yàn)證(演練)可回滾性。同時(shí)QA同學(xué)要把可回滾作為質(zhì)量驗(yàn)收的一部分仍律。

3嘿悬、平滑升級(jí)

(1)線上驗(yàn)收

通過(guò)staging環(huán)境或線上灰度鏈路, 進(jìn)行線上驗(yàn)收水泉。

(2)藍(lán)綠發(fā)布

線上部署兩個(gè)集群善涨,每個(gè)集群都能抗住所有的流量,發(fā)布的時(shí)候一個(gè)集群接受用戶請(qǐng)求草则,等當(dāng)前集群全部發(fā)布成功后钢拧,再把流量全部遷移到新版本集群。

優(yōu)點(diǎn):可保證新版本特性同一時(shí)間對(duì)所有用戶生效炕横;保證系統(tǒng)高可用源内,一個(gè)集群出問(wèn)題,可快速切換到備用集群看锉;

缺點(diǎn):日常使用的機(jī)器只有一半姿锭,造成浪費(fèi);

藍(lán)綠發(fā)布的高配方案:部署兩套集群伯铣,通過(guò)Nginx層動(dòng)態(tài)切換集群呻此。

藍(lán)綠發(fā)布的低配方案:用動(dòng)態(tài)開(kāi)關(guān)控制新舊邏輯,等新版本全量上線后腔寡,再切換到新代碼邏輯焚鲜。

(3)灰度發(fā)布(金絲雀發(fā)布)

采用金絲雀部署,可以在生產(chǎn)環(huán)境的基礎(chǔ)設(shè)施中小范圍的部署新的應(yīng)用代碼。一旦應(yīng)用新發(fā)布忿磅,只有少數(shù)用戶被路由到它糯彬。最大限度的降低影響。檢測(cè)新版本沒(méi)問(wèn)題葱她,再逐步擴(kuò)大發(fā)布范圍直至全量撩扒。

實(shí)現(xiàn)灰度發(fā)布,需要部署系統(tǒng)設(shè)置分批發(fā)布吨些,同時(shí)必須有監(jiān)控搓谆、報(bào)警等相關(guān)的系統(tǒng)的配合。確定沒(méi)問(wèn)題后再擴(kuò)量豪墅。

還有一點(diǎn)需要注意的就是灰度路由策略泉手,一般服務(wù)中用的多是的隨機(jī)策略,這樣可能導(dǎo)致用戶在發(fā)布過(guò)程中不斷刷新頁(yè)面偶器,可能會(huì)來(lái)回命中新老版本邏輯斩萌,影響用戶體驗(yàn)。避免方式有以下幾種:

  • 采用用戶ID做路由因子屏轰,問(wèn)題是新增颊郎、刪除機(jī)器時(shí),算法匹配的機(jī)器會(huì)變霎苗,就需要引入一致性Hash算法袭艺,復(fù)雜性較高

  • RPC路由策略一般不能執(zhí)行路由規(guī)則,就需要程序自己判斷叨粘。常用做法是采用動(dòng)態(tài)配置設(shè)置百分比值,算法如下:

userId % 100 < $dynamicTrafficPercent ? oldVersion : newVersion
(4)AB測(cè)試

AB測(cè)試雖然也有流量控制的功能瘤睹,但一般是用于驗(yàn)證不同版本之間的性能升敲、用戶體驗(yàn)、效果數(shù)據(jù)等的手段轰传。是上線后由運(yùn)營(yíng)控制的驴党。

AB測(cè)試和灰度發(fā)布最大的不同是AB測(cè)試是通過(guò)桶的方式分配流量。

4获茬、監(jiān)控報(bào)警

常用的發(fā)布相關(guān)的監(jiān)控報(bào)警包括:

  • 新港庄、舊版本的流量及百分比

  • 對(duì)外提供的接口的性能指標(biāo)、下游的性能指標(biāo)(TP50恕曲、TP90鹏氧、TP99、TP999)

  • 異常指標(biāo)及報(bào)警

  • 業(yè)務(wù)指標(biāo)

5佩谣、發(fā)布完成周知

  • PM: 周知PM關(guān)注業(yè)務(wù)指標(biāo)把还、客訴等

  • 上游:如果上游依賴此發(fā)布,周知上游開(kāi)始發(fā)布

  • 下游:周知下周注意流量增量及耗時(shí)等情況

五、上線步驟及規(guī)范

1吊履、不在高峰期上線,如必須上線,要發(fā)郵件申請(qǐng)卦尊,同時(shí)降低并發(fā)度

2漫萄、上線前周知

3、保證能回滾

4缀踪、發(fā)布過(guò)程采用分組發(fā)布(強(qiáng)制)

5居砖、上線過(guò)程中觀察系統(tǒng)指標(biāo)、業(yè)務(wù)指標(biāo)辜贵、異常指標(biāo)等悯蝉;如有異常立即禁用已發(fā)布機(jī)器

6、上線后周知PM托慨、上下游等

7鼻由、有異常第一時(shí)間回滾

六、總結(jié)

從本文可以看出厚棵,保證線上穩(wěn)定性是一個(gè)復(fù)雜且系統(tǒng)的工程蕉世,需要從技術(shù)規(guī)范、流程規(guī)范婆硬、周知狠轻、檢查、工具支持等各個(gè)方面來(lái)保證彬犯。

作者簡(jiǎn)介:木小豐向楼,美團(tuán)Java高級(jí)工程師,專注分享軟件研發(fā)過(guò)程中的實(shí)踐谐区、思考湖蜕。歡迎關(guān)注公共號(hào):Java研發(fā)

原文鏈接:構(gòu)建可回滾的應(yīng)用及上線checklist實(shí)踐

更多精彩文章:

Maven依賴沖突問(wèn)題排查經(jīng)驗(yàn)

升級(jí)Java17問(wèn)題記錄

使用Groovy構(gòu)建DSL

Gradle最佳實(shí)踐

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市宋列,隨后出現(xiàn)的幾起案子昭抒,更是在濱河造成了極大的恐慌,老刑警劉巖炼杖,帶你破解...
    沈念sama閱讀 211,123評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件灭返,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡坤邪,警方通過(guò)查閱死者的電腦和手機(jī)熙含,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)艇纺,“玉大人婆芦,你說(shuō)我怎么就攤上這事怕磨。” “怎么了消约?”我有些...
    開(kāi)封第一講書人閱讀 156,723評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵肠鲫,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我或粮,道長(zhǎng)导饲,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 56,357評(píng)論 1 283
  • 正文 為了忘掉前任氯材,我火速辦了婚禮渣锦,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘氢哮。我一直安慰自己袋毙,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,412評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布冗尤。 她就那樣靜靜地躺著听盖,像睡著了一般。 火紅的嫁衣襯著肌膚如雪裂七。 梳的紋絲不亂的頭發(fā)上皆看,一...
    開(kāi)封第一講書人閱讀 49,760評(píng)論 1 289
  • 那天,我揣著相機(jī)與錄音背零,去河邊找鬼腰吟。 笑死,一個(gè)胖子當(dāng)著我的面吹牛徙瓶,可吹牛的內(nèi)容都是我干的毛雇。 我是一名探鬼主播,決...
    沈念sama閱讀 38,904評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼侦镇,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼禾乘!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起虽缕,我...
    開(kāi)封第一講書人閱讀 37,672評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎蒲稳,沒(méi)想到半個(gè)月后氮趋,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,118評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡江耀,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,456評(píng)論 2 325
  • 正文 我和宋清朗相戀三年剩胁,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片祥国。...
    茶點(diǎn)故事閱讀 38,599評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡昵观,死狀恐怖晾腔,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情啊犬,我是刑警寧澤灼擂,帶...
    沈念sama閱讀 34,264評(píng)論 4 328
  • 正文 年R本政府宣布,位于F島的核電站觉至,受9級(jí)特大地震影響剔应,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜语御,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,857評(píng)論 3 312
  • 文/蒙蒙 一峻贮、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧应闯,春花似錦纤控、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,731評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至惜辑,卻和暖如春唬涧,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背盛撑。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,956評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工碎节, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人抵卫。 一個(gè)月前我還...
    沈念sama閱讀 46,286評(píng)論 2 360
  • 正文 我出身青樓狮荔,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親介粘。 傳聞我的和親對(duì)象是個(gè)殘疾皇子殖氏,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,465評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容