故障说明
之前官网曾出现过一次故障,为了防止故障再次发生,需要对官网服务完善一些监控指标。7.9 号,完善监控指标的过程中,意外发现某服务的 access.log 中持续出现一些状态码为 499
的接口请求。与业务方沟通后确认疑似问题接口为"用户预约接口",通过获取请求关联的手机号,我们抽查了 20 条数据, 2 条在数据库中找不到相关记录,其余 18 条数据最终落库成功。基于此我们推断该故障不止会影响用户体验,而且确实会影响到实际用户注册量。
分析 Root Cause
HTTP 499
An Nginx specific error code, which means that the client closed the connection before the server answered the request, usually caused by client side timeout.
根据 499
http code 的定义,说明是客户端在服务端请求返回前主动断开了连接,由于是客户端行为,再结合近期频繁的安全事件,初始时我们怀疑有人恶意攻击,故意消耗服务端资源。
是否属于恶意攻击?
我们首先找安全同事核查了 WAF 的配置和日志,但并没有收获。后面跟 ops 同事一起梳理了服务的架构,整理出该接口请求的完整链路: 用户 -> WAF -> LB -> Nginx -> pm2 -> nodejs,基于此我们开始分析 499
请求的可能原因。
既然 499
说明用户端主动断开请求,那我们首先要搞清楚的是,用户端断开请求是原因还是结果。
proxy_ignore_client_abort on | off;
Determines whether the connection with a proxied server should be closed when a client closes the connection without waiting for a response.
我们修改了 Nginx 配置 proxy_ignore_client_abort on
,这样即便客户端主动关闭了,Nginx 仍然会等到后端服务的返回。配置生效后,马上接口异常调用的状态码由 499
变成 504