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 .
来源: https://www.cnblogs.com/cmt/p/11892914.html