解决 Nginx 在分发大文件时 Block 浏览器请求的情况

(不要问 Ovear 为什么最近突然诈尸了,我也不知道(:з」∠)

起源

接上一篇,Ovear 买了一大堆奇奇怪怪的 VPS 之后,弄了一个 CDN 又弄了一个图床,又闲得无聊想试试做个视频 CDN,于是在原本的 CDN 上面上传了几个视频文件,然后用浏览器打开,结果发现卡!住!了!,整个请求页面都 Block 住了。然而 Wget 却是没有这个问题(:з」∠)

原因

遇到了这个问题以后, Ovear 开始抓包和日志来诊断问题,发现 Nginx 在回源的时候,会主动忽略 Content-Range, 也就是当浏览器发送带有 Content-Range 的请求的时候, 并且 Nginx 并未缓存,此时 Nginx 就会忽略 Content-Range
并且进行回源缓存整个文件,而此时用户请求的只是文件的一部分,但是也必须等待到 Nginx 缓存到所指定的位置,才会返回。

解决方法

经过查询,Nginx 支持 Cache Lock, 具体的文档可以在这里查看 http://nginx.org/en/docs/http/ngx_http_proxy_module.html。当开启此设置后,Nginx 收到第一个请求后,便会在后台开始缓存。之后的请求全部打回源服务器,这样也就避免了在缓存不完整的情况下阻塞请求

存在的问题

但是这样解决也有一个缺点,当一个新的文件被推上后端服务器的时候,此时 CDN 还没有进行缓存,如果大量用户涌入(比如说新番刚更新的时候),会造成严重的缓存穿透,也就是 CDN 会失效, 流量会穿过 CDN直接打入源服务器。但是 Ovear 的后端服务器宽带还比较充足,目前也暂时不存在,当 CDN 还未缓存完成的时候,有大量用户涌入。

配置

涉及的配置主要有以下几个

proxy_cache_lock on | off; #是否开启 Cache Lock
proxy_cache_lock_timeout 5s; #这个设置指的是,当 Nginx 在后台缓存的时候,阻塞用户最长的时间,如果超过设置的时间则不继续等待,直接进行后端回源。(请记住,Nginx 只会缓存整个文件,即使请求是请求的一部分文件。)
proxy_cache_lock_age 5s; #后台请求缓存最大的超时时间,如果超时后还未缓存完毕,当再有新请求进入时,Nginx会重新在后台进行缓存
proxy_cache_use_stale off; #这个参数指的是,当在什么情况下,允许 Nginx 使用过期的缓存,具体的设置可以去官网文档查看。

解释完涉及的参数之后,我们就可以根据我们目前的目的(分发大型视频、二进制文件)对上面参数进行调整,以便我们进行调整。
最后调整的结果如下

location ~ .*\.(avi|fla|mp4|mp3|ogg|wav|mpg)$
{
    proxy_cache_lock on;
    proxy_cache_lock_timeout 600s; #因为我们分发的是大文件,10分钟未缓存完成的时候,我们才重新进行缓存,这个值可以用 分发文件平均大小 / 回源平均速度 算出,在这里 Ovear 分发的是 300M 左右的视频文件, 回源速度最差在 1M 左右, 所以 300s 左右就可以缓存完毕,但是为了避免最差情况出现,所以 Ovear 直接做了翻倍处理
    proxy_cache_lock_age 0s; #因为视频文件的 meta-inf 可能在尾部,为了让浏览器能够最快的播放,我们这里设置为只要没有缓存到的部分,立即回源
    proxy_cache_use_stale updating; #当缓存正在更新的时候,允许 Nginx 使用过期的缓存

    proxy_cache bigfilecache;
    proxy_cache_valid 200 12h;
    proxy_pass http://backend_bigfile;
}

结语

在这里 Ovear 分发的大部分都是,一上线就不进行更改的文件,所以使用过期缓存问题并不大。
经过这样设置后, Nginx 分发大型文件就没有问题了,也不会阻塞浏览器~
最后例行结尾,晒一晒自己的 CDN 嘻嘻。

解决 Nginx 在分发大文件时 Block 浏览器请求的情况 有 4 个评论

  1. 博主没发现评论名字的URL是本窗口跳转么。。。这样直接跳出自己的网站感觉好别扭

发表评论

电子邮件地址不会被公开。 必填项已用*标注