1. 程式人生 > >遲到的故障公告:錯誤的快取資料引發新版部落格後臺釋出後的故障

遲到的故障公告:錯誤的快取資料引發新版部落格後臺釋出後的故障

10月18日晚上 22:00 ,我們對處於灰度釋出階段的新版部落格後臺(Angular 8.2.7 + .NET Core 3.0)進行了一次釋出操作,在釋出後由於清除快取 web api 的一個 bug 造成在釋出後通過新版部落格後臺修改的博文無法訪問(404錯誤);在發現問題後,我們回退至釋出之前的版本,但是由於 appsettings.Production.json 配置檔案的不一致造成回退後的版本出現 500 錯誤;在修復配置檔案問題後,在 docker swarm 叢集上部署時又遭遇奇怪的容器健康檢查失敗的問題,多次部署後才成功,直至 23:00 左右才恢復正常。

非常抱歉,這次故障給使用新版部落格後臺的園友帶來了很大的麻煩,請您諒解。

在這次釋出中包含一個比較大但卻沒有引起我們足夠重視的變更,原先在部落格後臺程式碼中進行的清除 memcached 快取(修改博文時清除對應的快取)的操作改為呼叫 web api ,在實現清除快取 web api 時由於沒有足夠重視在沒有寫整合測試覆蓋的情況下就釋出了,從而沒有及時發現其中埋藏的一個 bug ,這個 bug 是由下面的 C# 程式碼引起的:

await _cacheService.RemoveAsync(CacheKeyManager.GetBlogPost(blogId.Value, postId.Value));
var post = await blogPostService.GetCachedPostById(blogId.Value, postId.Value);            
//...
if (post.DisplayOnHomePage)
{
    await ClearHomePostsList(blogId.Value);
}
//..

上面的程式碼中在清除所修改博文的快取後,又獲取該博文進一步清除與該博文相關聯的快取,呼叫 GetCachedPostById 方法時又建立了快取,但由於實現時漏寫了 DTO 對映配置程式碼,造成快取的 BlogPostDto 欄位值不完整從而 PostId 的值為 0 。在我們的快取機制中,對於不存在的博文,會 new 一個空的 PostId 為 0 的 BlogPostDto 放入快取,所以 PostId 為 0 的快取資料都當作不存在的博文直接響應 404 ,故障因此而引發。

針對這次故障,在修掉 bug 程式碼的同時我們將採取以下改進措施:

1)對從快取中獲取的資料進行校驗並自動修復,這樣即使出現錯誤的快取資料,也可以減少對業務的影響。

else if (blogPost.PostId != postId)
{
    blogPost = await GetBlogPostById(blogId, postId);
    await _cacheService.UpdateAsync(cacheKey, 3600, blogPost);
}

2)加強 Code Review

3)提高整合測試的覆蓋率

4)解決生產環境配置管理的問題

5)改用 k8s 部署生產環境

最近的新版部落格後臺釋出故障暴露了我們在團隊開發能力上的落後,我們正在努力改進與提升,希望大家能夠諒解我們暫時的 low 。