前端知识框架 前端知识框架
首页
基础
框架
插件
Node
地图
更多
前端须知
  • 分类
  • 标签
  • 归档

BestIdea

首页
基础
框架
插件
Node
地图
更多
前端须知
  • 分类
  • 标签
  • 归档
  • 国产机环境浏览器兼容问题收集(持续收集)
  • canvas电子画板,适用于H5版本,组件产出为blob类型的文件流
  • Css3 filter(滤镜) 属性
  • css选择器
  • http缓存
    • 缓存的重要性
    • 浏览器缓存
    • 强缓存
      • Expires
      • Cache-Control
      • 强缓存 Expires 和 Cache-Control 总结
    • 协商缓存
      • Last-Modified 和 If-Modified-Since
      • ETag 和 If-None-Match
      • Last-Modified(If-Modified-Since) 和 ETag(If-None-Match) 的区别
    • 强缓存和协商缓存的区别
    • 浏览器缓存判断的流程
    • Nginx http 缓存设置
      • expires
      • if-modified-since
    • Nginx 的缓存服务
      • nginx 代理层缓存
    • 附录
  • less语法
  • New date()浏览器时间兼容性
  • rem自动适应性布局方案
  • 浏览器缓存机制
  • 屏幕适配
  • 前端基础方法汇总
  • 图片转码下载方式(解决浏览器下载图片时直接打开图片问题)
  • CSS命名规范
  • 大屏定位解决方案
  • TypeScript入门
  • 解决有些浏览器rem不以html的font-size为基准问题
  • 解决Vue项目页面缩放问题
  • H5扫一扫功能
  • crypto前端加密
  • 基础
Btzh
2022-03-26
目录

http缓存

# 缓存的重要性

  • 一个优秀的缓存策略,可以缩短网页请求资源的距离,减少延迟,缓存文件可以重复利用所以还可以减少带宽,降低网路负荷

# 浏览器缓存

浏览器启用缓存的优点:减少页面加载时间,减少服务器负载

浏览器是否使用缓存,缓存多久,是由服务器控制的

  • 即服务器响应的 响应头 中,某些字段指明了缓存的关键信息

浏览器缓存的分类

  • 强缓存 和 协商缓存

# 强缓存

  • Expires, Cache-Control

  • 返回的状态码 200

  • network => size => 会显示 from-cache (from-disk-cache),(from-memory-cache)

  • 强缓存的实现:通过( Expires ) 或者 ( Cache-Control ) 这两个 ( http response header ) 来实现的,他们用都是用来表示资源在客服端存在的 有效期

# Expires

  • http1.0 提出,响应头中的一个字段,绝对时间,用 GMT 格式的字符串表示

  • 注意:expires 是和浏览器本地的时间做对比,是一个绝对时间点,是一个 GMT 时间

  • Expires 是优化中最理想的情况,因为它根本不会产生请求,所以后端也就无需考虑查询快慢

  • Expires 的原理

# Expires 的原理

  1. 浏览器第一次向服务器请求资源,浏览器在请求资源的同时,在 responder 响应头中加上 Expires 字段
  2. 浏览器在接收到这个资源后,将这个资源和所有 response header 一起缓存起来 - 所以,缓存命中的请求返回的 header 并不是来自服务器,而是来自之前缓存的 header
  3. 浏览器再次请求这个资源时,先从缓存中寻找,找到这个资源后,拿出 Expires 跟当前的请求时间做比较 - 如果当前请求时间,在 Expires 指定的时间之前,就能命中强缓存,否则不能 - 注意:Expires 是和浏览器本地时间作对比
  4. 如果未命中缓存,则浏览器直接从服务器获取资源,并更新 response header 中的 Expires

expires 是较老的强缓存管理 header,是服务器返回的一个绝对时间,在服务器时间与客服端时间相差较大时,Expires 缓存管理容易出问题(比如:随便修改客户端时间,就能影响命中结果),所以在 http1.1 中,提出了新的 header => Cache-Control,一个相对时间,以秒为单位,用数值表示

# Cache-Control

  • http1.1 提出,响应头中的一个字段,相对时间,以秒为单位,用数值表示

  • 注意:Cache-Control 也是和浏览器本地时间做对比,以秒为单位的时间段

  • Cache-Control 可以指定:public 和 private

    • private:,Cache-Control 的默认取值,表示该资源仅仅属于发出请求的最终用户,这将禁止中间服务器(如代理服务器)缓存此类资源,对于包含用户个人信息的文件,可以设置private
    • public:允许所有服务器缓存该资源
    • must-revalidate: 只有当资源被视为陈旧时才需要重新验证。
    • max-age: 123123 // 一个时间段,单位是 s。
    • no-cache:并不意味着不缓存。实际上,在每次请求中使用任何缓存响应之前,它都意味着“使用服务器重新验证”,相当于 max-age=0,must-revalidate,走协商缓存。
    • no-store:实际上是完全不缓存指令,并且旨在防止以任何形式的缓存存储该表示。

    no-cache 和 no-store 以及 max-age=0 的区别 :

    no-cache

    Cache-Control 为 no-cache。表示必须重新去获取请求。由服务端来判断是否使用缓存,即可以在本地缓存,可以在代理服务器缓存,但是这个缓存要服务器验证才可以使用

    no-store

    是真正的不进行缓存。即彻底得禁用缓冲,本地和代理服务器都不缓冲,每次都从服务器获取

    max-age=0

    max-age>0 时 直接从游览器缓存中提取 max-age<=0 时 向 server 发送 http 请求确认 ,该资源是否有修改 有的话 返回 200 ,无的话 返回 304.(即max-age=0 表示不管 response 怎么设置,在重新获取资源之前,先检验 ETag/Last-Modified)

  • Cache-control: no-cache,private,max-age=123123

  • Cache-Control 的原理

# Cache-Control 的原理

  1. 浏览器第一次向服务器请求资源,服务器在返回资源的同时,在 responder 的 header 中加上 Cache-Control 字段
  2. 浏览器在接收到这个资源后,会将这个资源和所有的 response header 一起缓存起来,所以,缓存命中的请求返回的 header 并不是来自服务器,而是来自之前缓存的 header
  3. 浏览器再次请求这个资源时,先从缓存中寻找,找到这个资源后,拿出 Cache-Control 和当前请求的时间做比较。如果当前请求时间,在 Cache-Control 表示的时间段内,就能命中强缓存,否则不能。
  4. 如果缓存未命中,则浏览器直接从服务器获取资源,并更新 response header 中的 Cache-Control

# 强缓存 Expires 和 Cache-Control 总结

  • Expires 和 Cache-Control 可以开启一个,也可以同时开启

  • 当 Expires 和 Cache-Control 同时开启时,Cache-Control 优先级高于 Expires

  • Cache-Control 可以指定 private 和 public,表示是否允许中间服务器缓存该资源

  • expires 是一个用 GMT 时间表示的时间点,Cach-Control 是用秒表示的时间段,都是和浏览器本地时间做对比

# 协商缓存

  • Last-Modified(If-Modified-Since),ETag(If-None-Match)

  • 返回状态码 304

  • 协商缓存的原理:当浏览器对某个资源的请求没有命中强缓存,就会发一个请求到服务器,验证协商缓存是否命中,如果协商缓存命中,请求响应返回的 http 状态为 304,并且会显示一个 Not Modified 的字符串表示资源未被修改

  • modified: 是修改的意思

# Last-Modified 和 If-Modified-Since

  • Last-Modified 和 If-Modified-Since 都是根据 服务器时间 返回的 header
  • 响应头:Last-Modified
  • 请求头:If-Modified-Since
  • 原理

# Last-Modified If-None-Match

  1. 浏览器第一次跟服务器请求一个资源,服务器在返回这个资源的同时,在 response 的 header 加上 Last-Modified 的 header - 这个 header 表示这个资源在服务器上的最后修改时间

  2. 浏览器再次跟服务器请求这个资源时,在 request 的 header 上加上 If-Modified-Since 的 header - 这个 header 的值就是上一次请求时返回的 Last-Modified 的值

  3. 服务器再次收到资源请求时,根据浏览器传过来 If-Modified-Since 和资源在服务器上的最后修改时间判断资源是否有变化 - 如果没有变化则返回 304 Not Modified,但是不会返回资源内容; - 如果有变化,就正常返回资源内容。

    • 当服务器返回 304 Not Modified 的响应时,response header 中不会再添加 Last-Modified 的 header,因为既然资源没有变化,那么 Last-Modified 也就不会改变
  4. 浏览器收到 304 的响应后,就会从缓存中加载资源

  5. 如果协商缓存没有命中,浏览器直接从服务器加载资源时,Last-Modified Header 在重新加载的时候会被更新。下次请求时,If-Modified-Since 会启用上次返回的 Last-Modified 值。

# ETag 和 If-None-Match

  • 只要资源有变化 ETag 这个字符串就不一样,和修改时间没有关系,所以很好的补充了 Last-Modified 的问题
  • 响应头:ETag
  • 请求头:If-None-Match
  • 原理

# ETag 和 If-None-Match

  1. 浏览器第一次跟服务器请求一个资源,服务器在返回这个资源的同时,在 response 的 header 加上 ETag 的 header - 这个 header 是服务器根据当前请求的资源生成的一个唯一标识,这个唯一标识是一个字符串 - 只要资源有变化这个串就不同,跟最后修改时间没有关系,所以能很好的补充 Last-Modified 的问题
  2. 浏览器再次跟服务器请求这个资源时,在 request 的 header 上加上 If-None-Match 的 header, - 这个 header 的值就是上一次请求时返回的 ETag 的值
  3. 服务器再次收到资源请求时,根据浏览器传过来 If-None-Match 然后再根据资源生成一个新的 ETag - 如果没有变化则返回 304 Not Modified,但是不会返回资源内容 - 如果有变化,就正常返回资源内容。
    • 与 Last-Modified 不一样的是,当服务器返回 304 Not Modified 的响应时。 由于 ETag 重新生成过,response header 中还会把这个 ETag 返回,即使这个 ETag 跟之前的没有变
  4. 浏览器收到 304 的响应后,就会从缓存中加载资源。

# Last-Modified(If-Modified-Since) 和 ETag(If-None-Match) 的区别

  • ETag 的优势

    • ETag 和 Last-Modified 非常相似,都是用来判断一个参数,从而决定是否启用缓存。
    • 但是ETag相对于Last-Modified也有其优势,可以更加准确的判断文件内容是否被修改,从而在实际操作中实用程度也更高。

    状态码为 200 from cache 和 304 Not modified 的区别

    1、请求状态码为 200 from cache: 表示该资源已经被缓存过,并且在有效期内,所以不再向浏览器发出请求,直接使用本地缓存。

    4

    2、状态码为 304 Not modified: 表示浏览器虽然发现了本地有该资源的缓存,但是不确定是否是最新的,于是想服务器询问,若服务器认为浏览器的缓存版本还可用(即还未更新),那么便会返回 304,继续使用本地的缓存。

    5

# 强缓存和协商缓存的区别

  • 协商缓存跟强缓存不一样,强缓存不发请求到服务器,所以有时候资源更新了浏览器还不知道,但是协商缓存会发请求到服务器,所以资源是否更新,服务器肯定知道。

  • 大部分 web 服务器都默认开启协商缓存,而且是同时启用 Last-Modified,If-Modified-Since 和 ETag、If-None-Match

  • Last-Modified,If-Modified-Since 和 ETag、If-None-Match 一般都是同时启用,这是为了处理 Last-Modified 不可靠的情况

  • 分布式系统里多台机器间文件的 Last-Modified 必须保持一致,以免负载均衡到不同机器导致比对失败

  • 分布式系统尽量关闭掉 ETag(每台机器生成的 ETag 都会不一样)

# 浏览器缓存判断的流程

  1. 第一次正常请求后,缓存了资源和所有 header 的前提下

  2. 在资源缓存后,在缓存过期失效之前,如果再次请求该资源,默认先检查强缓存

    • 强缓存命中,则直接读取
    • 未命中强缓存,则发送请求到服务器,再检查是否命中协商缓存
  3. 未命中强缓存,再发请求到服务器检查是否命中协商缓存

    • 协商缓存命中,则告诉浏览器还是可以从缓存读取
    • 未命中协商缓存,才从服务器返回最新的资源

2

# Nginx http 缓存设置

Nginx 提供了 expires、etag、if-modified-since 指令来实现浏览器缓存控制。(http 模块中可以通过 add_header 来设置 cache-control)

location / {
   ...
   add_header Cache-Control max-age=3600;
   ...
}
1
2
3
4
5

# expires

如果我们使用 Nginx 作为静态资源服务器,那么可以使用 expires 进行缓存控制。

location /img {
   alias /export/img/;
   expires 1d;
}
1
2
3
4

当我们访问静态资源时,如,将得到类似如下的响应头。

5

对于静态资源会自动添加ETag,可以通过添加etag off指令禁止生成ETag。如果是静态文件,那么Last-Modified值为文件的最后修改时间。Expires是根据当前服务器系统时间算出来的。如上 Nginx 配置的计算逻辑(实际计算逻辑比这个多,具体参考官方文档)。

if (expires == NGX_HTTP_EXPIRES_ACCESS||r->headers_out.last_modified_ time == -1) {
  max_age = expires_time;
  expires_time += now;
}
1
2
3
4

# if-modified-since

此指令用于指定 Nginx 如何拿服务端的Last-Modified和浏览器端的if-modified-since时间进行比较,默认if_modified_since exact表示精确匹配,也可以使用if_modified_since_before表示只要文件的最后修改时间早于或等于浏览器端的if-modified-since时间,就返回 304。

# Nginx 的缓存服务

使用 Nginx 作为反向代理时,请求会先进入 Nginx,然后 Nginx 将请求转发给后端应用,如下图所示。

