10月18日晚上 22:00 ,我們對(duì)處于灰度發(fā)布階段的新版博客后臺(tái)(Angular 8.2.7 + .NET Core 3.0
)進(jìn)行了一次發(fā)布操作,在發(fā)布后由于清除緩存 web api 的一個(gè) bug
造成在發(fā)布后通過新版博客后臺(tái)修改的博文無法訪問(404錯(cuò)誤);在發(fā)現(xiàn)問題后,我們回退至發(fā)布之前的版本,但是由于
appsettings.Production.json 配置文件的不一致造成回退后的版本出現(xiàn) 500 錯(cuò)誤;在修復(fù)配置文件問題后,在 docker swarm
集群上部署時(shí)又遭遇奇怪的容器健康檢查失敗的問題,多次部署后才成功,直至 23:00 左右才恢復(fù)正常。
非常抱歉,這次故障給使用新版博客后臺(tái)的園友帶來了很大的麻煩,請(qǐng)您諒解。
在這次發(fā)布中包含一個(gè)比較大但卻沒有引起我們足夠重視的變更,原先在博客后臺(tái)代碼中進(jìn)行的清除 memcached 緩存(修改博文時(shí)清除對(duì)應(yīng)的緩存)的操作改為調(diào)用
web api ,在實(shí)現(xiàn)清除緩存 web api 時(shí)由于沒有足夠重視在沒有寫集成測(cè)試覆蓋的情況下就發(fā)布了,從而沒有及時(shí)發(fā)現(xiàn)其中埋藏的一個(gè) bug ,這個(gè)
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); }//..
上面的代碼中在清除所修改博文的緩存后,又獲取該博文進(jìn)一步清除與該博文相關(guān)聯(lián)的緩存,調(diào)用 GetCachedPostById
方法時(shí)又創(chuàng)建了緩存,但由于實(shí)現(xiàn)時(shí)漏寫了 DTO 映射配置代碼,造成緩存的 BlogPostDto 字段值不完整從而 PostId 的值為 0
。在我們的緩存機(jī)制中,對(duì)于不存在的博文,會(huì) new 一個(gè)空的 PostId 為 0 的 BlogPostDto 放入緩存,所以 PostId 為 0
的緩存數(shù)據(jù)都當(dāng)作不存在的博文直接響應(yīng) 404 ,故障因此而引發(fā)。
針對(duì)這次故障,在修掉 bug 代碼的同時(shí)我們將采取以下改進(jìn)措施:
1)對(duì)從緩存中獲取的數(shù)據(jù)進(jìn)行校驗(yàn)并自動(dòng)修復(fù),這樣即使出現(xiàn)錯(cuò)誤的緩存數(shù)據(jù),也可以減少對(duì)業(yè)務(wù)的影響。
else if (blogPost.PostId != postId) { blogPost = await GetBlogPostById(blogId,
postId);await _cacheService.UpdateAsync(cacheKey, 3600, blogPost); }
2)加強(qiáng) Code Review
3)提高集成測(cè)試的覆蓋率
4)解決生產(chǎn)環(huán)境配置管理的問題
5)改用 k8s 部署生產(chǎn)環(huán)境
最近的新版博客后臺(tái)發(fā)布故障暴露了我們?cè)趫F(tuán)隊(duì)開發(fā)能力上的落后,我們正在努力改進(jìn)與提升,希望大家能夠諒解我們暫時(shí)的 low 。
熱門工具 換一換