重大翻車現場,記一次線上事故

nanjingfm發表於2021-03-05

關鍵詞:golang、go、gorm、零值、有擔當的富人

翻車日期:2021.03.04

今天下午3:30有同事反饋,app冷啟動出現了測試公告彈窗。

image-20210304201616977

畫外音:半小時前剛更新一個服務,趕緊檢查下配置吧。

  • 10:27:程式碼釋出sandbox環境
  • 10:27~11:30:測試配置匯入(因為配置比較多)生產環境,並手動修改少量差異配置
  • 11:30~11:50:sandbox環境驗收完成
  • 11:51:api開始灰度
  • 12:46:灰度結束,api全量釋出
  • 15:00:最佳化配置解析,重新發布了config服務
  • 15:30:同事反饋app冷啟動有測試彈窗,立即檢查並修正公告配置

上午上線了一個需求,遷移了48條配置到業務配置中心(原來的配置是硬編碼在專案裡面的,每次改都要修改程式碼重新發布)。

上午上線之前明明驗收過,沒有問題才發生產的呀!

為了驗證遷移之後介面一致性,我還特地安裝了一個json-diff工具(官網),還特地從4.x5.x6.x驗證了多個版本的配置,都沒有問題。

image-20210304201103809

為啥現在有幾條配置跟我驗證時候的不一樣了呢?

image-20210304201442816

等等,這些文案不是測試環境的文案麼?

畫外音:這個很可疑哦!

因為配置檔案比較多,一個個在生產環境加太麻煩了,我就直接把測試配置匯入到生產環境中。然後手動修改下生產和測試不一致的幾條配置,其中就包含了測試公告的幾條配置。

畫外音:但是為什麼驗收的時候是好的,然後下午重新發布了下服務就出問題了呢?

我開啟資料庫,看到資料庫裡面這幾條配置記錄還是測試的配置,並沒有修改過來。。。我開啟我的goland,翻看了下編輯介面程式碼,一下就發現了可疑之處:

err := tx.Table(p.tableName).Where("id=?", configID).Updates(t).Error

gormUpdates有個坑啊——如果你傳的是一個structgorm預設是不更新“零值”欄位的。這個坑我早就知道,無奈再一次重重的的踩進去了。git blame看了下作者——原來就是我自己,去年12月份寫下的?(自己的坑自己填,好在沒有禍害到別人)。

我畫了一個簡圖,方便大家明白:

image-20210304203053829

  • 配置服務是無狀態服務,所有配置都儲存在記憶體中(業務配置不多,不會爆記憶體)
  • 服務啟動的時候從mysql(持久化儲存)載入所有配置,並與etcd保持一致性
  • 增量配置會儲存到mysql中,並透過etcd保持所有節點同步

畫外音:終於知道了為什麼上午驗收是好的,下午重啟就出問題了!!!

上午匯入的測試配置,生產環境正好要把他們其中幾條改成空值。增量資料透過etcd同步到記憶體是正確的,但是持久化到mysql的時候gorm把應該置空的欄位忽略了,導致資料庫裡面沒有修改正確。下午一重啟,GG。。。

領導好像沒有說什麼,因為沒有客訴,事情並不是很大。

畫外音:既然領導沒有說故障定責,要不就這樣算了?

猶豫了半分鐘——還是主動寫個故障報告吧。

我猶豫的是,沒有產生客訴,問題時間不長,而且犯得是這麼低階的錯誤,是不是睜一隻眼閉一隻眼就過去了。。。

還是寫了報告是因為內心告訴我,小事都不能承擔責任,大事(優質專案)還輪得到我麼?

最近看了《窮爸爸 富爸爸》這本書,書中說到“窮人的恐懼包括:害怕付不起賬單、害怕被解僱、害怕沒有足夠的錢、害怕重新開始等等”。簡單說就是,窮人總數怕這怕那。而這一次,我選擇了做個有擔當的富人?。。。

  • 使用json-diff工具,自認為可以100%驗證,就自測上線
  • 資料同步場景不僅僅要觀察表象,也要關注持久化資料是否與表象一致
  • 加強開發規範,需求不分大小,都需要請測試把關
  • 不能盲目自信,保持一顆敬畏的心

關鍵詞:golang、go、gorm、零值、有擔當的富人

本作品採用《CC 協議》,轉載必須註明作者和本文連結
您的點贊、評論和關注,是我創作的不懈動力。 學無止境,讓我們一起加油,在技術的衚衕裡越走越深!

相關文章