6

通常 nginx 反向代理配置

upstream backend_tomcat {
  server 192.168.61.1:9080 max_fails=10 fail_timeout=10s weight=5;
}

location / {
  proxy_pass http://backend_tomcat/cache$is_args$args;
}
1
2
3
4
5
6
7

接下来,我们可以通过如http://192.168.61.129/cache?millis=1471349916709访问 Nginx,Nginx 会将请求转发给后端应用。也就是说 Nginx 只是做了相关的转发(负载均衡),并没有对请求和响应做什么处理。

假设对后端返回的过期时间需要调整,可以添加 Expires 指令到 location。

location / {
  proxy_pass http://backend_tomcat/cache$is_args$args;
  expires 5s;
}
1
2
3
4

然后再请求相关的 URL,将得到如下响应。

6

过期时间相关的响应头被Expires指令更改了,但是last-modified是没有变的。

即使我们更改了缓存过期头,但 Nginx 自己没有对这些内容做代理层缓存,每次请求还是要到后端验证的,假设在过期时间内,这些验证在 Nginx 这一层验证就可以了,不需要到后端验证,这样可以减少后端很大的压力。即整体流程如下。

1.浏览器发起请求,首先到 Nginx,Nginx 根据 URL 在 Nginx 本地查找是否有代理层本地缓存。

2.Nginx 没有找到本地缓存,则访问后端获取最新的文档,并放入到 Nginx 本地缓存中,返回 200 状态码和最新的文档给浏览器。

3.Nginx 找到本地缓存,首先验证文档是否过期(Cache-Control:max-age=5),如果过期,则访问后端获取最新的文档,并放入 Nginx 本地缓存中,返回 200 状态码和最新的文档给浏览器;如果文档没有过期,即 if-modified-since 与缓存文档的 last-modified 匹配,则返回 304 状态码给浏览器。

7

内容不需要访问后端,即不需要后端动态计算/渲染等,直接 Nginx 代理层就把内容返回了,速度更快,内容越接近于用户速度越快。

7

即用户首先访问到全国各地的 CDN 节点,如果 CDN 没命中,则会回源到中央 Nginx 集群,该集群做二级缓存,如果没有命中缓存(该集群的缓存不是必须的,要根据实际命中情况等决定),则最后回源到后端应用集群。

# nginx 代理层缓存

proxy_cache_path和proxy_cache等

http {
    ...

    proxy_cache_path /path/to/cache
    levels=1:2
    keys_zone=nginx_cache:1024m
    max_size=10g
    inactive=7d
    use_temp_path=off; # 最好写在同一行

    server {
        ...

        proxy_cache_key $uri;
        proxy_cache_methods GET POST;
        proxy_cache nginx_cache;
        proxy_cache_valid  200 206 304 301 302 7d;

        set $nocache 0;
        # 这里可以写相关的匹配规则,来对不同的请求进行缓存或不缓存

        proxy_no_cache     $nocache;
        proxy_cache_bypass $nocache;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

参数说明:

  • proxy_cache_path:缓存存放路径;
  • levels:设置缓存文件目录层次;如果所有的缓存放入一个文件夹,则影响效率。这里设置的是 levels=1:2 ,表示两级目录;
  • keys_zone:在共享内存中设置一块存储区域来存放缓存的 key 和 metadata,这样 nginx 可以快速判断一个 request 是否命中或者未命中缓存,1m 可以存储 8000 个 key,10m 可以存储 80000 个 key;
  • max_size:最大的缓存空间,如果不指定,会使用掉所有的硬盘空间,当达到配额后,会删除最少使用的 cache 文件;
  • inactive:删除指定时间内未被访问的缓存文件;
  • use_temp_path:如果为 off,则 nginx 会将缓存文件直接写入指定的 cache 文件中,而不是使用 temp_path 存储,建议为 off,避免文件在不同文件系统中不必要的拷贝;
  • proxy_cache:启用 proxy cache,指定声明好的缓存区域 keys_zone;
  • proxy_cache_valid 200 206 304 301 302 7d:为对 http 状态为 200 206 304 301 302 等的缓存结果缓存 7 天;
  • proxy_cache_key $uri:定义缓存唯一 key,通过唯一 key 来进行 hash 存取;
  • proxy_no_cache 和 proxy_cache_bypass :当为 0 时表示缓存,不为 0 时表示不缓存。

# 附录

浏览器缓存

上次更新: 2022/05/05, 17:47:41
css选择器
less语法

← css选择器 less语法→

最近更新
01
webpack打包替换类名命名空间
05-01
02
Vite常用配置
02-26
03
crypto前端加密
01-18
更多文章>
Theme by Vdoing | Copyright © 2022-2024
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式