1. 1. Http报文结构
  2. 2. Http之缓存
    1. 2.1. Cache-Control
  3. 3. Expires
  4. 4. Last-Modified
    1. 4.1. If-Modified-Since:(此标头,仅对Get方法有意义)
    2. 4.2. If-Unmodified-Since:
  5. 5. Etag :(HTTP1.1)
    1. 5.1. 客户端如何获知是否过期,是否使用缓存?
  6. 6. Http之持久连接 —— Connection: Keep-Alive
  7. 7. Http之Chunk

Http报文结构

Http报文结构

Http之缓存

Http的缓存技术大致可以分为3种,Cache-Control系,Expires系,Last-Modified系,Etag系。
其中Cache-Control的存在会覆盖Expires,其他的同时存在则需要全部的规则都通过检验才能使用缓存。比如带有Cache-Control 和 If-Modified-Since,就要通过了 Cache-Control ,而且对比了 Last-Modified 确实在有效期内才可使用缓存。并不是冲突的关系。
下面介绍各系概念:

Cache-Control

Cache-Control主要有以下几种类型:

(1) 请求Request:
[1] no-cache —- 不要读取缓存中的文件,要求向WEB服务器重新请求
[2] no-store —- 请求和响应都禁止被缓存
[3] max-age: —- 表示当访问此网页后的max-age秒内再次访问不会去服务器请求,其功能与Expires类似,只是Expires是根据某个特定日期值做比较。一但缓存者自身的时间不准确.则结果可能就是错误的,而max-age,显然无此问题.。Max-age的优先级也是高于Expires的。
[4] max-stale —- 允许读取过期时间必须小于max-stale 值的缓存对象。
[5] min-fresh —- 接受其max-age生命期大于其当前时间 跟 min-fresh 值之和的缓存对象

[6] only-if-cached —- 告知缓存者,我希望内容来自缓存,我并不关心被缓存响应,是否是新鲜的.

[7] no-transform —- 告知代理,不要更改媒体类型,比如jpg,被你改成png.
(2) 响应Response:
[1] public —- 数据内容皆被储存起来,就连有密码保护的网页也储存,安全性很低
[2] private —- 数据内容只能被储存到私有的cache,仅对某个用户有效,不能共享
[3] no-cache —- 可以缓存,但是只有在跟WEB服务器验证了其有效后,才能返回给客户端
[4] no-store —- 请求和响应都禁止被缓存
[5] max-age: —– 本响应包含的对象的过期时间
[6] Must-revalidate —- 如果缓存过期了,会再次和原来的服务器确定是否为最新数据,而不是和中间的proxy
[7] max-stale —- 允许读取过期时间必须小于max-stale 值的缓存对象。
[8] proxy-revalidate —- 与Must-revalidate类似,区别在于:proxy-revalidate要排除掉用户代理的缓存的。即其规则并不应用于用户代理的本地缓存上。
[9] s-maxage —- 与max-age的唯一区别是,s-maxage仅仅应用于共享缓存.而不应用于用户代理的本地缓存等针对单用户的缓存. 另外,s-maxage的优先级要高于max-age.
[10] no-transform —- 告知代理,不要更改媒体类型,比如jpg,被你改成png.

注意在请求和响应中是不同的。
还有请求中的 no-cache 并非让服务器不使用缓存,这时候服务器还是有可能使用缓存的。这个命令意思是不能直接返回缓存,必须跟源服务器确认过返回最新的资源,假如确认了没有更新,那么可以返回缓存。
响应中类似的命令是must-revalidate 搭配max-age=10。
no-cache与must-revalidate深入探究
想绝对完全不存储和使用缓存的话,用 no-store。

Expires

Expires 字段指定的时间之前都会使用缓存。类似 Cache-Control:max-age。事实上, Cache-Control:max-age 存在时就会忽略 Expires。

Last-Modified

指明资源的最终修改的时间,一个GMT时间,告知,被请求实体的最后修改时间.用于客户端校验其缓存副本是否仍然可以信任.与其相关的两个条件请求标头:

If-Modified-Since:(此标头,仅对Get方法有意义)

