Nginx大文件下载时发生错误(104 Connection reset by peer):问题排查与解决

0 阅读3分钟

场景复现

目前生产环境中有一个下载功能,访问下载链接时首先会通过nginx调用后端鉴权接口,校验通过后再反代文件服务器url通过浏览器进行下载。在文件大小为几百M时无问题,但是当文件过大(超过1G)时会下载失败:浏览器正常下载,当下载进度条满时会突然显示“无法下载-网络问题”:

image.png

问题排查

此时查看nginx错误日志,显示:104: Connection reset by peer

2025/05/20 17:20:44 [error] 1929#1929: *895853 readv() failed (104: Connection reset by peer) while reading upstream, client: 客户端IP, server: 本机服务器域名.com, request: "GET /file/download/文件下载/v1/目标文件.zip?auth=a1eb9896fef74744ac2f2d8d3bda7cf5 HTTP/2.0", upstream: "http://反代IP地址/file/download/文件下载/v1/目标文件.zip?auth=a1eb9896fef74744ac2f2d8d3bda7cf5", host: "本机服务器域名.com", referrer: "https://本机服务器域名.com/publish"

上游文件服务器是支持大文件下载的,所以问题一定出在nginx配置上。

根据错误日志104: Connection reset by peer得知:

连接提前被上游close掉了,errno = 104错误表明你在对一个对端socket已经关闭的的连接调用write或send方法,在这种情况下,调用write或send方法后,对端socket便会向本端socket发送一个RESET信号,在此之后如果继续执行write或send操作,就会得到errno为104,错误描述为connection reset by peer。

所以当Ngin未设置缓冲区大小proxy_buffer_size时(默认为4或8KB),当缓冲区满时,Nginx 会通过TCP滑动窗口机制通知上游暂停发送数据(降低传输速度)。上游无法等待那么久,可能会因长时间等待而主动断开连接。

解决方法

在Nginx对应反代配置中添加缓冲区和超时有关配置并启用TCP keepalive:

location ^~ /file/download/ {
    #....原有配置

    proxy_buffering on;
    proxy_buffers 8 10M;
    proxy_buffer_size 4k;
    proxy_busy_buffers_size 20M;
    #控制写入临时文件时的缓冲大小,必须大于等于`proxy_buffer_size`和`proxy_buffers`中任意一个 buffer 的大小
    proxy_temp_file_write_size 20M; 
    
    # 超时设置
    proxy_connect_timeout 10s; # 与上游建立连接的最大等待时间
    proxy_send_timeout 300s;   # 向上游发送请求体(如大文件上传)过程中,如果某段时间无数据传输就超时
    proxy_read_timeout 1800s;  # 从上游读取响应(如大文件下载)过程中,如果某段时间无数据传输就超时
    send_timeout 300s;         # 向客户端发送响应数据过程中,如果客户端长时间不读取数据就断开
    
    proxy_socket_keepalive  on;

    #....
}

成功解决🎉🎉