Nginx 客户端缓存Etag和If-None-Match

 

浏览器缓存和Nginx缓存


缓存是提升用户访问速度,节省带宽,减轻服务器压力的必经之道。

下面都是针对的Http 1.1来说明,HTTP缓存都是针对浏览器客户端,其他第三方客户端不考虑。

使用缓存是最有效的提高访问速度的方法,在web服务器的场景当中不仅要考虑nginx作为缓存服务时候的使用方法还得考虑浏览器中的缓存失效的场景,因为浏览器缓存是否生效可以通过nginx指令去控制。浏览器的缓存对用户体验也是最大的。

使用浏览器缓存,即本地缓存,只需要读取本地的磁盘或者内存就可以了。通常是同时使用浏览器和nginx缓存。

Nginx 客户端缓存Etag和If-None-Match_第1张图片

 

 

基本原理和概念


相同的两次请求返回的结果相同时,第一次返回的结果缓存在客户端,第二次服务端不再返回结果,仅返回一个特殊的状态码,告诉客户端第二次请求的结果与上次相同,可以直接使用上次返回的数据。

实现中,会用到HTTP头中的两个字段:

  • ETag 返回应答数据的标记,服务端生成发送给客户端

  • If-None-Match 同样的请求,上一次返回的 ETag 值

Nginx 客户端缓存Etag和If-None-Match_第2张图片

 

 

交互过程


  • 服务端在将数据发送给客户端之前,首先计算应答数据的摘要(通常是MD5),把计算结果作为 ETag 的值,和数据一同发送给客户端。

  • 客户端收到应答数据后,检测 HTTP Header 中是否有 ETag 字段,如有则缓存应答数据和 ETag 的值

  • 客户端再次发起同一请求时,读取上次缓存的 ETag 值,将其作为 If-None-Match 的值,并与请求数据一同发送给服务端

  • 服务端收到请求,执行请求,在把应答数据返回给客户端之前计算摘要,并与客户端上报的摘要比较,如果两次摘要相同,说明本次的应答数据与上一次请求的应答数据相同,且客户端已缓存该数据,则简单返回304。

  • 客户端收到304,直接读取本地缓存的数据返回给调用网络模块的业务方。

交互过程总结如下图:

Nginx 客户端缓存Etag和If-None-Match_第3张图片

如果你禁用浏览器缓存 ,打开一个新的网页每次你刷新网页都会返回200而不是304。

Nginx 客户端缓存Etag和If-None-Match_第4张图片

 

缓存模式


浏览器缓存可以分为两种模式,强缓存协商缓存

  • 强缓存(无HTTP请求,无需协商)

    直接读取本地缓存,无需跟服务端发送请求确认,http返回状态码是200(from memory cache或者from disk cache ,不同浏览器返回的信息不一致的)。

    对应的Http header有:

    • Cache-Control
    • Expires
  • 协商缓存(有HTTP请求,需协商)

    浏览器虽然发现了本地有该资源的缓存,但是不确定是否是最新的,于是想服务器询问,若服务器认为浏览器的缓存版本还可用,那么便会返回304(Not Modified) http状态码。

    对应的Http header有:

    • Last-Modified
    • ETag

 

Etag头部


 Etag是存在于HTTP响应当中的,是Nginx向浏览器返回时添加的,它来标识一个特定版本的资源,Etag的值是通过上次修改时间的值以及资源的字节长度来生成的。

Syntax: etag on | off;
Default: etag on;
Context: http, server, location

生成规则:
ngx_sprintf(etag->value.data, "\"%xT-%xO\"",
r->headers_out.last_modified_time,
r->headers_out.content_length_n)

Nginx 客户端缓存Etag和If-None-Match_第5张图片

 

之前用户请求资源nginx返回了Etag给浏览器,浏览器也会缓存该Etag的值。当浏览器通过时间维度认为Etag值过期了,那么这个时候浏览器又想去nginx上重新读资源,比如nginx服务器上这个资源到底有没有修改过,如果没有修改过返回304给客户端,而不需要将完整的内容给客户端,比如这个文件有几十兆。

怎么样让nginx快速的判断这个资源有没有修改过。浏览器会通过if-none-match头部在它的值里面填的是Etag的值,这样nginx收到if-none-match的时候就会做比较,当Etag标识出来的值和nginx的Etag值比较匹配的时候才会返回200,否则验证失败返回304表示没又改变。

Nginx 客户端缓存Etag和If-None-Match_第6张图片

 

If-None-Match


Nginx 客户端缓存Etag和If-None-Match_第7张图片

 

举个例子


Nginx 客户端缓存Etag和If-None-Match_第8张图片

关闭缓存可以看到实际的请求发到上游服务器了,下面开始打开缓存

Nginx 客户端缓存Etag和If-None-Match_第9张图片

浏览器虽然发现了本地有该资源的缓存,但是不确定是否是最新的,于是想服务器询问,若服务器认为浏览器的缓存版本还可用,那么便会返回304(Not Modified) http状态码。 

Nginx 客户端缓存Etag和If-None-Match_第10张图片

直接读取本地缓存,无需跟服务端发送请求确认,http返回状态码是200(from memory cache或者from disk cache ,不同浏览器返回的信息不一致的)。 

你可能感兴趣的:(Nginx,nginx)