记一次前端提交文件请求超时问题

问题环境:

华为云

问题现象:

前端浏览器提交请求(请求中包含表单参数、文件,且文件大小超过1.5M左右),浏览器在发出请求10秒后提示网络异常,并在console控制台中打印如下日志:

同时在后端服务日志中看到整个请求进入到具体服务的处理时长为3秒左右,远小于浏览器的10秒超时;

同时单独的上传附件(异步、el-upload控件),并没有出现以上超时问题;

问题原因:

前端Axios中统一设置了10秒超时,导致前端浏览器在后端请求返回时间超过10秒后自动超时断开;

扫描二维码关注公众号,回复: 9986472 查看本文章

问题分析:

前端浏览器显示了10秒超时,而后端服务的处理时间远小于10秒,所以问题没有出在后端服务的处理速度上,起初认为是各种环境(Isito、K8s)引发了超时问题,但是其实我们普遍都忽略了一个问题,就是具体服务日志的处理时间不代表整个Http请求的处理时间,尤其在包含文件上传的请求中尤为明显;

通过Chrome浏览器控制台可以查看一个请求的具体Timing,如下图为具体的一次Timing统计:

大家注意到这次请求的总共耗时15.34s,而其中Request Sent耗时9.87s,Waiting耗时5.46s,Content Download耗时6.20ms,

Request Sent可以简单理解为浏览器端将所有请求数据(表单参数、文件)传输到服务器的时间,

Wating为服务器收到前端浏览器提交的数据后进行处理的时间,

Content Download为服务器返回响应到浏览器的传输时间,

也就是说在提交请求时,花费了将近10秒左右的时间才把浏览器端的请求(参数、>1.5Mb文件)提交到服务器,尽管后端具体服务的处理时间可能才2~3s的时间,但总共的请求时间早已超过10s,最终引发了前端浏览器报出10s超时;

以上Timing是在调大了前端超时时间(60s)后获得,引发超时的请求无法获得Timing统计;

具体Timing说明可参考如下图片:

其实,最开始这个问题的排查是从后端Nginx入手并发现问题的,在后端Nginx日志中发现如下异常:

100.125.68.209 - - [12/Sep/2019:17:06:08 +0800] xxx.xxx.com "POST /mx_dspt_service/web/500105/13/98427144886030336/formDispatcher/11/257/0/dGJveC9yZWYvc2F2ZUZvdGFUYm94VXBncmFkZVJlZg== HTTP/1.1" xxx.xxx.com 499 0 "http://xxx.xxx.com/" "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3730.400 QQBrowser/10.5.3805.400" "-" 9.954 - /mx_dspt_service/web/500105/13/98427144886030336/formDispatcher/11/257/0/dGJveC9yZWYvc2F2ZUZvdGFUYm94VXBncmFkZVJlZg== -

Http返回码为499,且文件>1Mb,dspt、ota服务都处理完成,且日志均已打印成功,

通过查看Nginx相关文档,发现499含义如下:

即客户端主动关闭了连接,导致服务端无法返回响应;

加之在反复提交请求的过程中出现了一次成功请求,并注意到了Timing统计,才最终确定问题根源出现在前端的10s超时设置;

扩展:

之前在测试环境都好好的,怎么一切到云环境上就出现超时呢?

测试环境都走的内网,而云环境都需要通过外网后再进入到ELB,

外网的传输速度相比于内网速度会相应慢一些,所以外网才会会出现超时;

如下为目前华为云服务架构:

我们在浏览器发出的请求过程如下:

(1)浏览器发出请求,

(2)首先会进入到华为云的ELB(弹性负载均衡,可以简单理解为云上的Nginx,做请求负载、请求转发的,云环境的入口),

(3)之后由ELB转发请求到Nginx(之所以添加了Nginx层,是由于Https证书、私钥绑定在Nginx上),

(4)Nginx将请求转发到Istio的网关Gateway(Istio集群的外部域名调用入口,在k8s中为Ingress),

(5)Istio Gateway将请求最终转发到我们的具体服务(其实在Istio中请求首先转发到每个服务对应的边车Sidecar Envoy上,之后由边车再将请求转发到我们的服务)

以上 浏览器->ELB,ELB->Nginx,Nginx-> Gateway,Gateway->Sidecar,Sidecar->app均有传输耗时,但是只有 浏览器->ELB需要通过外网传输,而其他传输都发生在内网耗时较少,

所以一开始提到的前端传输超时(Request Sent)可以理解为主要是受到 浏览器->ELB 传输耗时的影响;

关于Nginx,即可以将Https相关设置放到Istio Gateway中,如此只需依赖Istio即可(将Https与ELB、Nginx进行解耦),

日后亦可对华为云架构调整如下:

解决方案:

(1)针对个别请求(带有文件提交、导入文件的请求)调整前端请求超时时间(例如由10s调整为60s);

(2)优化网络传输速度(外网速度、华为云ELB传输速度);

补充:

目前大多数服务都是通过后端将文件上传到云存储(浏览器 -> 服务网关Dspt-> 具体服务 -> 云存储),

即大致存在3次文件上传:

(1)浏览器->服务网关Dspt的文件上传(耗时最长,通过外网进入到ELB或网关,后再进入dspt,此处存在多次文件上传,为了便于理解统一归为1次),

(2)服务网关dspt->具体服务的文件上传(内网传输,耗时相对较短),

(3)具体服务->云存储的文件上传(耗时较长,视具体云存储服务性能和网络情况)

若文件可以进行异步上传(附件上传),则均可通过前端浏览器直接上传(前端请求后端获取相应token后直接在前端进行云存储的上传操作),并将上传成功后的文件URL提交给后端服务,以上方式即可省掉前2次的文件上传(节省服务器资源、减少网络传输耗时),而仅通过浏览器直接进行1次文件上传即可,以减少文件上传耗时;

发布了56 篇原创文章 · 获赞 6 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/luo15242208310/article/details/100883057