凌晨两点十七分,手机连续震动,监控平台弹出红色告警:生产环境首页响应超时,错误率100%。人还半梦半醒,手已经条件反射地摸到笔记本电源键。等打开监控大盘,心凉了半截——全站所有接口都在转圈,流量跌到几乎为零。值班群开始刷屏,客户投诉截图一张接一张。来不及抱怨,先打开命令行,准备按最小代价原则排查。

接下来要做的不是马上重启服务,而是先确认影响范围。打开本地 hosts 文件路径 C:\Windows\System32\drivers\etc\hosts,确认没有被篡改,同时用 curl -I 直接访问源站,返回 502 Bad Gateway,说明域名解析和 CDN 层面基本正常,问题出在源站后端。再登录云服务器控制台,CPU 和内存没有打满,但连接数异常高,初步判断是应用层或数据库连接池被拖垮。
第一小时:先别急着重启,确认影响范围
遇到网站突然打不开,很多人的第一反应是重启服务器。但在这个案例里,重启非但解决不了问题,还可能把仅存的现场日志冲掉。正确的做法是先观察监控曲线,看流量是瞬间掉零,还是缓慢下降;是部分地区不可用,还是所有地域都报错。用第三方拨测工具检测,发现北京、上海、广州全部超时,说明是全局性故障,不是某个机房网络抖动。
紧接着查看 Nginx 访问日志和错误日志。用 tail -f /var/log/nginx/access.log 实时观察,发现大量请求返回 502,而后端服务日志里出现 Java 堆栈异常,提示数据库连接获取超时。此时基本可以锁定:不是网络问题,不是 DNS 问题,而是应用服务到数据库这一层出现瓶颈。先不要贸然回滚,把当前线程栈、连接数、慢查询快照保存下来,这些是后面定位根因的关键证据。
上午:定位到那次看似普通的发布
翻看发布记录,发现凌晨零点十分有一个自动部署单,改动内容只是调整了一个配置文件中的数据库连接池参数。表面上看是常规操作,但打开配置一看,最大连接数从 200 被误写成了 20,而线上并发高峰下需要至少 180 个连接。连接池很快被占满,后续请求排队等待,最终导致全站 502。这个错误在预发布环境没有被发现,因为那边流量太小,根本触发不了瓶颈。
定位到根因后,立即执行回滚。通过 git 找到上一个稳定版本号,用发布系统的回滚按钮把代码恢复到前一天的状态。回滚完成后,部分页面能打开了,但订单接口仍然卡顿。查看数据库连接数,已经从 2000 回落到 300 左右,但还存在大量积压的慢查询和未提交事务。此时不能干等,需要手动杀掉阻塞进程,释放锁资源。执行 SHOW PROCESSLIST 找到长时间 Sleep 和 Locked 的连接,逐个确认后 kill 掉。
这里有个细节值得注意:回滚之前一定要先备份当前配置和日志,哪怕是坏掉的版本。因为一旦回滚后问题依旧,你还需要回到故障现场继续分析。我们当时就犯了一个小错误,着急回滚,差点把故障版本的完整日志覆盖掉。好在监控系统保留了历史采集数据,才补上了时间线。
下午:数据修复与攻击疑云
服务恢复了大概七成,但用户投诉开始集中到订单重复提交和支付回调丢失。排查数据库后发现,在故障期间有大量用户反复点击提交按钮,加上前端限流失效,订单表出现重复记录。需要写一个临时脚本,按订单号和用户ID去重,保留最早一条,把重复的标记为无效。这个操作必须非常谨慎,先在测试库演练,再对生产库分批执行。每执行一批就统计影响行数,确保没有误删有效数据。
与此同时,安全同事在访问日志里发现异常:故障发生后的一小时内,来自某几个境外 IP 的扫描请求暴增,路径集中在后台登录接口和文件上传接口。虽然这次宕机不是直接由攻击引起,但这些扫描流量加重了服务器负担,也暴露出后台接口缺少频率限制。临时措施是在 WAF 上封禁这批 IP,并对后台接口增加验证码和登录失败锁定。封禁时要注意不能把正常企业出口 IP 一并封掉,可以先只封有明确恶意 payload 的攻击源。
更麻烦的是数据库增量数据。检查备份发现最近一次全量备份在故障前 23 小时,之后只有 binlog 增量。为了补齐这 23 小时内的数据,先恢复备份到临时实例,再用 binlog 按时间点回放到故障发生前。整个过程耗时四个小时,期间网站保持只读模式,避免产生新写入导致不一致。最终数据核对无误,订单金额和库存数量都对上了。
晚上:复盘与防线升级
到晚上十点,网站核心业务基本恢复稳定,错误率降到正常水位。团队没有马上解散,而是开了一个小时的复盘会。把时间线画在白板上:零点十分发布错误配置,零点四十五分监控告警,凌晨两点十七分收到人工反馈,两点三十分开始排查,上午九点回滚,下午两点数据恢复,晚上十点全部结束。整个过程中,从发布到告警有三十五分钟空窗,从告警到人工确认又有一个半小时延迟,这说明监控告警策略虽然存在,但阈值设置偏高,没有在问题初期就触发。
改进措施列了几条:第一,所有生产配置变更必须走人工审批,不能完全依赖自动部署;第二,数据库连接池、慢查询数、接口响应时间要增加更灵敏的告警阈值;第三,每周做一次恢复演练,确保备份和 binlog 回放流程可用;第四,后台接口统一接入限流和 WAF 规则。故障报告写完后发给客户和业务方,坦诚说明原因和补救措施,客户最终没有索赔,但要求我们提交一份改进计划。
现在回头看这二十四小时,真正让人后怕的不是错误本身,而是错误在自动发布后毫无阻拦地进入生产环境。运维工作就是这样,平时觉得无关紧要的一个参数,可能在后半夜让整个网站停摆。把每一次惊魂都变成防线,是唯一能让自己睡安稳觉的办法。