nginx 强缓存和协议缓存

https://www.lcgod.com/articles/97

HTTP状态码

200 (form memory cache) 不请求网络资源,从内存中读取资源,一般脚本、字体、图片会存在内存当中

200 (form disk cache) 不请求网络资源,从磁盘中读取资源,一般非脚本会存在内存当中,如css等

200 (1kb) 从服务器下载最新资源. (1kb即资源的大小)

304 (1kb) 请求服务端发现资源没有更新,使用本地资源. (1kb即报文的大小)

以上是chrome在请求资源是最常见的几种http状态码

前两种200状态码是不需要浏览器请求服务器的, 直接从本地读取资源, 所以速度是最快的, 而304状态码也是缓存, 只不过需要浏览器先请求服务器, 这种是协商缓存

那么浏览器究竟在什么情景下会返回以上几种不同的状态码呢?

答案很简单, 在浏览器第一次访问某个URL时, 服务端会直接返回第三种200状态码, 返回内容是被请求的最新资源, 与此同时服务端可以在返回内容时主动设置Response Headers里的last-modified属性标记此资源在服务端最后被修改的时间, 还可以设置cache-control属性和etag属性以及expire属性, 浏览器就会根据返回的几个属性, 自行判断下次该如何请求资源, 那么下文将依次讲解这些属性的作用, 以及在什么情况会返回剩余的三种状态码.

last-modified

last-modified格式类似这样:

last-modified : Fri , 12 May 2006 18:53:33 GMT

客户端第二次请求此URL时,根据HTTP协议的规定,浏览器会向服务器发送if-modified-since报头,询问该时间之后文件是否有被修改过:

if-modified-since : Fri , 12 May 2006 18:53:33 GMT

如果服务器端的资源没有变化,则返回 304(Not Changed)状态码,内容为空,这样就节省了传输数据量。当服务器端代码发生改变或者重启服务器时,则重新发出资源,返回和第一次请求时类似。从而保证不向客户端重复发出资源,也保证当服务器有变化时,客户端能够得到最新的资源。

Nginx默认开启last modified特性, 也可以在nginx.conf中添加以下配置, 主动控制:

if_modified_since off|on;

etag

HTTP协议规格说明定义etag为“被请求变量的实体值”。另一种说法是,etag是一个可以与Web资源关联的记号(token)。典型的Web资源可以一个HTML文档,但也可能是JSON或XML文档。

服务器单独负责判断记号是什么及其含义,并在HTTP响应头中将其传送到客户端,以下是服务器端返回的格式:

etag:“50b1c1d4f775c61:df3”

客户端的查询更新格式是这样的:

if-none-match : W / “50b1c1d4f775c61:df3”

如果etag的值没有发生改变,则返回 304(Not Changed)状态码,这也和last-modified一样。etag在断点下载时会非常有用。

Nginx1.7.3及以上的版本默认开启Etag特性, 但是和Last-Modified一样, 可以主动配置:

etag off|on;

cache-control

cache-control 是最重要的规则。这个字段用于指定所有缓存机制在整个请求/响应链中必须服从的指令。这些指令指定用于阻止缓存对请求或响应造成不利干扰的行为。这些指令通常覆盖默认缓存算法。缓存指令是单向的,即请求中存在一个指令并不意味着响应中将存在同一个指令。

简单来说, 当同时存在last-modified以及etag还有cache-control这个3个属性时, cache-control的优先级是最高的

cache-control有以下几个值:

public 所有内容都将被缓存

private 内容只缓存到私有缓存中

no-cache 所有内容都不会被缓存

no-store 所有内容都不会被缓存到缓存或 Internet 临时文件中

must-revalidation/proxy-revalidation 如果缓存的内容失效,请求必须发送到服务器/代理以进行重新验证

max-age=xxx (xxx is numeric) 缓存的内容将在 xxx 秒后失效, 如果和Last-Modified一起使用时, 优先级更高

浏览器对以上几种值的不同表现:

打开新窗口

public 会从缓存中读取资源, 也就是返回前两种200状态码

private, no-cache, no-store 都会重新访问服务器。

如果指定了max-age值,那么在此值内的时间里就不会重新访问服务器,例如:

cache-control: max-age=5(表示当访问此网页后的5秒内再次访问不会去服务器)

在原窗口按Enter键

public 会从缓存中读取资源, 也就是返回前两种200状态码

private或must-revalidate 则只有第一次访问时会访问服务器,以后就不再访问。

no-cache, no-store 每次都会访问。

如果指定了max-age值,那么在此值内的时间里就不会重新访问服务器

点击刷新按钮

无论将cache-control设置为什么值,浏览器都会重新访问服务器

点击后退按钮

public、private、must-revalidate、max-age 都不会重新访问

no-cache 则每次都重复访问

cache-control是关于浏览器缓存的最重要的设置,因为它覆盖其他设置,比如 expires 和 last-modified。另外,由于浏览器的行为基本相同,这个属性是处理跨浏览器缓存问题的最有效的方法。

Nginx设置cache-control(例如设置max-age为30秒):

add_header Cache-Control "max-age=30";

expires

