您的位置:首页 > 理论基础 > 计算机网络

Http缓存

2019-05-19 23:40 1171 查看

通过网络提取内容速度缓慢并开销巨大。较大的响应需要在客户端和服务器之间进行多次往返通信,延迟浏览器获得和处理内容的时间,增加访问者的流量费用。因此缓存并重复利用之前获取的资源的能力是性能优化的一个关键。

http请求报文分为两部分:报文头部和数据主体。
报文头部包含(cookie, 缓存信息等);数据主体即http想要传输的数据内容。

http缓存相关的报文头有:

字段名 字段所属
Pragma 通用头
Expires 响应头
Cache-Control 通用头
Last-modified 响应头
if-modified-since 请求头
ETag 响应头
If-None-Match 请求头

一 强制缓存(Expires, Cache-control)

  • Expires(Http1.0中的,现已被cache-control取代)
    服务器告诉浏览器缓存过期时间,下一次请求时,如果浏览器当前时间没有达到过期时间,直接使用缓存数据。

    存在的问题:

      浏览器时间和服务器时间不同步,如果浏览器设置了一个很后的时间,过期时间一直没有用
    1. 缓存过期后,不管文件有没有变化,服务器都会再次读取文件返回给浏览器
  • Cache-control(Http 1.1)
    针对浏览器和服务器时间不同步,加入新的缓存方案;服务器不是直接告诉浏览器过期时间,而是使用相对时间,控制浏览器和其他中间缓存如何缓存各个响应以及缓存多久。

    no-cache/no-store:

    no-cache(强制确认缓存):每次请求时,缓存会将此请求发送到服务器,服务器验证请求中所描述的缓存是否过期,未过期(返回304),缓存使用本地缓存副本。
    no-store: 缓存中不得存储任何关于客户端请求和服务端响应的内容。每次由客户端发起的请求都会下载完整的响应内容

    public/private

    “public”: 指令表示该响应可以被任何中间人(比如中间代理、CDN等)缓存。若指定了"public",则一些通常不被中间人缓存的页面(因为默认是private)(比如 带有HTTP验证信息(帐号密码)的页面 或 某些特定状态码的页面),将会被其缓存。
    “private”: 表示该响应是专用于某单个用户的,中间人不能缓存此响应,该响应只能应用于浏览器私有缓存中。

    max-age

    表示资源能够被缓存(保持新鲜)的最大时间。相对Expires而言,max-age是距离请求发起的时间的秒数

    must-revalidate

    缓存必须在使用之前验证旧资源的状态,并且不可使用过期资源。

理想情况下,目标应该在客户端上缓存尽可能多的响应,缓存尽可能长的时间,并为每个响应提供验证令牌(ETag),以实现高效的重新验证。

二 协商/对比缓存 (Last-modified, ETag)

强制缓存的弊端很明显,即每次都根据时间判断缓存是否过期,但是到达过期时间后,若文件没有改动,再次去获取文件有点浪费服务器资源。当缓存的文档过期之后,需要进行缓存验证或者重新获取资源。只有在服务器返回强校验器或者弱校验器的时候才会验证。

协商缓存有两组报文结合使用:

  1. last-modified/If-modified-since(弱校验器)

    弱的原因是因为只能精确到1s。若响应头中含有last-modified,客户端可以在后续的请求中带上If-Modified-Since

  2. ETag/If-None-Match(强校验器)

    如果请求资源的响应头中含有ETag,客户端可以在后续的请求中带上If-None-Match来验证缓存

当向服务端发起缓存校验的请求时,服务端会返回 200 ok表示返回正常的结果或者 304 Not Modified(不返回body)表示浏览器可以使用本地缓存文件。304的响应头也可以同时更新缓存文档的过期时间

三 Pragma

http1.0时,给客户端设定缓存的方式通过两个字段–Prama和Expires,虽然这两个字段早就可以抛弃,但是为了http协议的向下兼容,还是有很多网站会带上这两个字段。

Pragma 是HTTP/1.0标准中定义的一个header属性,请求中包含Pragma的效果跟在头信息中定义Cache-Control: no-cache相同,但是HTTP的响应头不支持这个属性,所以它不能拿来完全替代HTTP/1.1中定义的Cache-control头。

优先级:Pragma->Cache-Control->Expires. 以下设置结果是页面重新请求了一次。

Cache-Control: public, max-age=86400
Pragma: no-cache

Http/1.0 用Pragma禁用缓存,用Expires启动和定义缓存,Expires的值对应一个GMT(格林尼治时间),比如Mon, 22 Jul 2002 11:12:01 GMT来告诉浏览器资源缓存过期时间,如果还没过该时间点则不发请求。(比较Expires值和头里的Date属性值来判断,Date是指报文创建时间)

四 缓存头部对比

用户刷新

  • 在URI输入栏中输入然后回车/通过书签访问–遵循浏览器缓存策略
  • F5/点击工具栏中的刷新按钮/右键菜单重新加载(mac command+R)–跟URI输入栏中输入然后回车没什么不同
  • Ctl+F5(mac command+shift+R)–强制从server重新获取资源

缓存策略

对于所有可缓存资源,指定一个Expires或Cache-Control max-age以及一个Last-Modified或ETag至关重要。同时使用前者和后者可以很好的相互适应。
在用户的不同刷新页面行为中,二者的结合也能很好的利用HTTP缓存控制特性,无论是在地址栏输入URI然后输入回车进行访问,还是点击刷新按钮,浏览器都能充分利用缓存内容,避免进行不必要的请求与数据传输。

如何才能鱼和熊掌兼得:客户端缓存和快速更新?组合使用 ETag、Cache-Control 和唯一网址来实现:较长的过期时间、控制可以缓存响应的位置以及随需更新。

  • 在资源“过期”之前,将一直使用本地缓存的响应。
  • 您可以通过在网址中嵌入文件内容指纹,强制客户端更新到新版本的响应。
  • 为获得最佳性能,每个应用都需要定义自己的缓存层次结构。

定义缓存层次结构例子:

不存在什么最佳缓存策略,制定缓存策略时,可以使用以下方法

  • 使用一致的网址-如果您在不同的网址上提供相同的内容,将会多次提取和存储这些内容;
  • 确保服务器提供验证令牌 (ETag);
  • 确定中间缓存可以缓存哪些资源:对所有用户的响应完全相同的资源非常适合由 CDN 以及其他中间缓存进行缓存;
  • 3ff7 为每个资源确定最佳缓存周期:不同的资源可能有不同的更新要求;
  • 确定最适合您的网站的缓存层次结构:可以通过为 HTML 文档组合使用包含内容指纹的资源网址和短时间或 no-cache 周期,来控制客户端获取更新的速度。
  • 最大限度减少搅动:某些资源的更新比其他资源频繁。 如果资源的特定部分(例如 JavaScript 函数或 CSS 样式集)会经常更新,可以考虑将其代码作为单独的文件提供。 这样一来,每次提取更新时,其余内容(例如变化不是很频繁的内容库代码)可以从缓存提取,从而最大限度减少下载的内容大小

参考:
https://imweb.io/topic/5795dcb6fb312541492eda8c
https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching?hl=zh-cn
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Caching_FAQ

扩展阅读:
http2与http1.x的不同
https://developers.google.cn/web/fundamentals/performance/http2/

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: