ETag的作用 - HTTP缓存

浏览器都附带HTTP缓存实现,只需使用相应的HTTP标头指令,浏览器就能知道何时使用缓存及缓存时间。

服务器返回响应时会附带一组HTTP头,描述返回内容的类型、长度、缓存指令、验证令牌等。

如图所示,服务端返回一个1024字节的响应,告诉客户端最长缓存120秒,附带一个验证令牌(“ x234dff”),用于缓存过期后检查资源是否已修改,如果修改则重新加载,否则继续使用缓存内容,并自动延长120秒。

ETag

未使用ETag的场景:

假如距离第一次请求的返回已过去120秒,浏览器再次向同一资源发现请求时,

首先,浏览器会检查本地缓存找出先前的响应。

此时,响应的内容已过期,浏览器无法使用。

浏览器会重新发出新请求获取内容,但是,这样效率并不高,因为,资源如果没有发生变化,这次请求就显得十分浪费!

使用ETag场景:

ETag中指定的验证令牌旨在解决重复下载未发生变化内容的问题。

服务器生成并返回一个令牌,令牌是资源的指纹,资源发生变化则令牌也会发生变化。

客户端不需要知道指纹是如何生成的,只需要在下一个请求时将令牌通过http头带回给服务端。

服务器端查看指纹是否与资源现有的指纹相同,如果相同说明资源没有发生变化,直接返回304,告诉浏览器资源没有发生变化,浏览器直接使用缓存内容。

示例中,客户端在HTTP请求标头中使用“ If-None-Match” 带上ETag令牌。

服务器根据当前资源检查令牌,如果令牌一致,返回“ 304 Not Modified”响应,告诉浏览器缓存中的内容未发生变化,并且缓存时间可以再延长120秒。

缓存控制

从性能优化角度来看,最好的请求是不需要与服务器通信:

内容的本地副本能消除所有网络延迟,避免数据传输。

为达到该目标,HTTP规范允许服务器返回Cache-Control指令,该指令控制浏览器和中间缓存的响应方式及缓存时间。

no-cache

如果存在ETag,no-cache会导致往返验证缓存的内容,如果验证后资源没有更改,则不会下载内容,直接使用缓存内容。

no-store

不允许浏览器和所有中间缓存存储返回的内容,每次用户请求该资源时,都会将请求发送到服务器,并重新下载完整内容。

public

如果响应被标记为“public”,则即使它具有HTTP身份验证,且响应状态代码通常不可缓存,也能够将其缓存。

大多情况下,“public”不是必需的,因为显式的使用能让响应无论如何都是可缓存的。

private

浏览器可以缓存“private”响应。但是,这些响应通常是针对单个用户的,因此,不允许中间缓存将其缓存。如:不允许CDN缓存该页面。

max-age

指定从返回内容开始到重新获取内容的最长时间(以秒为单位)。

如,“ max-age = 60”表示内容可以缓存并在接下来60秒内可重复使用。

按照上面的决策树确定应用程序资源的最佳缓存策略。

理想情况应让客户端尽可能长的缓存尽可能多的内容,为每个响应提供ETag令牌并启用有效验证。