nginx经常被用来做生产的代理和负载均衡,它高效的处理能力,得到了很多公司的青睐。可是,随着业务的不断发展,随之而来,可能会因为nginx产生一些意想不到的问题,比如说幽冥请求。
本文所说的幽冥请求泛指以下几种情况:
一次客户端请求,前端能够收到返回的信息,但是后端位于不同VM的同个程序却被请求了多次,请求参数完全一致,并全部执行正常
一次客户端请求,前端报异常返回,但是后端位于不同VM的同个程序被请求多次,从业务日志角度排查,程序返回正常
客户端上传请求,出现一次上传了多个同样文件的情况
所谓的幽冥请求,其实就是本不该出现却又出现的请求。这里限定情况为明确客户端确实请求了一次的情况下。
在遇到过的幽冥请求案例中,大部分情况,程序上线后运行正常,经过了长时间未更改代码的运行后,突然就发生了幽冥请求情况。幽冥请求可能一直出现,也可能偶尔出现。通过nginx日志,可以确认来自客户端的请求只有一次,可是请求返回的时间较长。通过程序日志确定,请求正常可达,并且有正常的返回。事件发生后程序员都是没法从本地或者测试环境进行重现的。
问题究竟在哪呢?其实,问题出现在nginx的原生模块ngx_http_proxy_module配置上。对于ngx_http_proxy_module,其实大部分使用过的技术人员应该都不默认,它主要实现的是反向代理的功能,常用的配置如下:
可是,它有另外的几个配置却被忽略了:
以上几个配置,主要用于故障转移,当nginx将请求转发到对应服务器,但后期认为服务相应异常时,便会触发故障转移,其中各个配置解释如下:
重新回到幽冥请求上,大部分的情况,nginx配置了全局超时时间,为了方便各个业务,可能会设置的比较大,如5分钟,然而却没有配置代理超时时间,默认使用为60s。
如图,客户端请求到达nginx后,nginx进行了第一次的转发,但是由于转发到的VM处理速度较慢导致超过默认设置的超时时间,因此nginx进行了第二次的转发,该转发耗时45s后正常返回。
这种情况在客户端看来,请求只请求了一次,除了反应慢一点没有任何异常。在nginx的请求日志看来,客户端的请求只有一次。而程序看来,虽然处理时间较长,可是前一次请求确实正常返回结果了,而第二次请求,却像是凭空产生的一般。
其实,在排查的过程中,不难发现,重复请求产生的时间是有规律的,由于nginx代理超时时间为60s,所以重复请求产生的时间,应该是在上一轮请求之后的60s后。根据这样的规律,便不难查出原因了。
总结,遇到上述问题的时候,为保生产,应该第一时间将代理过期时间设置为合理的区间,保证生产正常运行。但是,一个接口的请求时长过程,本身也算是一种潜在的问题,应该及时优化解决。将代理过期时间设长,应该事用在大文件上传或者一些实在无法避免的问题上。
领取专属 10元无门槛券
私享最新 技术干货