线上部分上传失败问题解决记录
问题排查
新接手的系统,操作人上传健康码截图的。总是有人陆陆续续报上传失败,但是每次都是不一样的人,且绝大部分都是iphone 手机端,起初怀疑是前端的问题。
后来加了日志,发现的确应用端没有收到请求。前端排查代码也没有发现任何问题。最后怀疑是网络较慢,求超时。所以当时想前后端都增加一下请求的超时时间。
后来在看nginx配置的时候发现配置如下
1 | include mime.types; |
client_header_timeout 和 send_timeout 都是1分钟,应该是足够了。但是看到下面一个配置 client_max_body_size 请求body_size 只有3m 。
而在 spring boot 应用里面配置的限制是 10M
1 | spring.servlet.multipart.max-file-size=10MB |
因为系统需要上传健康码、行程码、核酸报告三个图片,并且是在一个请求中上传的, 而 iphone 的截图大的有 1-2M 这么大,三张图大小偶尔会超过 3M, 所以才导致很难复现且飘忽不定。
我都是用的安卓收集,从来没有出现过这个问题是因为安卓的截图基本都是几百kb。所以最终解决方案 client_max_body_size 50m;
ps. nginx 的超时时间配置
client_header_timeout timeout
设置读取客户端请求头超时时间,默认为60s,如果在此超时时间内客户端没有发送完请求头,则响应408(RequestTime-out)状态码给客户端。
client_body_timeout timeout
设置读取客户端内容体超时时间,默认为60s,此超时时间指的是两次成功读操作间隔时间,而不是发送整个请求体的超时时间,如果在此超时时间内客户端没有发送任何请求体,则响应408(RequestTime-out)状态码给客户端。
send_timeout timeout
设置发送响应到客户端的超时时间,默认为60s,此超时时间指的也是两次成功写操作间隔时间,而不是发送整个响应的超时时间。如果在此超时时间内客户端没有接收任何响应,则Nginx关闭此连接。
keepalive_timeout timeout [header_timeout]:设置HTTP长连接超时时间,其中:
第一个参数timeout是告诉Nginx长连接超时时间是多少,默认为75s。
第二个参数header_timeout是用于设置响应头“Keep-Alive: timeout=time”,即告知客户端长连接超时时间。
两个参数可以不一样,“Keep-Alive:timeout=time”响应头可以在Mozilla和Konqueror系列浏览器起作用,而MSIE长连接默认大约为60s,而不会使用“Keep-Alive: timeout=time”。
如Httpclient框架会使用“Keep-Alive: timeout=time”响应头的超时(如果不设置默认,则认为是永久)。如果timeout设置为0,则表示禁用长连接。
ps. springboot 配置
springboot 不同版本的配置不一样。
springboot1.3或更早版本中:
1 | multipart.max-file-size |
在springboot1.4与springboot1.5版本中:
1 | spring.http.multipart.max-file-size=-1 |
在springboot2.0版本中:
1 | spring.servlet.multipart.max-file-size=-1 |