场景:当用nginx作为反向代理,并对上游响应进行缓存的时候,当响应文件很大,而nginx处理这样大响应时,效率就很低下了,特别是多个请求同时到达没有缓存的大文件时,性能非常糟糕
Nginx为我们提供了slice模块,可以通过range协议把一个很大的响应分解为小的响应来提升性能
文档
ngx_http_slice_module模块是一个过滤器,它将一个请求分解为多个子请求,每个子请求返回一定范围的响应。过滤器提供了更有效的大响应缓存
为0表示禁用这个功能
分解成独立的缓存
运行流程:
第一步,客户端请求100个字节(150-250),发到nginx后,nginx根据它的slice配置(配置为100),也就是说从0-99,100-199,200-299,他切成了三块,当然这个文件有多大,最终就会切成多少块,nginx就会在第二步构造出两个请求,一个是100-199,一个是200-299,这两个请求返回以后会生成两个文件,一个是slice100-199,一个是200-299,然后nginx把他俩组合起来,生成150-249的这样一个响应
演示:
curl -r 500000-500010 http://47.94.161.71/test.mp4 -I
curl -r表示客户端使用range协议分片访问一个大的文件,本次测试只访问大文件的500000-500010字节
结果如下:
HTTP/1.1 206 Partial Content
Server: openresty/1.15.8.1
Date: Thu, 01 Aug 2019 12:58:04 GMT
Content-Type: video/mp4
Content-Length: 11
Last-Modified: Thu, 01 Aug 2019 09:43:26 GMT
Connection: keep-alive
ETag: “5d42b43e-52c274”
Content-Range: bytes 5000000-5000010/5577409
tail -f ../logs/access.log
可以看到返回的确实只有11个字节(Content-Length),但是上游却返回了5M,这是nginx做的一个优化,你只是访问了一个大文件的一小部分,但nginx考虑到如果我一次向上游获取到整个的响应内容,你后续访问其他的这些,就可以直接使用我的缓存了,这只是一种场景,如果说我们的服务是并发的,同时有多个客户并发的访问这一块的话,会引发很严重的问题,因为很多请求都去访问一个巨大的文件了,这是slice模块就有了用武之地
使用slice模块要配置三个地方
注意:
slice后面要有一个单位,以多大的文件切分,如果太小会造成有很多文件,太多则效果不明显
proxy_cache_key一定要加上$slice_range
proxy_set_header 定义一个请求头部,保证range是发到上游的
可以看到发到上游的只有1m
127.0.0.1 - - [02/Aug/2019:15:58:32 +0800] "GET /ceshi HTTP/1.0" 206 1048576 "-" "curl/7.47.0"