一 问题描述
接到上游调用方反馈到服务一直504,根本没办法使用,同时机器cpu 监控一直报警
二 问题排查过程
解决思路1
-
思路一: 接口本身处理比较耗时,加上上游并发请求比较大,所以才会一直报警
-
思路一解决方案: 确实也是如此,如果你的服务处理非常快且不是特别消耗资源那么确实不会在目前的并发下出现密集的504问题。
那么先优化目前的接口。 接口是提供图像ocr功能,会加载深度学习模型的模型文件,代码中每一次请求都会重新实例化一个对象,这样做就会存在两个问题:
1,每次请求都去load 一次模型文件,这部分IO操作其实还是比较耗时的,而且是没有必要;
2 每个请求都实例化一个对象,那么在高并发下,系统的内存会很吃紧。
所以针对这个问题,定义了一个全局的对象,让该进程的所有请求都用同一个对象去处理。 -
思路一存在问题: 该方案确实减少了每次请求的耗时,同时也减少了内存的占用。更新服务后并没有解决, 而且ocr请求耗时取决于你传入图片的大小,如果图像太大,元素太多,耗时问题同样无解
解决思路2
-
思路二: 504问题的就是超时问题,是不是我的nginx超时时间的问题。
-
思路二解决方案: 确实也是如此,nginx初始超时时间是在一些较小图像下得到的一个值,但是现在上游调用传入的图像比较大,那么在并发比较大的情况下,肯定都超过了这个时间,所以才会一直返回504
ok,将超时时间设置大一点
- 思路二存在问题: 虽然问题解决了,但是其实没有完全解决。 为什么修改了nginx超时时间后,我的服务实例的CPU压力降了下来???
总结思路
-
504问题: 修改了nginx超时时间,所以大部分请求能够正常返回了
-
cpu超负荷问题:
虽然服务本身比较吃CPU,但是在目前的请求并发下不应该完全打满。因为在nginx超时时间是1s时候,上游调用504后都会重新请求多次。这里需要注意下⚠️: 虽然调用client和nginx的链接断开了,但是服务实例还是在继续处理该次请求,直到请求处理完成,这样直接导致了流量被扩充了N倍!!!(不断重试) -
最终解决方案
1、 接口本身优化,尽量提升处理速度,尽量减少系统占用资源
2、 nginx + 服务本身 超时设置,如果断开的链接,就没有必要继续去执行,浪费系统资源
3、 预估服务的能力,设定访问限制(每秒请求多少),将超过限制的流量挡住
三 总结
在高并发,高可用的需求下,确实是有一套好的方法论供参考。或许只有自己真正在遇到问题后才会去理解学习,这样其实并不好,应该学会在设计系统时候将这些潜在的风险都尽量考虑周全
日常记录,有问题欢迎指出,自己搞清楚的同时也不想误导他人