这一篇记录一下Nginx压缩缓存相关的指令,各位看到此博客的小伙伴,如有不对的地方请及时通过私信我或者评论此博客的方式指出,以免误人子弟。多谢!
目录
优化
sendfile
tcp_nopush
tcp_nodelay
压缩
体验示例
相关配置
gzip
gzip_types
gzip_comp_level
gzip_vary
gzip_buffers
gzip_disable
gzip_http_version
gzip_min_length
Web缓存
Web缓存种类
浏览器缓存
为什么使用浏览器缓存
浏览器缓存的执行流程
浏览器缓存相关指令
expires
add_header
测试
优化
Nginx对静态资源如何进行优化配置。这里从三个属性配置进行优化:
sendfile on;
tcp_nopush on;
tcp_nodeplay on;
sendfile
用来开启高效的文件传输模式。
语法 | sendfile on |off; |
默认值 | sendfile off; |
位置 | http、server、location... |
请求静态资源的过程:客户端通过网络接口向服务端发送请求,操作系统将这些客户端的请求传递给服务器端应用程序,服务器端应用程序会处理这些请求,请求处理完成以后,操作系统还需要将处理得到的结果通过网络适配器传递回去。
tcp_nopush
该指令必须在sendfile打开的状态下才会生效,主要是用来提升网络包的传输效率。
语法 | tcp_nopush on|off; |
默认值 | tcp_nopush off; |
位置 | http、server、location |
tcp_nodelay
该指令必须在keep-alive连接开启的情况下才生效,来提高网络包传输的实时性。
语法 | tcp_nodelay on|off; |
默认值 | tcp_nodelay on; |
位置 | http、server、location |
经过刚才的分析,"tcp_nopush"和”tcp_nodelay“看起来是"互斥的",那么为什么要将这两个值都打开,这个大家需要知道的是在linux2.5.9以后的版本中两者是可以兼容的,三个指令都开启的好处是,sendfile可以开启高效的文件传输模式,tcp_nopush开启可以确保在发送到客户端之前数据包已经充分“填满”, 这大大减少了网络开销,并加快了文件发送的速度。 然后,当它到达最后一个可能因为没有“填满”而暂停的数据包时,Nginx会忽略tcp_nopush参数, 然后,tcp_nodelay强制套接字发送数据。由此可知,TCP_NOPUSH可以与TCP_NODELAY一起设置,它比单独配置TCP_NODELAY具有更强的性能。所以我们可以使用如下配置来优化Nginx静态资源的处理。
压缩
经过上述内容的优化,我们再次思考一个问题,假如在满足上述优化的前提下,我们传送一个1M的数据和一个10M的数据那个效率高?,答案显而易见,传输内容小,速度就会快。那么问题又来了,同样的内容,如果把大小降下来,我们脑袋里面要蹦出一个词就是"压缩",接下来,我们来学习Nginx的静态资源压缩模块。
在Nginx的配置文件中可以通过配置gzip来对静态资源进行压缩。
体验示例
我们在html目录下放入一个jquery-1.10.1.js文件,访问 http://127.0.0.1/jquery-1.10.1.js,结果如下:
配置开启压缩后,如下:
gzip on;
gzip_types application/javascript;
相关配置
gzip
该指令用于开启或者关闭gzip功能。
语法 | gzip on|off; |
默认值 | gzip off; |
位置 | http、server、location... |
注意只有该指令为打开状态,下面的指令才有效果。
gzip_types
该指令可以根据响应页的MIME类型选择性地开启Gzip压缩功能。
语法 | gzip_types mime-type ...; |
默认值 | gzip_types text/html; |
位置 | http、server、location |
所选择的值可以从mime.types文件中进行查找,有些类型比如图片、视频等本身压缩了也节省不了多少空间,反而会浪费CPU资源,所以在选择压缩的时候需要注意是否有必要进行压缩。
http{
gzip_types application/javascript;
}
gzip_comp_level
该指令用于设置Gzip压缩程度,级别从1-9,1表示压缩程度最低,效率最高,9刚好相反,压缩程度最高,但是效率最低最费时间,所以使用时,注意并不是级别越高越好。建议设置在中间值5/6即可。
语法 | gzip_comp_level level; |
默认值 | gzip_comp_level 1; |
位置 | http、server、location |
gzip_vary
该指令用于设置使用Gzip进行压缩发送是否携带“Vary:Accept-Encoding”头域的响应头部。主要是告诉接收方,所发送的数据经过了Gzip压缩处理。
语法 | gzip_vary on|off; |
默认值 | gzip_vary off; |
位置 | http、server、location |
开启后,在浏览器中可以看到多了一项,如下标红部分:
gzip_buffers
该指令用于处理请求压缩的缓冲区数量和大小。
语法 | gzip_buffers number size; |
默认值 | gzip_buffers 32 4k|16 8k; |
位置 | http、server、location |
其中number:指定Nginx服务器向系统申请缓存空间个数,size指的是每个缓存空间的大小。主要实现的是申请number个每个大小为size的内存空间。这个值的设定一般会和服务器的操作系统有关,所以建议此项不设置,使用默认值即可。
gzip_disable
针对不同种类客户端发起的请求,可以选择性地开启和关闭Gzip功能。
语法 | gzip_disable regex ...; |
默认值 | — |
位置 | http、server、location |
regex:根据客户端的浏览器标志(user-agent)来设置,支持使用正则表达式。指定的浏览器标志不使用Gzip.该指令一般是用来排除一些明显不支持Gzip的浏览器。
gzip_disable "MSIE [1-6]\.";
gzip_http_version
针对不同的HTTP协议版本,可以选择性地开启和关闭Gzip功能。
语法 | gzip_http_version 1.0|1.1; |
默认值 | gzip_http_version 1.1; |
位置 | http、server、location |
该指令是指定使用Gzip的HTTP最低版本,该指令一般采用默认值即可。
gzip_min_length
进行压缩响应页面的最小长度,响应页面的大小可以通过头信息中的Content-Length
来获取,如果设置的值大于content-length将不进行压缩。
语法 | gzip_min_length length; |
默认值 | gzip_min_length 20; |
位置 | http、server、location |
nignx计量大小的单位:bytes[字节] / kb[千字节] / M[兆]
例如: 1024 / 10k|K / 10m|M
Web缓存
Web缓存是指一个Web资源(如html页面,图片,js,数据等)存在于Web服务器和客户端(浏览器)之间的副本。缓存会根据进来的请求保存输出内容的副本;当下一个请求来到的时候,如果是相同的URL,缓存会根据缓存机制决定是直接使用副本响应访问请求,还是向源服务器再次发送请求。比较常见的就是浏览器会缓存访问过网站的网页,当再次访问这个URL地址的时候,如果网页没有更新,就不会再次下载网页,而是直接使用本地缓存的网页。只有当网站明确标识资源已经更新,浏览器才会再次下载网页。
Web缓存种类
客户端缓存: 浏览器缓存。
服务端缓存: Nginx / Redis / Memcached等。
浏览器缓存
是为了节约网络的资源加速浏览,浏览器在用户磁盘上对最近请求过的文档进行存储,当访问者再次请求这个页面时,浏览器就可以从本地磁盘显示文档,这样就可以加速页面的阅览。
为什么使用浏览器缓存
- 成本最低的一种缓存实现。
- 减少网络带宽消耗。
- 降低服务器压力。
- 减少网络延迟,加快页面打开速度 。
浏览器缓存的执行流程
HTTP协议中和页面缓存相关的字段,我们先来认识下:
header | 说明 |
Expires | 缓存过期的日期和时间 |
Cache-Control | 设置和缓存相关的配置信息 |
Last-Modified | 请求资源最后修改时间 |
ETag | 请求变量的实体标签的当前值,比如文件的MD5值 |
(1)用户首次通过浏览器发送请求到服务端获取数据,客户端是没有对应的缓存,所以需要发送request请求来获取数据;
(2)服务端接收到请求后,获取服务端的数据及服务端缓存的允许后,返回200的成功状态码并且在响应头上附上对应资源以及缓存信息;
(3)当用户再次访问相同资源的时候,客户端会在浏览器的缓存目录中查找是否存在响应的缓存文件
(4)如果缓存中有,直接响应,如果没有找到对应的缓存文件,从服务器重新获取。
(5)如果有缓存文件,接下来对缓存文件是否过期进行判断,过期的判断标准是(Expires),
(6)如果没有过期,则直接从本地缓存中返回数据进行展示
(7)如果Expires过期,接下来需要判断缓存文件是否发生过变化
(8)判断的标准有两个,一个是ETag(Entity Tag),一个是Last-Modified
(9)判断结果是未发生变化,则服务端返回304,直接从缓存文件中获取数据
(10)如果判断是发生了变化,重新从服务端获取数据,并根据缓存协商(服务端所设置的是否需要进行缓存数据的设置)来进行数据缓存。
浏览器缓存相关指令
Nginx需要进行缓存相关设置,就需要用到如下的指令。
expires
expires:该指令用来控制页面缓存的作用。可以通过该指令控制HTTP应答中的“Expires"和”Cache-Control"
语法 | expires [modified] time expires epoch|max|off; |
默认值 | expires off; |
位置 | http、server、location |
time:可以整数也可以是负数,指定过期时间,如果是负数,Cache-Control则为no-cache,如果为整数或0,则Cache-Control的值为max-age=time;
epoch: 指定Expires的值为'1 January,1970,00:00:01 GMT'(1970-01-01 00:00:00),Cache-Control的值no-cache
max:指定Expires的值为'31 December2037 23:59:59GMT' (2037-12-31 23:59:59) ,Cache-Control的值为10年
off:默认不缓存。
add_header
add_header指令是用来添加指定的响应头和响应值。
语法 | add_header name value [always]; |
默认值 | — |
位置 | http、server、location... |
Cache-Control作为响应头信息,可以设置如下值:
指令 | 说明 |
must-revalidate | 可缓存但必须再向源服务器进行确认 |
no-cache | 缓存前必须确认其有效性 |
no-store | 不缓存请求或响应的任何内容 |
no-transform | 代理不可更改媒体类型 |
public | 可向任意方提供响应的缓存 |
private | 仅向特定用户返回响应 |
proxy-revalidate | 要求中间缓存服务器对缓存的响应有效性再进行确认 |
max-age=<秒> | 响应最大Age值 |
s-maxage=<秒> | 公共缓存服务器响应的最大Age值 |
测试
location ~ .*\.(html|js|css|png)$ {
expires 1000;
}
如上,我们设置浏览器对html、js、css、png类型的响应进行缓存,缓存时间为1000秒, 然后再次访问 http://118.190.152.59/jquery-1.10.1.js 返回的响应信息中就可以看到多了几项,如下:
补充一下,从请求上看下缓存的效果,第一次访问的时候状态码200,传输文件267K,当我们刷新页面后会发现 状态码为304并且传输栏里也变为了已缓存。
我们再试下 add_header相关的指令,如下:
location ~ .*\.(html|js|css|png)$ {
expires 1000;
add_header Cache-Control no-store;
}
如上,我们指定浏览器不缓存请求或响应的任何内容,清空浏览器缓存后,多次访问资源每次都会请求服务器,状态码200,传输都会显示资源的大小。