线上问题记录20230610-NGINX代理大文件下载问题
问题描述
我们有一个在线项目:是一个对象文件存储服务,是用来给用户提供文件对象存储的。今天用户在使用的时候发现超过1G的文件无法进行下载。幸好今天是星期六,使用的人并不是特别多,我们立马去排查问题。
问题排查
后台代码排查
我们第一时间去排查了后台的服务日志。发现报错如下:
org.apache.catalina.connector.ClientAbortException: java.net.SocketTimeoutException
上面的问题经过分析可能的结果如下:
org.apache.catalina.connector.ClientAbortException
这是Tomcat服务器上的一个异常类,它表示客户端(浏览器)中断了与服务器的连接。java.net.SocketTimeoutException
这是Java网络编程中的一个异常类,它表示套接字操作超时。在这种情况下,连接建立后一段时间内没有收到数据,导致超时异常。
当这两个异常被组合在一起时,ClientAbortException: java.net.SocketTimeoutException
通常表示以下情况之一:
- 客户端在等待响应时,超时发生,可能是由于网络延迟或服务器处理请求的时间过长引起的。在这种情况下,客户端(浏览器)取消了与服务器的连接,因为它认为服务器已经不再响应。
- 客户端请求的数据量过大,导致服务器在发送响应之前超时。这可能是因为客户端发送了大量数据,而服务器在规定的时间内无法接收和处理完整个请求。
到这里我们仔细排查了我们后台的代码,代码中并没有限制文件的传输大小和超时时间,并且我们在内网的环境下直接对后台服务进行请求,下载超过1个G以上的文件并没有问题。
网关服务排查
排查确定了后台服务没有问题,这里我们怀疑是由于网关的限制造成的,我们使用的网关是NGINX,由它来做代理和负载均衡。
查看NGINX的报错日志如下:
2023/06/10 19:23:37 [error] 138672#0: *1504581 upstream prematurely closed connection while reading upstream
在网上搜索问题,发现了一个问题帖:https://github.com/owncloud/client/issues/5706
在这篇issue中通过设置proxy_request_buffering off;proxy_buffering off;
解决这个问题。因此可以确定应该是NGINX的缓存配置有问题。
查看NGINX的官方文档:http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_buffering
从NGINX的缓存配置中发现了一个参数:proxy_max_temp_file_size
从这里看到,默认缓存的临时文件大小为1024M就是1个G大小,这和我上面的问题一致,找到问题就好办了。
问题解决
这里我修改NGINX的代理配置,如下所示:
server {
listen 8000 ssl;
server_name server;
proxy_max_temp_file_size 10240M;
location / {
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Real-PORT $remote_port;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://localhost:9000;
}
}