• HTTP 缓存及其工作方式


    受众是更新不频繁的静态资源
    为什么要使用HTTP缓存?
    减少服务器负载压力,每次请求完可能要渲染页面,用户体验不好
    缓存之后,第一次打开稍慢,后面进来很快

    缓存的内容?
    缓存的更多是一些静态资源文件。如js,图片等更新频率不大的静态资源
    不是缓存某一个响应,而是静态资源文件
    因此发现第一次进网页慢,后面进来就快了

    Expires

    响应头,HTTP1.0的属性,代表资源过期时间,由服务器返回提供,在与HTTP1.1的cache-control:max-age共存的情况下,优先级要低

    Cache-Contro

    请求/响应头,缓存控制字段
    no-store:所有内容都不缓存
    no-cache:缓存,但是浏览器使用缓存前,会请求服务求判断缓存资源是否是最新(只用不过期的缓存)
    max-age=x(单位秒):请求缓存后的X秒不再发起请求(缓存后的多少秒内不发起缓存,http1.1的属性,和1.0的expires类似,但是优先级要高)。
    s-maxage=x(单位秒):代理服务器请求资源缓存后的x秒不再发起请求,只对CDN缓存有效
    public:客户端和代理服务器(CDN)都可缓存
    private:只有客户端可以缓存Expires

    Cache-Control:max-age 和 Expires的区别

    Expires和max-age的区别:
    Expires和max-age都可以用来指定文档的过期时间,但是二者有一些细微差别bai

    1.Expires在HTTP/1.0中已经定义,Cache-Control:max-age在HTTP/1.1中才有定义,为了向下兼容,仅使用max-age不够;

    2.Expires指定一个绝对的过期时间(GMT格式),这么做会导致至少2个问题

    1. 客户端和服务器时间不同步导致Expires的配置出现问题
      2)很容易在配置后忘记具体的过期时间,导致过期来临出现浪涌现象;

    3.max-age 指定的是从文档被访问后的存活时间,这个时间是个相对值(比如:3600s),相对的是文档第一次被请求时服务器记录的Request_time(请求时间)

    4.Expires指定的时间可以是相对文件的最后访问时间(Atime)或者修改时间(MTime),而max-age相对对的是文档的请求时间(Atime)

    5.在Apache中,max-age是根据Expires的时间来计算出来的max-age = expires- request_time:(mod_expires.c)
    429 expires = base additional;
    430 apr_table_mergen(t, "Cache-Control",
    431 apr_psprintf(r->pool, "max-age=%" APR_TIME_T_FMT,
    432 apr_time_sec(expires - r->request_time)));
    注:如果是A,base=request_time,M的话base=finfo.mtime.
    expires - request_time得到max-age,如果Expires根据的是A(也就是AccessTime)设置的(A后面的值就是addtional),那么expires设置的值就等于addtional值,但是如果Expires根据的是Mtime,那么如果M后面的参数小于最后修改时间到当前时间的差(比方说2小时前修改了文件(19:00:00),现在设置M3600(现在是21:00:00)并且访问,max-age=expires-request_time = (finfo.mtime additional)- request_time),计算出的max-age就是负数(可以试验看到这个结果):
    max-age = (19:00:00 3600/3600) - 21:00:00 = -3600s
    这样,在Apache中,max-age就不仅仅是相对Atime的时间了,如果设置为M,相对的是Mtime。

    HTTP1.1 If-Modified-Since Last-Modified

    If-Modified-Since
    请求头,资源最新修改时间,由浏览器告诉服务器。(其实就是上次服务器给的Last-Modified)
    和last-modified是一对,它两会进行对比,共同决定资源要不要重新发送。

    Last-Modified
    响应头,资源最新修改时间,由服务器告诉浏览器
    和if-Modified-Since是一对,它两会进行对比,共同决定资源要不要重新发送。

    HTTP1.1 If-None-Match Etag

    If-None-Match
    请求头,缓存资源标识,由浏览器告诉有服务器(其实就是上次服务器给的Etag)
    和Etag是一对,它两会进行对比

    Etag
    响应头,资源标识,由服务器告诉浏览器的资源表示
    和if-None-Match是一对

    HTTP缓存工作方式

    场景一:让服务器与浏览器约定一个文件过期时间Expires
    服务器设置了Expires和f.js
    浏览器对比当前时间,判断是否大于Expires(是否超过了约定的过期时间)
    如果时间过期了,就再次发起请求加载最新资源

    如果约定时间之后资源依然没有修改呢?看场景二

    场景二:让服务器与浏览器约定文件过期时间的基础上,再加一个文件最新修改时间(last-modified)的对比
    last-Modified与if-Modified-Since。

    1. 如果当前时间没有超过过期时间expires,那么就使用本地缓存资源
    2. 如果超过了当前时间,但是浏览器的文件修改时间if-modified-since与服务器的last-modified时间没有差异,即不存在文件修改,那么依然使用本次缓存。注意是由服务器拿到请求中的if-modified-since和last-modified对比
    3. 在2的基础上,如果if-modified-since与last-modified有差异,说明文件有更改,那么就不再使用缓存而是加载最新资源

    具体过程如下图:
    请求头的Cache字段里面加上if-since-modified
    响应头的entity字段里面会有last-modified
    https://img2020.cnblogs.com/blog/1471668/202012/1471668-20201229220015149-1325137555.png)

    到了过期时间,再对比文件修改时间
    如果到期了,文件也修改了,那么返回新的
    (在请求头加上if-Modified-since,其实就是服务器返回的last-Modified。如果相等就返回304 not Modified,你还是访问本地缓存吧)

    问题: 极端情况,last-Modified精确到秒(GMT格式),可能在一秒以内改变了资源,收不到更新,看场景三
    让服务器与浏览器再过期时间expires+last-Modified的基础上,增加一个文件内容唯一对比标记--ETag与If-None-Match
    仅仅使用Expires不稳定(服务器指定的是一个绝对的过期时间,如果客户端和服务器时间不同步那么会出现问题,另外很容易在配置后忘记具体过期时间,导致过期来临出现对某个资源的请求峰值(专业一点叫浪涌现象),另外存在ATime和MTime),加入一个max-age来代替,再接入一个唯一标识ETag(具体是一个hash值,可详查)对比标记和if-None-Match

    f.js+Expires过期时间+max-age过期时间+last-Modified(文件最后修改时间)+Etag文件内容标识

    因此流程变为:

    1. expires+max-age(max-age优先级高,同时设置的话expires就没用了):判断过期时间,如果没过期不加载最新资源
    2. if-Modified-since + last-modified+: 如果过期了,再对比文件最后修改时间,如果有变化就加载最新资源,否则使用缓存
    3. if-None-Match + eTag:如果没过期,考虑到2过程的时间是GMT格式,精确到秒,存在一秒以内资源更新的极端情况,那么再对比文件唯一标识Etag(hash值),如果文件不唯一,那么加载最新资源

    请求头的cache字段有
    Cache-Control:max-age=60
    if-modified-since:GMT时间
    if-none-match:hash

    响应头的entity字段有
    ETag
    Last-Modified:GMT时间

    eTag优先级比if-None-Match高,毕竟是解决1秒内更新的问题

    以上方案都有缺陷,如果max-age,或者expires不过期,浏览器无法主动感知服务器的文件变化

    缓存改进方案

    上述:
    修改时间对比,唯一标识对比,建立在两者文件路径相同的情况下
    如果是f-hash1.js f-hash2.js
    如果是两个不同的文件(前提),那么根本不存在文件对比的时间
    因此只需要在项目发布的时候,添加md5就行了

    1.md5/hash缓存
    通过不缓存html,为静态文件添加MD5或者hash标识,解决浏览器无法跳过缓存过期时间主动感知文件变化的问题(说起来上述的方案是递进关系,时间没过期也不会进入Etag等流程?)

    2.CDN
    s-max-age
    什么是CDN?
    CDN是构建在网络之上的内容分发网络,依靠部署在各地的边缘服务器,通过中心平台的负载均衡、内容分发、调度等功能模块,是用户就近获取所需内容,降低网络拥塞,提高用户访问响应速度和命中率。

    优点是:

    1. 通过分流的形式,降低了源站的负载压力
    2. 解决了跨地区访问的方式,联通和电信

    CDN缓存的工作方式

    第一次请求,cdn和浏览器都进行请求
    后续请求

    1. 对比缓存时间
    2. 缓存没过期,返回304
    3. 缓存过期,向服务器拿到最新资源,返回给浏览器

    缓存本身针对于更新频率不高的静态文件

    浏览器操作对缓存的影响

    1. Expires/Cache-Control
    2. Last-Modified/Etag
      地址栏回车、页面连接跳转、新开窗口时 1和2都有效
      F5刷新 1失效,2有效
      ctrl+F5刷新(强制请求) 1和2都失效
  • 相关阅读:
    洛谷 P1991 无线通讯网/一本通OJ 1487【例 2】北极通讯网络
    [NOIP2016TG] 洛谷 P1850 换教室
    洛谷 P1169 [ZJOI2007]棋盘制作
    C#中数组、ArrayList和List三者的区别
    【转载】C#读写注册表
    UninstallTool(Windows软件卸载工具)--快捷、方便卸载电脑中的软件
    C#启动一个外部程序-CreateProcess
    C# 调用外部程序Process类
    学习C#,每天一话
    C#中字符串处理(随时更新)
  • 原文地址:https://www.cnblogs.com/ltfxy/p/16314572.html
Copyright © 2020-2023  润新知