项目场景:
浏览通过Nginx代理请求下载超过1GB文件
问题描述
前几天项目开发时发现,通过 Nginx 代理下载 超过1GB的大文件时,出现"网络错误",而在服务器上下载时却很正常。经确认排除嫌疑,最后发现是 Nginx Buffer 的锅。下面就来聊聊这个问题是怎么发生的。
原因分析:
Nginx Buffer 机制默认处于开启状态,其会根据 proxy_buffer_size 和 proxy_buffers 这两个参数控制写入内存的大小。
如果响应大于这个 buffer 大小,Nginx 会继续通过 proxy_max_temp_file_size 参数将响应其余部分写入到磁盘临时文件。
我遇到的问题:proxy_max_temp_file_size 默认为 1G,当客户端的网络比较慢时,临时文件很快就被写满。这时候后端的响应还会继续被接收到 socket 缓冲区,直到缓冲区被打满。
此时,Nginx 所在服务器通过滑动窗口 zero 0 告知后端服务器停止发送数据,直至触发了后端的 write 超时。
解决方案:
proxy_max_temp_file_size 2048m
* 调整 proxy_max_temp_file_size 大小
调大:让临时文件足够可以缓冲整个响应
调小:让整个链路上的数据流动起来,不要阻塞后端的 write 操作,进而触发后端的超时
* 关闭 Buffer:不推荐,会影响 Nginx 到后端的连接复用
补充:
关于proxy_buffering:
proxy_buffering这个参数用来控制是否打开后端响应内容的缓冲区,如果这个设置为off,那么proxy_buffers和proxy_busy_buffers_size这两个指令将会失效。但是无论proxy_buffering是否开启,对proxy_buffer_size都是生效的。
proxy_buffering开启的情况下,nignx会把后端返回的内容先放到缓冲区当中,然后再返回给客户端(边收边传,不是全部接收完再传给客户端)。临时文件由proxy_max_temp_file_size和proxy_temp_file_write_size这两个指令决定的。如果proxy_buffering关闭,nginx会立即把从后端收到的响应内容传送给客户端,每次取的大小为proxy_buffer_size的大小,这样效率肯定会比较低。
注:proxy_buffering启用时,要提防使用的代理缓冲区太大。这可能会吃掉你的内存,限制代理能够支持的最大并发连接数。
另,可以参考以下步骤
设置一,不限制临时文件大小
vim /etc/nginx/weijishu.conf
加入如下配置,
server {
#...
location / {
#...
proxy_max_temp_file_size 0;
#...
}
}
配置修改完成后,需要重载服务使配置生效,
systemctl reload nginx.service
注:缓冲区大小无限制,一直下载完整个文件
设置二,关闭代理响应缓存(可选)
vim /etc/nginx/nextcloud.cmdschool.org.conf
加入如下配置,
server {
#...
location / {
#...
proxy_buffering off;
#...
}
}
注:参数“proxy_buffering”设置为“off”则回应收到立刻同步传递到客户端
配置修改完成后,需要重载服务使配置生效,
systemctl reload nginx.service