8 月 7 日上午 8 点 30 分左右,聊天服务出现不稳定状态,8 点 59 分我们内部监控系统显示服务不可用并报警,工程师随之上线处理。之后陆续收到用户反馈,说终端用户无法连接上 LeanCloud 聊天服务器。经我们检查确认是由于某台服务器出现了网络故障而导致连锁反应,我们工程师在定位故障后即刻进行了服务重启和扩容,最终在 11 点 50 分让服务彻底恢复正常。
这是一次非常重大的事故。为了将问题说清楚,我们先来介绍一下 LeanCloud 聊天服务的架构。
这里主要包括如下几部分:
接下来给大家还原一下事故的过程和我们的处理措施:
时间
过程描述
07:57
有一台服务器出现网络问题,所有进出的 RPC 请求都无法完成,与 Zookeeper 连接也多次失败。
08:25
由于其他机器发送到故障机的请求堆积,整个集群内存紧张,服务开始出现不稳定。
08:59
系统监控开始报警,服务大范围不可用。这时候我们工程师紧急上线开始处理。
09:10
剔除故障机,第一次尝试重启集群。但由于客户端重连机制的存在,重连压力太大造成服务启动失败。
09:50
用 iptables 来挡住部分连接请求,第二次尝试逐步开放服务,再次失败。
10:15
扩容集群,再次逐步开放服务。虽然重连压力依然非常大,但服务器运行正常。
10:50
限制对旧节点和端口的访问,开放 15% 的访问流量,这时候应用内有少量用户已经恢复使用。
11:20
所有旧节点使用新端口重新上线,并逐步开放 30%、50%、70% 的访问流量。
11:50
全流量开放,实时通信和推送服务完全恢复正常。
下面这张图表是我们在故障期间所监控到的连接数变化情况:
虽然我们较早就收到了系统报警,但在事故处置阶段,因为没有很好地应对大量客户端重连的情况,所以导致几次重新开放服务都宣告失败,影响了服务恢复的速度,这值得我们反思:当开放服务时,我们首先尝试了同时开放全部服务器,但因请求量过大,应用层无法处理而失败。然后我们将 router 规则调整为随机分配,小范围地开放了两台服务器,但又发现进程最大可用文件句柄数很快被占满,单台机器上瞬时涌入了数倍于正常状态的连接。经过分析,确认是客户端重连、发来的 SSL 握手请求无法被应用层处理,所以最后我们通过同时更改 iptables 和 router 规则,逐步放行访问流量,才让集群最终恢复过来。
本次故障持续时间超过 3 个半小时,对用户业务产生了重大影响,我们对此深感愧疚!
我们一直致力于打造最稳定的云服务,接下来整个团队会以最高优先级来解决平台稳定性问题,信誓旦旦的保证是没有实际意义的,所以后续改进措施里也加入了截止时间,希望大家一起来监督: