[转]HTTP 1.1的一些细节:Cache机制

HTTP 1.1的一些细节:Cache机制
Du XiaoGang <dugang@188.com>

    Cache机制可能是HTTP 1.1协议中最复杂的一个组成部分,它的目的有两个:
        1, 降低网络上发送HTTP请求的次数,这采用"过期"机制(Expiration Mechanism).
        2, 降低网络上完整回复HTTP请求包的次数,这采用"确证"机制(Validation Mechanism).

    首先描述"过期"机制的模型.
     HTTP Cache机制的最理想目标是使客户端根本不发起非必要的请求.
    它的基本原理是为每个被请求实体(Entity)设定一个内容将变更的时间点,从该实体第一次被请求后到这个时间点到达之前实体的内容是不变的,因而可以直接使用Cache中缓存的内容满足针对该实体的后续请求,而不必每次由源HTTP服务器做响应.
    HTTP服务器通过两种实体头(Entity-Header)来实现"过期"机制:Expires头和Cache-Control头的max-age子项.

    其次是"验证"机制模型.
    HTTP服务器为每个作为响应发送的实体附加一个"验证子",当Cache中的响应"过期"后,Cache将该验证子发送给HTTP源服务器以验证是否该响应已确实过期. 如果确认过期则源服务器发送新响应包,否则只发送改变的实体头,这种机制可有效节省带宽.
    HTTP服务器通过两种方式实现该"验证子":ETag以及Last-Modified Date.验证子的特点在于它会随着所代表实体的变化而变化,就像是实体的指纹,而且验证子可分为强验证子和弱验证子两种,强验证子会严格随实体变化而变化,弱验证子则只是在实体发生显著变化时才变化.

    以下是与Cache相关的实体头:
    Date: 响应(包含实体)产生的时间.
    Expires: 时间值,该时间点之前可以认为对应实体内容不变.
    Cache-Control:Cache命令,主要有以下子项:
        public: 实体可被public类型的Cache缓存.
        private: 实体只对某个用户有效,不能被public类型的Cache缓存.
        no-cache: 实体不可被缓存.
        no-store: 实体不能被存储在非易失存储器中,应当在用完后被立即清除.
        max-age: 实体保持有效的最长时间,其优先级高于Expires指定时间.


    Age: 一般由响应路径中的Cache产生,表示自从响应发出到现在在Cache中所经过的时间.
    ETag: "验证子",一般为强性.
    Last-Modified: "验证子",一般为弱性,表示实体最后变更的时间.
    If-Match/If-None-Match/If-Modified-Since/If-Unmodified-Since:条件验证语句,Match搭配ETag,当符合条件时执行请求. Modified搭配Last-Modified验证子,符合条件时执行请求.



HTTP 1.1中有两个实体头(Entity-Header)直接与编码相关,分别为Content-Encoding和Transfer-Encoding.

    先说Content-Encoding, 该头表示实体已经采用了的编码方式.Content-Encoding是请求URL对应实体(Entity)本身的一部分.比如请求URL为http://host/image.png.gz时,可能会得到的Content-Encoding为gzip.Content-Encoding的值是不区分大小写的,目前HTTP1.1标准中已包括的有gzip/compress/deflate/identity等.
   与Content-Encoding头对应,HTTP请求中包含了一个Accept-Encoding头,该头用来说明用户代理(User-Agent,一般也就是浏览器)能接受哪些类型的编码. 如果HTTP请求中不存在该头,服务器可以认为用户代理能接受任何编码类型.

    接下来重点描述Transfer-Encoding, 该头表示为了达到安全传输或者数据压缩等目的而对实体进行的编码. Transfer-Encoding与Content-Encoding的不同之处在于:
        1, Transfer-Encoding只是在传输过程中才有的,并非请求URL对应实体的本身特性.
        2, Transfer-Encoding是一个"跳到跳"头,而Content-Encoding是"端到端"头.
    该头的用途举例如,请求URL为http://host/abc.txt,服务器发送数据时认为该文件可用gzip方式压缩以节省带宽,接收端看到Transfer-Encoding为gzip首先进行解码然后才能得到请求实体.
    此外多个编码可能同时对同一实体使用,所以Transfer-Encoding头中编码顺序相当重要,它代表了解码的顺序过程.同样,Transfer-Encoding的值也是不区分大小写的,目前HTTP1.1标准中已包括的有gzip/compress/deflate/identity/chunked等.
    Transfer-Encoding中有一类特定编码:chunked编码.该编码将实体分块传送并逐块标明长度,直到长度为0块表示传输结束, 这在实体长度未知时特别有用(比如由数据库动态产生的数据). HTTP1.1标准规定,只要使用了Transfer-Encoding的地方就必须使用chunked编码,并且chunked必须为最后一层编码.任何HTTP 1.1应用都必须能处理chunked编码.
    与Transfer-Encoding对应的请求头为TE,它主要表示请求发起者愿意接收的Transfer-Encoding类型. 如果TE为空或者不存在,则表示唯一能接受的类型为chunked.
    其他与Transfer-Encoding相关的头还包括Trailer,它与chunked编码相关,就不细述了.

    顾名思义,Content-Length表示传输的实体长度,以字节为单位(在请求方法为HEAD时表示会要发送的长度,但并不实际发送.).Content-Length受Transfer-Encoding影响很大,只要Transfer-Encoding不为identity,则实际传输长度由编码中的chunked决定,Content-Length即使存在也被忽略.

关于HTTP Message Body的长度
在HTTP中有消息体(Message body)和实体(Entity body)之分,简单说来在没有Transfer-Encoding作用时,消息体就是实体,而应用了Transfer-Encoding后,消息体就是编码后的实体,如下:
        Message body = Transfer-Encoding encode(Entity body)

    如何确定消息体的长度? HTTP 1.1标准给出了如下方法(按照优先级依次排列):
        1, 响应状态(Response Status)为1xx/204/304或者请求方法为HEAD时,消息体长度为0.
        2, 如果使用了非"identity"的Transfer-Encoding编码方式,则消息体长度由"chunked"编码决定,除非该消息以连接关闭为结束.
        3, 如果存在"Content-Length"实体头,则消息长度为该数值.
        3, 如果消息使用关闭连接方式代表消息体结束,则长度由关闭前收到的长度决定. 该条对HTTP Request包含的消息体不适用.
posted on 2009-10-18 16:20  feney  阅读(1450)  评论(0编辑  收藏  举报