HTTP缓存笔记整理

前言

缓存是性能优化的总要手段,合理使用缓存,不仅能够节省服务器资源,更能为用户提供好的浏览体验

Pragma

Pragma: no-cache 是 HTTP 1.0 的产物,它要求缓存服务器在返回缓存的版本之前将请求提交到源头服务器进行验证。在效果上和HTTP 1.1 中的Cache-Control: no-cache一样。

缓存服务器是代理服务器的一种,用于缓存静态资源。通常资源在保存到数据库中时,我们会同时保存资源的创建时间和更新时间,然后设置响应头的Last-Modified字段为资源的最新更新时间,当下一次请求到达时,服务端会先读取请求头中的If-Modified-Since的值,判断资源是否更新过,如果没有更新就返回304,数据返回空;如果更新过,状态码返回200,并返回新的数据

Expires

Expires: <GMT> 也是HTTP 1.0 的产物,用来告诉浏览器资源缓存过期时间,如果还没过该时间点则不发请求。由于服务器时间和客户端的时间可能有偏差,所以这种方式设置的缓存时间并不可靠

Cache-Control

Cache-Control 是 HTTP 1.1 中的字段,取值如下:

public: 表示允许缓存HTTP请求经过的任何地方都可以缓存

private: 表示只允许发起请求的浏览器进行缓存

no-cache:允许使用本地和代理服务器缓存,但要求在返回缓存的版本之前将请求提交到源头服务器进行验证

no-store: 不允许本地和代理服务器缓存,必须要到源服务器请求最新资源(即使本地或代理服务器有缓存)

no-transform: 不允许缓存服务器对资源进行转换(比如压缩)

max-age=:表示允许浏览器缓存多少秒,指定时间内不向服务器发送请求

s-maxage=:表示允许代理服务器缓存多少秒。如果同时设置了max-ages-maxage,浏览器会根据max-age进行缓存,代理服务器会根据s-maxage进行缓存

must-revalidate:如果缓存过期了,浏览器必须要到源服务器发送请求

proxy-revalidate:如果缓存过期了,缓存服务器必须要到源服务器发送请求

// 浏览器和代理服务器对资源缓存一年,并且每次请求都到服务器器去验证
Cache-Control: max-age=31536000, no-cache

通常情况下服务端会设置1年的长缓存,为了避免资源更新而浏览器仍然读取缓存的问题,前端可以把打包后的新资源加上hash值,然后上传到静态资源服务器,由于文件地址已经改变,浏览器就会去加载新的文件,这是目前使用广泛的缓存解决方案

ETag

ETag 是HTTP 1.1 推出的缓存验证字段,它相比于Last-Modified这种基于时间的验证方式要更加可靠。服务端在返回资源时先基于某种算法计算出资源的唯一值(比如hash),然后设置到ETag里,下次请求时浏览器会自动带上If-None-Match: <ETag-value>,服务器通过判断Etag值决定是否返回新的资源,

Nginx 缓存

Nginx 缓存类似于浏览器缓存,只不过一个存在用户本地,一个存在服务器。开启缓存的方法很简单,在配置文件中添加下面两行代码

# proxy_cache_path:缓存资源的路径;levels:开启二级目录;keys_zone:缓存关系占用内存大小(cache下可以有很多缓存文件夹,文件夹和缓存资源的对应关系需要保存到内存中)

proxy_cache_path /var/cache levels=1:2 keys_zone=my_cache:10m

server {
  proxy_cache   my_cache;
}

代理缓存优势:只要第一个用户发送了请求,代理服务器就可以进行资源缓存,后面的所有请求都能从缓存中读取,即使用户切换了浏览器效果也是一样的,因为它是针对URL进行缓存的。源服务器设置的max-age值对浏览器和代理服务器都是有效的,也可以通过s-maxage对代理服务器单独设置缓存时间

vary

上面的缓存都是基于URL,即只要请求的地址是一样的,就允许浏览器或代理服务器进行缓存。但是实际开发中可能有这样的需求,要求同一个URL根据不同的国家返回不同的数据,或者根据不同的终端(手机端和PC端)返回不同的数据,这时候就不能简单的只存取一种缓存了,Vary字段就是解决同一个URL不同缓存的问题的

Vary=<value> 比如我们在服务端设置了 Vary: X-Test-Cache,然后客户端发送请求时,在请求头中添加了X-Test-Cache: zh-CN,此时缓存服务器会进行首次缓存。然后下次请求是可能是一个外国朋友发送的,它的请求头是X-Test-Cache: en-US,这时候不会从缓存中读取数据,而是向源服务器发送一个新的请求,缓存服务器再对这次结果进行缓存。后面的请求如果是来自zh-CN就读取zh-CN中的缓存,如果来自en-US就读取en-US的缓存,这样就解决了同一个URL不同缓存的问题

原文地址:https://www.cnblogs.com/yesyes/p/15375866.html