如果实体在指定时间后,没有修改则返回一个304,否则返回一个常规的Get请求的响应(比如200). 另外,如果该标头的值是一个非法的值,那么也同样返回一个常规的Get请求的响应.
PS:用户代理发起 If-Modified-Since尝试握手的条件,可能会有不同,比如IE系,如果该实体第一次响应头中包含Cache-Control:no-cache.则 IE不会使用If-Modified-Since请求资源.而其他浏览器则会. 但是如果使用Cache-Control:no-store.则所有用户代理的表现一致.都不使用If-Modified-Since(因为no-store的语义十分强烈.不允许任何缓存,这个在后续有专门介绍.)

If-Unmodified-Since:

如果实体在指定时间后,没有任何修改,那么就可以直接执行该请求使用方法的对应行为. 而如果有修改,则返回一个412 Precondition Failed状态码,并且抛弃该方法对应的行为操作(GET方法除外).
Last-Modified: Wed, 04 Jul 2016 09:26:05 GMT

Etag :(HTTP1.1)

生成一段可代表实体版本的字串.默认就是一段hash + 时间戳的形式.其实我们是可以使用自己的算法来生成Etag值.比如md5.
Apache的默认Etag包含Inode,Mtime,Size三部分.而且Etag有强弱之分.比如一般的弱Etag,是以W/开头的,如:W/”abcde12”,这部分不是我们关注的焦点.因为弱Etag和强Etag的区别只在于算法.比如某种弱Etag关注的时间精度,为秒.而我们在项目中,最常见的做法是使用MD5.是一种忽略时间维度的,强Etag.为的是保证精确度.以及负载均衡设备的同步.除非我们的项目有特殊需求.但是往往我们可以根据需求,来调整算法.而不是沿用一些传统的弱Etag算法.
这东西,是要和客户端的两个请求标头配合使用的:
(1) If-Match:
语义:如果有匹配,或者值为””,才可以能去执行,请求所使用的方法,所对应的行为.
If-Match,可以看做是一个过滤器,主要应用于资源多版本共存的解决方案.比如服务器端对同一实体,有多个版本.那么客户端,即可按照指定版本来获取实体.
If-Match的值就是对应指定版本的Etag值.这个值可以是多选的.典型的应用场景是,客户端使用put方式请求服务器端,并带有多个If-Match的值.服务器端检查所有该实体的版本.找到匹配项,就立刻更新服务器端的对应版本.如果无一匹配,则发送一个412 Precondition Failed状态码.
(2) If-None-Match:
语义:如果有任何匹配,或值是”
”,并且原始服务器存在其请求的实体,则不允许执行该请求所使用放的对应行为,如果此时,该请求使用的get,或head方法.则返回一个304状态码.以及其他一些相关的缓存控制的标头.
与If-Match相反 .但它的典型应用,也是我们要关注的部分.支持http1.1的现代浏览器,以及web server,应用If-None-Match头用于,缓存新鲜度校验.典型应用场景就是,一但原始服务器的某个响应中包含Etag时,如果浏览器本地缓存了该实体.那么在第二次的常规的get或head请求时,就会自动带上 If-None-Match头.当原始服务器上该实体的版本对应的Etag值与之匹配时,则原始服务器会返回304状态码.然后浏览器认为本地缓存是新鲜的.则继续使用缓存的实体. 但,其实Etag的本意是版本管理.而并不是缓存有效性校验.这应该是一个衍生出来的使用方式. 而这种方式相比Last-Modified校验方式的好处是,如果我们消除时间戳部分,仅使用hash作为Etag值. 就可以方便做负载均衡同步.

客户端如何获知是否过期,是否使用缓存?

缓存有效返回304状态码。无效返回200和含有最新实体的body。

Http之持久连接 —— Connection: Keep-Alive

初期版本的Http协议中,每进行一次Http通讯就要断开一次TCP连接。当并发访问资源的时候,无形中造成了大量无谓的TCP连接建立和断开,增加通讯开销。
为解决这个问题,Http 1.1 搞出了持久连接(Presistent Connections, keep-alive,或connection reuse)。特点是,只要任意一端没有明确提出断开连接,则保持TCP连接状态。
http_reuse_connection
持久连接由 Connection: Keep-Alive 控制,Http 1.1 默认连接都是持久连接。之前的版本需要主动指定 Connection: Keep-Alive 。
当服务器想明确断开连接时,可指定 Connection: close。

Http之Chunk

在回复消息的Headers有transfer-coding域值为chunked,表示将用chunked编码传输内容。这时候 Content-Length 无效。