这类问题我又碰上了一次。nginx 1.24 做视频点播,拖动进度条时浏览器一直转圈,响应码是 206,Content-Range 看上去也对,文件放在本地 SSD,客户端每次要等五六秒才出画面。

第一反应是「aio 没开,大文件随机读走同步 IO,磁盘队列被排队打满」,验证下来不成立。

把日志和配置对完,能解释这个现象的基本就这几处。mp4 的 moov 盒在文件尾部,浏览器要发多次 range 请求才能拿到索引;sendfile 开着但 output_buffers 太小,一个分片要拆成很多次写;关掉了 proxy_cache,每个分片都回源,后端限速成了瓶颈。

量一次 range 请求的真实耗时

curl -r 0-1023 -o /dev/null -s -w '%{http_code} %{time_total} %{size_download}
' http://127.0.0.1/vod/demo.mp4

接着确认 moov 在文件头还是尾部

grep -abo moov demo.mp4 | head -3

随后打开 aio 和 directio 放大缓冲区

printf '%s
' 'aio on;' 'directio 8m;' 'output_buffers 8 512k;' > /etc/nginx/conf.d/vod.conf

reload 后复测同一段 range

nginx -t && nginx -s reload

改完先别撤,确认这几项。同一段 range 的 time_total 从五秒降到两百毫秒以内,拖动进度条立刻出画,206 的长度与请求区间一致。

补一句。moov 在尾部是移动端播放卡顿的头号原因,服务端怎么调都治不彻底;上线前用 ffmpeg -movflags faststart 重排一次索引最省事。如果同一现象隔几天又出现,说明根因没找到,别当偶发处理。

作者 9823189