Skip to content

Instantly share code, notes, and snippets.

@dailc
Last active March 28, 2021 15:41
Show Gist options
  • Save dailc/43b2831cc48a114ff4de4b9ff8bc7d83 to your computer and use it in GitHub Desktop.
Save dailc/43b2831cc48a114ff4de4b9ff8bc7d83 to your computer and use it in GitHub Desktop.
[webvie缓存] webview和浏览器缓存机制 tags:webview,cache
## Expires,ETag,Cache-Control之间的关系
### Last-Modified
浏览器第一次请求资源时,服务器的返回状态时`200`,内容是对应的请求资源,同时头部中会有一个`Last-Modified`属性标识,记录此文件在服务器端最后的被修改的时间,格式为:
```
Last-Modified:Tue, 24 Feb 2009 08:01:04 GMT
```
浏览器第二次请求此url时(如果有缓存),根据Http协议,浏览器会向服务器发送`If-Modified-Since`报头,询问该时间后文件是否有被修改过。
客户端格式为:
```
If-Modified-Since:Tue, 24 Feb 2009 08:01:04 GMT
```
如果服务器端的资源没有变化,则会自动返回`Http 304`,内容为空,获取浏览器本地缓存,这样就节省了传输数据量。当服务器端代码发送改变或者重启时,则会重新回到第一步,在浏览器请求时写入`Last-Modified`,确保服务器有变化时,浏览器能得到最新资源
tips: 如果`If-Modified-Since`的时间比服务器当前时间(当前的请求时间request_time)还晚,会认为是个非法请求
### ETag
ETag是**被请求变量的实体标记**,ETag由服务器端生成,会随着文件的改变而改变。
即服务器响应时给请求URL标记(也就是说一个请求URL对应一个ETag),
并通过Http响应头传给浏览器,格式为:
```
Etag:“5d8c72a5edda8d6a:3239″
```
客户端的查询更新格式为:
```
If-None-Match:“5d8c72a5edda8d6a:3239″
```
如果ETag没有改变,则返回状态`304`(只有`If-Modified-Since`和ETag等操作都符合才会304)
ETag主要用来判断URL对象是否改变,会配合`Last-Modified`等使用
ETag主要用来解决`Last-Modified`无法解决的问题,比如能比`Last-Modified`更加精确的知道文件是否修改过,`Last-Modified`只能检测到秒级别,如果一秒内多次修改无法判断(原因是UNIX记录MTIME只能精确到秒),而ETag可以避免这个问题
所以正常来说ETag是`Last-Modified`的精确版本。
**注意**
分布式系统里多台机器间文件的last-modified必须保持一致,以免负载均衡到不同机器导致比对失败
分布式系统尽量关闭掉Etag(每台机器生成的etag都会不一样)
### Expires
结合`Last-Modified`一起使用。用于控制请求文件的有效时间。当请求数据在有效期内浏览器从缓存获取,缓存中的数据失效或过期,才会从服务器端更新。
它是`Http 1.0`的内容,声明了一个网页或URL不再被浏览器缓存的时间,一旦超过了这个时间,浏览器不管怎么样都应该重新联系服务器。如
```
Expires:Thu, 02 Apr 2009 05:14:08 GMT
```
在`Http 1.0`中,如果设置了Expires,在这个时间内,浏览器不会发出新的请求,而是直接使用本地缓存。
Expires 的一个缺点就是,返回的到期时间是服务器端的时间,这样存在一个问题,如果客户端的时间与服务器的时间相差很大,那么误差就很大,所以在HTTP 1.1版开始,使用`Cache-Control: max-age=`秒替代。
每次下载新的页面时,Expires会重新计算。
### Pragma
例如`Http 1.0`中的`Pragma:no-cache`等同于`Http 1.1`中的`Cache-Control:no-cache`
### Cache-Control
`Http 1.1`的内容,它有一个值`max-age`规定了缓存在本地的有效时间(这个是一个数字-多少秒)。
`Expires =max-age + "每次下载时的当前的request时间"`
理论上来说,这个有效时间是和Expires的失效时间一致的,但是有时候不一定,Cache-Control的优先级要更高。
(Expires是过时的,如果max-age和Expires同时存在,则被Cache-Control的max-age覆盖)
Cache-Control的可取值:
| Cache-directive| 说明 |
| :------------- |-------------:|
| public | 所有内容都将被缓存(客户端和代理服务器都可缓存) |
| private | 内容只缓存到私有缓存中(仅客户端可以缓存,代理服务器不可缓存) |
| no-cache | 必须先与服务器确认返回的响应是否被更改,然后才能使用该响应来满足后续对同一个网址的请求。因此,如果存在合适的验证令牌 (ETag),no-cache 会发起往返通信来验证缓存的响应,如果资源未被更改,可以避免下载 |
| no-store | 所有内容都不会被缓存到缓存或 Internet 临时文件中 |
| must-revalidation/proxy-revalidation | 如果缓存的内容失效,请求必须发送到服务器/代理以进行重新验证 |
| max-age=xxx (xxx is numeric) | 缓存的内容将在 xxx 秒后失效, 这个选项只在HTTP 1.1可用, 并如果和Last-Modified一起使用时, 优先级较高 |
tips: 设置了max-age时,在有效期间内,不会发起新的请求,过期后,才会重新发请求,这时候就会继续Last-Modified和Etag的验证。
### 不能缓存的请求
当满足以下条件时,请求无法被浏览器缓存:
* HTTP信息头中包含Cache-Control:no-cache,pragma:no-cache(HTTP1.0)
* 需要根据Cookie,认证信息等决定输入内容的动态请求是不能被缓存的
* 经过HTTPS安全加密的请求(有人也经过测试发现,ie其实在头部加入Cache-Control:max-age信息,firefox在头部加入Cache-Control:Public之后,能够对HTTPS的资源进行缓存,参考[《HTTPS的七个误解》](http://www.ruanyifeng.com/blog/2011/02/seven_myths_about_https.html))
* POST请求无法被缓存
* HTTP响应头中不包含Last-Modified/Etag,也不包含Cache-Control/Expires的请求无法被缓存
### 用户行为与缓存
浏览器的缓存与不同用户行为有关,不同的机制在不同的操作下有效性不一样。如下表:
| 用户操作| Expires/Cache-Control | lAST-Modified/Etag |
| :------------- |:-------------:|-------------:|
| 地址栏回车 | 有效 | 有效 | | 页面链接跳转 | 有效 | 有效 |
| 新开窗口 | 有效 | 有效 |
| 前进,后退 | 有效 | 有效 |
| F5刷新 | 无效 | 有效 |
| ctrl+F5刷新 | 无效 | 无效 |
## 客户端缓存与服务器缓存
上述提到的内容都属于客户端缓存(浏览器缓存)
服务器端的缓存一般是服务器为了提升速度而产生的一些临时文件,如gzip的文件,一般是放在特定的目录。
## 参考
* http://blog.csdn.net/eroswang/article/details/8302191
* http://www.open-open.com/lib/view/open1494985360881.html
* http://www.cnblogs.com/zichi/p/4685822.html?tvd
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment