翻車了,記一次 Go 線上事故
關(guān)鍵詞:golang、go、gorm、零值、有擔(dān)當(dāng)?shù)母蝗?/p>
翻車日期:2021.03.04
翻車現(xiàn)場
今天下午3:30有同事反饋,app冷啟動(dòng)出現(xiàn)了測試公告彈窗。

畫外音:半小時(shí)前剛更新一個(gè)服務(wù),趕緊檢查下配置吧。
事件回述
10:27:代碼發(fā)布sandbox環(huán)境 10:27~11:30:測試配置導(dǎo)入(因?yàn)榕渲帽容^多)生產(chǎn)環(huán)境,并手動(dòng)修改少量差異配置 11:30~11:50:sandbox環(huán)境驗(yàn)收完成 11:51: api開始灰度 12:46: 灰度結(jié)束,api全量發(fā)布 15:00: 優(yōu)化配置解析,重新發(fā)布了config服務(wù) 15:30: 同事反饋app冷啟動(dòng)有測試彈窗,立即檢查并修正公告配置
蛛絲馬跡
上午上線了一個(gè)需求,遷移了48條配置到業(yè)務(wù)配置中心(原來的配置是硬編碼在項(xiàng)目里面的,每次改都要修改代碼重新發(fā)布)。
上午上線之前明明驗(yàn)收過,沒有問題才發(fā)生產(chǎn)的呀!
為了驗(yàn)證遷移之后接口一致性,我還特地安裝了一個(gè)json-diff工具(官網(wǎng)),還特地從4.x、5.x、6.x驗(yàn)證了多個(gè)版本的配置,都沒有問題。

為啥現(xiàn)在有幾條配置跟我驗(yàn)證時(shí)候的不一樣了呢?

等等,這些文案不是測試環(huán)境的文案么?
畫外音:這個(gè)很可疑哦!
來龍去脈
因?yàn)榕渲梦募容^多,一個(gè)個(gè)在生產(chǎn)環(huán)境加太麻煩了,我就直接把測試配置導(dǎo)入到生產(chǎn)環(huán)境中。然后手動(dòng)修改下生產(chǎn)和測試不一致的幾條配置,其中就包含了測試公告的幾條配置。
畫外音:但是為什么驗(yàn)收的時(shí)候是好的,然后下午重新發(fā)布了下服務(wù)就出問題了呢?
我打開數(shù)據(jù)庫,看到數(shù)據(jù)庫里面這幾條配置記錄還是測試的配置,并沒有修改過來。。。我打開我的goland,翻看了下編輯接口代碼,一下就發(fā)現(xiàn)了可疑之處:
err := tx.Table(p.tableName).Where("id=?", configID).Updates(t).Error
gorm的Updates有個(gè)坑啊——如果你傳的是一個(gè)struct,gorm默認(rèn)是不更新“零值”字段的。這個(gè)坑我早就知道,無奈再一次重重的的踩進(jìn)去了。git blame看了下作者——原來就是我自己,去年12月份寫下的??(自己的坑自己填,好在沒有禍害到別人)。
豁然明朗
我畫了一個(gè)簡圖,方便大家明白:

配置服務(wù)是無狀態(tài)服務(wù),所有配置都保存在內(nèi)存中(業(yè)務(wù)配置不多,不會(huì)爆內(nèi)存) 服務(wù)啟動(dòng)的時(shí)候從mysql(持久化存儲(chǔ))加載所有配置,并與etcd保持一致性 增量配置會(huì)保存到mysql中,并通過etcd保持所有節(jié)點(diǎn)同步
畫外音:終于知道了為什么上午驗(yàn)收是好的,下午重啟就出問題了!?。?/p>
上午導(dǎo)入的測試配置,生產(chǎn)環(huán)境正好要把他們其中幾條改成空值。增量數(shù)據(jù)通過etcd同步到內(nèi)存是正確的,但是持久化到mysql的時(shí)候gorm把應(yīng)該置空的字段忽略了,導(dǎo)致數(shù)據(jù)庫里面沒有修改正確。下午一重啟,GG。。。
總結(jié)
領(lǐng)導(dǎo)好像沒有說什么,因?yàn)闆]有客訴,事情并不是很大。
畫外音:既然領(lǐng)導(dǎo)沒有說故障定責(zé),要不就這樣算了?
猶豫了半分鐘——還是主動(dòng)寫個(gè)故障報(bào)告吧。
我猶豫的是,沒有產(chǎn)生客訴,問題時(shí)間不長,而且犯得是這么低級的錯(cuò)誤,是不是睜一只眼閉一只眼就過去了。。。
還是寫了報(bào)告是因?yàn)閮?nèi)心告訴我,小事都不能承擔(dān)責(zé)任,大事(優(yōu)質(zhì)項(xiàng)目)還輪得到我么?
最近看了《窮爸爸 富爸爸》這本書,書中說到“窮人的恐懼包括:害怕付不起賬單、害怕被解雇、害怕沒有足夠的錢、害怕重新開始等等”。簡單說就是,窮人總數(shù)怕這怕那。而這一次,我選擇了做個(gè)有擔(dān)當(dāng)?shù)母蝗??。。。
教訓(xùn)與改進(jìn)
使用 json-diff工具,自認(rèn)為可以100%驗(yàn)證,就自測上線數(shù)據(jù)同步場景不僅僅要觀察表象,也要關(guān)注持久化數(shù)據(jù)是否與表象一致 加強(qiáng)開發(fā)規(guī)范,需求不分大小,都需要請測試把關(guān) 不能盲目自信,保持一顆敬畏的心
推薦閱讀
