这个坑值得记一笔。CentOS 7.9 + nginx 1.18 反向代理文件下载服务,为了让进度条实时刷新,运维把 proxy_buffering 关掉,之后大文件并发到二十个,后端就报 too many open files,nginx 侧五零二一片。
刚开始盯着「没有给下载单独限并发,二十个大文件同时来,后端进程池被同步读文件的请求占满」,折腾了半个多小时,排掉了。
把日志和配置对完,能解释这个现象的基本就这几处。关掉缓冲后 nginx 变成逐字节透传,上游连接要一直保持到客户端收完,一个下载占一条;客户端网速慢,上游连接被慢速消费拖着不放,keepalive 池很快被耗尽;缓冲回退到临时文件时目录不在数据盘,写入又把根分区拖慢。
动手时先确认缓冲和临时文件相关的当前配置
grep -E 'proxy_buffering|proxy_max_temp_file_size|proxy_temp_path' /etc/nginx/conf.d/download.conf
随后改回缓冲模式并给足缓冲区
sed -i 's/proxy_buffering off;/proxy_buffering on; proxy_buffers 16 128k; proxy_busy_buffers_size 256k;/' /etc/nginx/conf.d/download.conf && nginx -t
给下载接口按来源地址限并发
sed -i '/http {/a\ limit_conn_zone $binary_remote_addr zone=dl:10m;' /etc/nginx/nginx.conf && sed -i '/proxy_buffering on;/a\ limit_conn dl 4;' /etc/nginx/conf.d/download.conf && nginx -s reload
等前面都确认过,再看后端连接是否还在疯长
ss -tan state established '( sport = :8080 )' | wc -l
改完先别撤,确认这几项。同样压二十个大文件,后端 established 连接数稳定在个位,nginx 日志不再出现五零二,error.log 里没有 too many open files。
这里还有个坑。缓冲换来的代价是首字节变慢,对实时性有要求的小接口单独开 location 关缓冲,别整站一刀切。报错文案容易误导,真正的原因往往在相邻那一层的日志里。
