【故障公告】发布 .NET Core 版博客站点引发大量 500 错误

很是抱歉,今天上午的博客站点故障给你们带来了很大的麻烦,请你们谅解。此次故障是咱们发布 .NET Core 版博客站点引发的,虽然咱们进行了充分的准备,但仍是低估了高并发下的复杂问题。nginx

如下是故障背景与大体通过:web

在这个炎炎夏日,咱们正热火朝天地忙着整个 .NET Core 迁移工程的收官 —— 发布 .NET Core 版博客站点与博客后台。咱们的其余系统都早已迁移至 .NET Core 并已在线上工做一番时日,只剩下最难啃的硬骨头 —— 博客系统,到这个月这根钢铁般坚硬的硬骨头也被啃得差很少了,它的发布上线将为咱们整个 .NET Core 迁移工程画上完美的句号,并顺带以此里程碑迎接 .NET Core 3.0 正式版的发布。docker

因此,发布 .NET Core 版博客站点与博客后台成为咱们8月份最重要的工做。.NET Core 版博客站点7月份就已经完成开发,这段时间一边进行更进一步的内测,一边进行灰度发布,接入一些生产流量以发现咱们测试中未能发现的问题并进行修复,在上个周末接入更多生产流量进行测试与修复后,咱们已经颇有信心,评估后认为已具有正式发布条件,除了咱们没法在测试环境中模拟的博客系统所处的复杂高并发场景。centos

因而一边带着信心,一边带着对高并发问题的担忧,咱们决定在今天一大早进行发布。服务器

发布时的部署场景是这样的,博客系统基于 .NET Core 3.0 Preview 7 (EF Core 用的仍是 3.0 Preview 5),7台阿里云 centos 服务器组建了 docker swarm 集群,6台4核8G服务器做为 worker 节点跑博客站点的应用容器,1台2核4G的服务器做为 manager 节点(不部署任何容器),每一个 worker 节点都部署 1 个 nginx 与 .net core 博客应用容器,全部请求都由阿里云均衡转发到 nginx 容器,再由 nginx 容器转发给 .net core 应用容器,nginx 经过端口映射的方式监听 worker 节点服务器的 80 端口。网络

这样的部署环境也是咱们通过长期验证的,惟一没有通过验证的就是博客系统这么高的并发。并发

顶着2个高并发问题的风险(docker swarm 与 .net core ),咱们在今天早上 5:30 左右进行了发布。curl

开始访问量小,并发低,没出现问题,但到 8:30 左右出现问题了,打开不少博客页面要1秒多(正常状况是几十毫秒),而在容器内用 curl 命令请求都不到10毫秒。高并发

$ docker exec -t $(docker ps -f name=blog_web -q) curl -H 'X-Forwarded-Proto:https' -w %{time_total} -o /dev/null -s localhost 
0.002876

怀疑是 nginx 的问题,准备从新建立一个 docker 集群,不用  nginx 直接用 kestrel 监听 80 端口。性能

后来同事指出,不是 nginx 的问题,是 docker swarm 端口映射在高并发下的性能问题,只有将端口映射改成 host 网络模式才能解决这个问题。

9:30 左右,随着并发愈来愈高,nginx 容器开始报 500 错误,开始觉得是集群中的服务器负载太高,因而向 docker swarm 集群中添加服务器,但于事无补,500 错误愈来愈多。

出现 500 错误时,有时刷新一次就会好,有时要刷新好几回,怀疑是集群中某些服务器不稳定,因而一台一台登陆集群中的服务器进入容器用 curl 命令进行测试,除了1台服务器不稳定,其余服务器 curl 命令测试时响应速度都正常,将那台不太稳定的服务器下线,问题依旧,随着并发量继续增大,500 错误也继续增多。

进一步分析后,怀疑 500 错误是由于高并发下 nginx 容器与 .net core 应用容器之间的网络通讯出现问题,因而 10:30 左右决定放弃此次发布,回退至跑在 Windows 上的 .net framework 版本博客站点,恢复了正常。

相关文章
相关标签/搜索