1.引出问题
Nginx可以作为静态资源服务器,比如我们访问192.168.110.97:80
,熟悉的nginx欢迎界面,这其实也是nginx为我们提供的一个静态文件:index.html
。
既然是静态资源,那我们能否优化一下传输效率呢?
1)sendfile文件高效传输模式。如何开启?它的原理到底是什么呢?
2)数据量大,传输效率低,如何进行优化?
2.sendfile高效传输
在nginx.conf
中配置sendfile on;
指令就可以开启文件高效传输模式,那么它的原理是什么呢?
话不多说,走起。
sendfile的实现原理是通过调用内核提供的sendfile()调用来实现的。调用过程中,内核会将源文件的数据直接传输到socket中,而不需要将数据先拷贝到用户空间再进行传输。这样就可以避免数据在用户空间和内核空间之间的多次拷贝,从而提高了文件传输的效率。
既然是这样,那么普通传输模式和高效传输模式之间的区别就越发清晰了。
1)普通传输模式
发起文件读取命令–》读取文件到内核空间–》拷贝文件到用户空间–》拷贝文件到socket内核空间–》传输给socket
2)高效传输模式
发起文件读取命令–》读取文件到内核空间–》拷贝文件到socket内核空间–》传输给socket
3)小结
1)普通传输模式涉及到多次内核态与用户态之间的切换,这很消耗系统资源。
2)sendfile高效传输模式,直接在内核态进行数据传输,不涉及内核态与用户态之间的切换,传输效率大大提升。
3.gzip文件压缩
前面我们提到过,开启sendfile文件高效传输模式,可以提升传输的效率。其实,只做到这一步还是不够的,一旦文件的数据量较大,传输的速度又会大打折扣。
比如一部电影的大小是2G,下载时间很长,严重影响我们的观影体验,如果能够压缩到1G,那传输的时间就会减半。
Nginx为我们提供了gzip相关的模块,帮助实现对文件的压缩。
3.1 ngx_http_gzip_moudle
据nginx官方文档介绍,通过ngx_http_gzip_moudle提供的压缩功能,有助于将数据的大小减少一半甚至更多。👍
nginx已默认为我们安装该模块。接下来我们配置其指令。
1)配置是否开启gzip
作用域:http, server, location, if in location
语法:gzip on | off;
默认值:
gzip off;
2)配置gzip可压缩的响应类型
作用域:http, server, location
语法:gzip_types mime-type …;
默认值:
gzip_types text/html;
可以看到,我们可以配置多个mime-type,并且可以使用*
匹配所有的mime-type。
🔔Tips:通常不会使用*
进行匹配,如果所有的类型都开启压缩,如果本身静态资源的可压缩性不高,就会造成系统资源的浪费。
到这里,我们可以来体验一下开启gzip之后的压缩效果。
1)准备静态文件/usr/local/nginx/html/jquery.js
下载地址:https://code.jquery.com/jquery-3.6.4.js
2)增加location块
location /jquery {
root html;
}
访问http://192.168.110.98/jquery.js,查看文件大小:304kb
3)开启gzip
为了保持配置文件清爽,我们只对gzip压缩相关指令进行注释说明。
worker_processes 1;
gzip on;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name localhost;
location / {
root html;
index index.html index.htm;
}
# 测试gzip压缩效果
location /jquery {
# 配置可压缩的响应类型
gzip_types text/javascript;
root html;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
访问http://192.168.110.98/jquery.js,查看文件大小:107kb
3)配置gzip压缩级别
作用域:http, server, location
语法:gzip_comp_level level;
默认值:
gzip_comp_level 1;
🔔Tips:gzip默认压缩级别为1,可设置的值为1-9,值越高压缩程度越高,但是不一定值越高效果就越好,我们还是需要根据文件的可压缩性设置合适的压缩级别,否则也会造成系统资源的浪费。
4)配置根据User-Agent禁用gzip
作用域:http, server, location
语法:gzip_disable regex …;
作用:如果请求的User-Agent头信息与正则表达式匹配,则禁用gzip压缩功能
🔔Tips:User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 YaBrowser/23.3.4.594 Yowser/2.5 Safari/537.36
,可以根据需要配置正则表达式。
5)配置gzip可压缩响应的最小长度
作用域:http, server, location
语法:gzip_min_length length;
默认值:
gzip_min_length 20;
🔔Tips:默认单位为byte,长度是由Content-Length
响应头决定,如果长度低于设置的值,就关闭gzip压缩。建议设置为1kb以上。
6)gzip与sendfile的冲突问题
我们知道,开启sendfile文件高效传输模式,文件在内核空间直接传输给socket,不会经过用户程序,开启gzip之后,该模式也就失效了。那么怎么解决这个问题呢?
3.2 ngx_http_gzip_static_module
前面提到的gzip与sendfile的冲突问题,我们可以通过引入
ngx_http_gzip_static_module
模块来进行解决。该模块允许发送文件扩展名为.gz
的预压缩文件。
🔔Tips:nginx默认不会添加该模块,需要我们自行引入。
配置指令:
作用域:http, server, location
语法:gzip_static on | off | always;
默认值:
gzip_static off;
gzip_static on;
或gzip_static off;
都会检测是否存在.gz
预压缩文件。
gzip_static always;
会始终使用.gz
预压缩文件。
1)对文件进行压缩,使用gzip命令
cd /usr/local/nginx/html
gzip jquery.js
2)修改配置文件
# gzip on;
gzip_static on;
我们再次访问http://192.168.110.98/jquery.js,文件大小为87.5KB,访问的是压缩过的.gz
文件。
以上就是Nginx对静态资源传输的优化,Nginx是多模块化的,还有很多高级功能,我们后面继续探索。