Expires 头部字段提供一个日期和时间,响应在该日期和时间后被认为失效。失效的缓存条目通常不会被缓存(无论是代理缓存还是用户代理缓存)返回,除非首先通过原始服务器(或者拥有该实体的最新副本的中介缓存)验证。(注意:cache-control max-age 和 s-maxage 将覆盖 Expires 头部。)

Expires 属性接收以下格式的值:

Expires: Sun, 08 Nov 2009 03:37:26 GMT

如果查看内容时的日期在给定的日期之前,则认为该内容没有失效并从缓存中提取出来。反之,则认为该内容失效,缓存将采取一些措施。

以上几种属性的优先级

协商缓存: 第一次请求后响应参数Etag <---->第二次请求参数 If-None-Match(比较值是否相同)

  第一次请求后响应参数Last-modified<----->请求参数If-Modify-since(比较时间是否相同)

  优先级:Pragma>Cache-Control>Expires>Etag>Last-modify (下面有各个缓存的解释)

原文链接:https://blog.csdn.net/en_kai/article/details/122259178

服务器收到请求则会先判断资源的 last-modified,再判断 etag ,必须都没有过期,才能返回 304(Not Changed)状态码。

请注意,不同的浏览器和服务器可能会有不同的处理方式,但上述优先级通常适用于大多数情况。在实际部署时,建议查阅具体的服务器和客户端文档,以确保正确的缓存行为。

可能出现的问题

前面只讲了几种属性同时被设置后, 浏览器和服务器判断的优先级, 还有一种情况(也是最常见的情况)也是需要我们去考虑的

那就是服务端只设置了last-modified 以及 etag, 并没有设置cache-control和expires属性

为什么说这种情况是最常见的? 仔细想想还真是那么回事, 因为nginx默认开启了last-modified和etag属性

如果一只后端汪正常地配置了生产环境, 并没有在缓存方面做一些配置, 那默认就是这种情况

这种情况下浏览器就不得不自行判断它应该将资源缓存多久。有些浏览器会将其缓存一天以上。

Google caching best practices guide 里提到: 浏览器会根据 last-modified 自行推算缓存时长。

Firefox 的推算方法是:

缓存时长 = (Date - last-modified) / 10

Chrome / Safari / IE 并没有公布他们的公式或算法。

此类文件的缓存时长通常取决于以下因素:

  • 浏览器开辟的缓存空间大小

  • 用户浏览过的站点数量和大小

  • 用户是否关闭了浏览器

也就是说当服务端只配置了last-modified 以及 etag, 没有配置cache-control和expires的时候, 除非用户手动点击刷新按钮, 否则浏览器每次都会从本地缓存中加载, 而且这个本地缓存的缓存时间也是未知的

这就导致了一个问题, 比如说你没有做任何缓存的配置, 却发现每次更新了网站的PHP, HTML, JS, CSS文件, 非得让用户手动点击刷新按钮才能显示更新内容, 这可不是我们想要的!(别问我怎么知道的)

所以,你如果不想关闭 last-modified,etag, 还不想浏览器从本地加载缓存资源,就应该显示地指定cache-control或expires

下面是我网站的nginx的缓存配置(仅供参考):

 

强缓存:浏览器不与服务端协商直接取浏览器缓存

协商缓存:浏览器会先向服务器确认资源的有效性后才决定是从缓存中取资源还是重新获取资源

无缓存:浏览器直接向服务器重新获取资源

 

 

  1. 安装 gzip 模块: 确保你的 Nginx 安装了 gzip 模块。在编译 Nginx 时,通常需要添加 --with-http_gzip_static_module--with-http_gzip_dynamic_module 选项来启用 gzip 压缩。

  2. 配置 gzip 压缩: 在 Nginx 的配置文件(通常是 nginx.conf)中,你可以找到 httpserverlocation 块,并添加以下配置来启用 gzip 压缩:

http {
    # 启用 gzip 压缩
    gzip on;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
    # 设置压缩级别,1-9,9 为最高压缩比,但 CPU 使用率也最高
    gzip_comp_level 6;
    # 设置压缩文件的最小大小,小于这个大小的文件不会被压缩
    gzip_min_length 256;
    # 设置压缩文件的缓冲区大小
    gzip_buffers 16 8k;
    # 设置压缩文件的输出缓存大小
    gzip_http_version 1.1;
    # 设置是否使用压缩文件作为缓存
    gzip_vary on;
}

  这些设置会告诉 Nginx 对指定的 MIME 类型进行压缩,并且对请求的 HTTP 版本进行适应。gzip_vary on 允许 Nginx 根据客户端的 Accept-Encoding 头部信息来决定是否发送压缩内容。

 4.重启 Nginx: 更改配置文件后,需要重启 Nginx 服务以使更改生效。在大多数 Linux 系统中,你可以使用以下命令重启 Nginx:

  1. sudo systemctl restart nginx 或者 sudo service nginx restart
     
    请注意,启用 gzip 压缩可能会增加服务器的 CPU 使用率,因为它需要在发送内容之前进行压缩。然而,对于大多数现代服务器来说,这种开销是可以接受的,因为它可以显著提高用户体验。在生产环境中,建议监控服务器的性能,以确保压缩不会对服务器造成过大负担。

 

posted @ 2024-01-19 13:54  星云惊蛰  阅读(76)  评论(0)    收藏  举报