消息的可缓存性v0 1

12
Hosting Imporvement 消消消消消消消

Upload: lichun-pickup

Post on 13-May-2015

888 views

Category:

Technology


4 download

DESCRIPTION

消息的可缓存性V0 1

TRANSCRIPT

Page 1: 消息的可缓存性V0 1

Hosting Imporvement

消息的可缓存性

Page 2: 消息的可缓存性V0 1

目 录 目 录

目目 录录......................................................................................................................................... 2

1 修订记录............................................................................................................................. 3

2 介绍.................................................................................................................................... 4

2.1 目的和范围...................................................................................................................................4

2.2 术语与缩写解释............................................................................................................................4

3 可缓存实体.......................................................................................................................... 5

3.1 按状态码分类的 response可缓存性...............................................................................................5

3.2 cache-control response可缓存性...................................................................................................5

3.3 Response响应的过期与保鲜.........................................................................................................8

3.4 Validation验证............................................................................................................................10

4 其他建议........................................................................................................................... 11

4.1 进一步工作.................................................................................................................................11

5 相关文档列表.................................................................................................................... 12

Page 3: 消息的可缓存性V0 1

1 修订记录

修订日期 版本号 描述 修订人

2008/06/

27

0.1 消息的可缓存性 v0.1 Pickup.Li

Page 4: 消息的可缓存性V0 1

2 介绍

2.1 目的和范围

本文档的目的介绍HTTP消息的缓存以及相关信息。

cache服务器作为反向代理可以减少后端web服务器的访问压力并提高用户的访问速度,但是 cache

服务器到底可以缓存那些东西,可以缓存多久,怎么控制某个消息过期以后的动作等等。这些都是本文档关注的内容。

本文介绍的内容主要来源是HTTP 1.1,某些缓存服务器通过一定的配置(比如:squid配置中refresh_pattern的 ignore-private等)能够显式的违反某些规则,所以具体的某个消息的缓存还依赖于缓存服务器的配置及相关因素,需要具体问题具体分析。

另外,本文关注的主要是做反向代理的缓存服务器。

2.2 术语与缩写解释

编号 术语 解释1. message 消息,HTTP通讯的基本单元,通常指 request或者 response消息2. request 请求,客户端向服务器发送的请求3. response 响应,服务器对客户端请求的响应4. cache 缓存,存储在本机的 response信息,以及对这些信息的存储,获取,删除等。

这些信息存储以便在相同的 request请求时能够及时返回,从而减少响应时间和网络流量的消耗。

5. cacheable 可缓存,某个 response信息如果可以存储在下来以供接下来同样的 request请求使用,那么这个信息可以被认为作可缓存的。即使某个 response是可以缓存的,当一个特定的 request请求到达时,是否返回该 response还要受到一些附加的条件限制

6. explicit

expiration time

显式的过期时间,源服务器指定的过期时间,当过了过期时间以后 cache服务器返回相应 response之前必须经过验证。

7. heuristic

expiration time

启发式的过期时间,当没有显式的过期时间时由 cache服务器生成的过期时间

8. age 年龄,一个 response的年龄值就是它从被源服务器发送或者验证之后经过的时间值

9. freshness

lifetime

保鲜时间,它表示从 response生成到过期之间经过的时间值

10. fresh 保鲜的,如果一个 response的 age没有超过 freshness lifetime则被认为是保鲜的

11. stale 过期的,如果一个 response的 age超过了 freshness lifetime则被认为是过期的

12. validator 验证子,用于确认 cache保存的实体是否和源服务器一致的协议元素(比如:Last Modified time或者一个 entity tag)

Page 5: 消息的可缓存性V0 1

13. Shared and Non-

Shared Caches

共享和不可共享 cache,不可共享 cache是指那些只能被单个用户访问的cache,访问它必须经过相关的权限认证,其他的 cache都是共享 cache。

Page 6: 消息的可缓存性V0 1

3 可缓存实体

在 Squid Cache 服务器安装配置与测试数据 中,经过测试和分析,发现 cache服务器不仅可以为web

服务器分担压力,并且能够提高用户访问时的速度。以 squid为例,网站用 squid 加速,目的有二

1: squid 本身具有缓存功能,可以将webserver输出的内容缓存起来,在缓存没有过期之前来的访问,都直接用缓存里面的内容,这样可以有效减少 webserver 机器上面的请求数量。这是 squid 的主要功用。

2: 网络慢的用户会长时间占用 webserver 的 TCP 连接,webserver 对每个连接占用的资源比较大,如果长时间不能释放出来服务其他请求,性能会有比较大的影响。前面放一个 squid,webserver 就可以迅速处理完逻辑以后,把数据快速发送给 squid, 然后去处理别的逻辑,而 squid 每个 TCP 连接占用的资源很少,不用担心占用太多资源。这个用途也叫做连接管理,有一些网络设备也可以做这个事情,价格都很贵。

所以我们有必要搞清楚哪些东西可以缓存,哪些不能被缓存,怎么控制,为网页制作人员和web

service维护配置人员提供指导。

3.1 按状态码分类的 response可缓存性

我们知道,response按照状态码可以分成 5类,分别是 1xx信息类,2xx成功类,3xx重定向类,4xx

客户端错误类和 5xx服务器错误类。这里可以被缓存的 response只有状态码为:200, 203, 206, 300, 301 或者 410的 response。其他的 response除非由 cache-control或者其他的 header显式指定(比如:cache-

control中的 “max-age”, “s-maxage”, “mustrevalidate”,“proxy-revalidate”, “public” 或 “private”),否则都不能被缓存。

3.2 cache-control response可缓存性

cache-control定义了一系列 request/response链上的 cache服务器必须要遵守的规则。这些规则大部分会改变缺省的 cache算法。cache-control的基本语法格式为:

Cache-Control = "Cache-Control" ":" 1#cache-directive

1#cache-directive表示一个或者多个 cache-directive,cache-directive可能是 cache-request-directive也有可能是 cache-response-directive。

cache-request-directive包括:"no-cache", "no-store", "max-age='delta-seconds'", "max-stale[='delta-

seconds']", "min-fresh='delta-seconds'", "no-transform", "only-if-cached"和 cache-extension。其中,"max-

stale"可以指定以秒为单位的时间值,"max-age"和"min-fresh"则必须指定以秒为单位的时间值。

cache-response-directive包括:"public", "private[='1#field-name']", "no-cache[='1#field-name']", "no-

store", "no-transform", "must-revalidate", "proxy-revalidate", "max-age='delta-seconds'", "s-maxage='delta-

seconds'", cache-extension。其中,"max-age"和" s-maxage"必须指定以秒为单位的时间值," private "和" no-

cache "可以带一个或者多个HTTP header域从而指定这些 header不能缓存。cache-extension是类似community="UCI"的 cache-control扩展标签,它可以用于自定义的 cache缓存协议元素,比如community="UCI"作为 Private的附带元素可以表示该条 response信息只能被私有的标识为“UCI”的 cache

缓存,其他的 cache都不能缓存它。

Page 7: 消息的可缓存性V0 1

首先,我们介绍一些影响 response可缓存性的 cache-control规则:"public", "private[='1#field-name']",

"no-cache[='1#field-name']"。

"public"表示该 response可以被缓存,就算平常被认为不能缓存或者只能被 non-shared cache缓存的那些 response也可以。

"private"表示该 response的全部或者某一部分是为单个用户服务的,不可以被 shared cache缓存,源服务器可以用它来标示该 response隶属于某个用户而不能为其他用户服务。私有(non-

shared)cache可以保存这些消息,但是"private"并不能保证消息内容的私密安全性。

"no-cache",如果 no-cache没有特别指定某些 field-name,那么它表示 cache如果需要返回该response给接下来的 request之前必须先向源服务器验证,否则不能发送。这样,源服务器就可以用它来强制 cache验证该 response,即使 cache被设置为可以返回过期的 response给用户。如果no-cache附带了一些 field-names,cache可以受限的返回 response,也就是说返回的 response

中对应的这些特定的 field-names在返回之前必须经过验证,这样源服务器可以限制某些 header

不会被重用,从而使得这些 header都是最新的。

接下来我们来看看影响 cache存储 response的 cache-control规则:"no-store"。

cache可存储 reponse和 response的可缓存性是不同的。为了避免某些敏感数据不被 cache存储下来,可以指定"no-store",它作用于整个 request或者 response消息。指定了"no-store"的 request表示该 request

以及由它引起的 response都不能被存储,指定了"no-store"的 response表示该 response以及引起它的request都不能被存储。它对 non-shared cache和 shared-cache都有效。也就是说 cache不能故意的把它存储在永久存储设备上,并且在转发了它以后应该及时清除易失存储设备上的信息。"no-store"提供了一定的私密安全保证,但是某些 cache也许不会遵守该约定,也有可能被浏览器本身缓存下来了(当用户点击后退按钮可以访问),并且也可以通过网络监听获得对应的数据。

接着介绍一下影响过期机制的一些 cache-control规则:"max-age", "s-maxage","max-stale"和"min-

fresh"。其中"max-age"可以应用于 request或者 response。

作用于 response的影响过期机制的一些 cache-control规则

"max-age":过期时间有源服务器的"Expires"头指定,也可以由"max-age"规则指定。"max-age"优先于"Expires"头(即使"Expires"头限制的时间值更加严格),当一个 response年龄值大于过期时间时,它被认为是过期的,返回过期的数据需要经过验证或者后面提到的 cache-control规则的作用。事实上,"max-

age"暗示了该 repsonse可以被缓存,除非指定了一些别的更加严格的 cache规则。HTTP 1.0没有制定"max-

age"规则。

"s-maxage":"s-maxage"总是被 private cache忽略。对于 shared cache,它指定了 response的最高生命期。它的优先级比"max-age"和"Expires"都要高。"s-maxage"在语义上包含了"proxy-revalidate",也就是说,cache服务器在返回一个过期的 response之前必须要首先提交源服务器进行验证。

作用于 request的影响过期机制的一些 cache-control规则

"max-age":在 request中包含"max-age"表示客户端同意接受一个 age小于指定秒数的 response。如果没有指定"max-stale"那么客户端并不同意接受一个过期的 response。

"min-fresh":表示客户端同意接受一个 freshness_lifetime不小于当前 age值+指定秒数的 response。也就是说客户端希望收到的 response的新鲜度至少在指定秒数以内。

"max-stale":表示客户端同意接受一个过期的 response消息。如果指定了时间值,表示客户端同意接受一个超过过期时间不大于指定秒数的 response消息。如果没有指定具体的数值,表示客户端同意接受一个超过过期时间任意值的 response消息。但是,不管是由于用户指定了"max-stale"还是 cache服务器被配置为返回过期的数据,cache服务器必须给这个过期的数据加上Warning 110(Response is stale)头。

Page 8: 消息的可缓存性V0 1

我们发现,"max-age"即可以应用于 request也可以应用于 response,如果 request和 response都包含了"max-age",那么应该以它们两个中的值更小的那一个为准。

上面,我们提到了 cache数据过期后需要提交源服务器进行验证,cache-control同样存在影响验证的规则:"max-age","only-if-cached","must-revalidate"和"proxy-revalidate"。

"max-age":客户端提交 request的时候可以加上不带 field-names的"no-cache"(如果是HTTP 1.0客户端可以用"Pragma: no-cache")来获得源服务器上的 response版本从而使 cache也装入这个版本。如果使用"max-age=0"附带于 request上,可以使得从客户端到源服务器链路上的所有 cache已有的对应 response

都提交源服务器进行验证,并且把该 response装入那些没有存储该 response的 cache服务器中。当链路中的某台 cache服务器收到"max-age=0"的 request请求,并且该请求中还附带了 validator,而该 validator于cache验证的 validator不同时,cache服务器可以选择自己的或者附带的 validator(比较好的方法是使用cache服务器自己的 validator),这样在服务器收到 200或者 304响应的时候可以根据具体的情况更新缓存,并给客户端发送正确的响应。另外,如果 request中包含了"no-cache"就不应该包含"max-age","max-

stale"和"min-fresh"。

"only-if-cached":在某些情况下(比如网络情况非常差),客户端可能希望获得 cache服务器中存储的response,而要求验证或者从源服务器重新获得对应 response消息,用户就可以在 request中包含"only-if-

cached"。收到这样的请求的 cache服务器可以返回本地存储的相应 response,或者 504(Gateway

Timeout)错误信息。如果它属于构建的 cache服务器集群,那么它也可以将这个请求转发给集群的其他cache服务器。

"must-revalidate":上面提到,用户指定"max-stale"或者 cache服务器被配置为返回过期的数据都可以导致过期消息的返回。而"must-revalidate"是源服务器用于指定 response在过期后必须到源服务器进行验证的规则,不管用户是否指定了"max-stale"或者 cache服务器是否被配置为返回过期的数据。它为某些协议特性提供了可靠性操作。如果 cache验证时不能连上源服务器,它必须返回 504(Gateway Timeout)错误信息。

"proxy-revalidate":除了不能够应用于 non-shared cache以外,"proxy-revalidate"和"must-revalidate"的意思是一样的。它允许在用户 cache中保存那些经过权限认证的 response(它们 应该包含有"public"来保证它们可以被缓存)并且在认证过同样的 request到达时返回缓存数据而不经过源服务器验证过程;其他的则每次都必须经过验证。

最后我们介绍一下"no-transform"规则。为了某些原因,一些 cache服务器在保存和传输消息的时候可能会转变实体主体的媒体类型。比如为了降低缓存空间或者在较慢的链接中减少传输流量,cache服务器可能会把一个图片的格式转换一下。但是某些应用场景下,数据的传输一个 bit也不能转换,这里"no-transform"就非常必须了。如果一个消息中包含了"no-transform",那么非修改头部及其指定的消息主体部分都不能转换或者改变,这些非修改头部包括"Content-Location", "Content-MD5", "ETag", "Last-Modified", "Expires",

"Content-Encoding", "Content-Range", "Content-Type"(参见HTTP 1.1 section 13.5.2 )

一般说来:遵循以下基本的规则

1. 如果响应头信息:告诉缓存器不要保留缓存,缓存器就不会缓存相应内容;

2. 如果请求信息是需要认证或者安全加密的,相应内容也不会被缓存;3. 如果在回应中不存在校验器(ETag或者 Last-Modified头信息),缓存服务器会认为缺乏直接的更新度信息,内容将会被认为不可缓存。

4. 一个缓存的副本如果含有以下信息:内容将会被认为是足够新的

o 含有完整的过期时间和寿命控制头信息,并且内容仍在保鲜期内;o 浏览器已经使用过缓存副本,并且在一个会话中已经检查过内容的新鲜度;o 缓存代理服务器近期内已经使用过缓存副本,并且内容的最后更新时间在上次使用期之前;

Page 9: 消息的可缓存性V0 1

o 够新的副本将直接从缓存中送出,而不会向源服务器发送请求;5. 如果缓存的副本已经太旧了,缓存服务器将向源服务器发出请求校验请求,用于确定是否可以继续使用当前拷贝继续服务;

3.3 Response响应的过期与保鲜

3.3.1 age 的计算方法

先介绍一下一个响应的 age的计算方法。

/*

* age_value: is the value of Age: header received by the cache with this response.

* date_value: is the value of the origin server's Date: header

* request_time: is the (local) time when the cache made the request that resulted in this cached response

* response_time: is the (local) time when the cache received the response

* now: is the current (local) time

*/

apparent_age = max(0, response_time - date_value);

corrected_received_age = max(apparent_age, age_value);

response_delay = response_time - request_time;

corrected_initial_age = corrected_received_age + response_delay;

resident_time = now - response_time;

current_age = corrected_initial_age + resident_time;

3.3.2 过期时间的计算方法

过期时间主要分为 explicit expiration time和 heuristic expiration time,强烈建议用户指定 explicit

expiration time,因为只有网页制作者更加清楚这个网页的过期时间。

先介绍一下 explicit expiration time的计算方法。

客户可以通过设置 Expires或者Cache-control的max-age(max-age优先级大于 Expires)来指定explicit expiration time。我们测试了 html和 php语言设置 Expires的方法,并且使用 ethereal观察了传输的HTTP信息,在我们的环境下,发现使用 html设置 header meta不能反映到HTTP header中去,而 php的header()函数则能够成功。

php设置HTTP头的方法很简单,只要调用函数 header()就可以了,假如我们新建一个名为testHeader.php的文件并将其内容修改为:

<?php

$offset = 3600 * 24;

$expire = "Expires: " . gmdate("D, d M Y H:i:s", time() + $offset) . " GMT";

Page 10: 消息的可缓存性V0 1

Header($expire);

Header("Content-Language: zh-cn");

echo "success";

?>

当用户访问该网页时我们可以传输的信息找到这两个(Expires和Content-Language)HTTP头。

meta是用来在HTML文档中模拟HTTP协议的响应头报文。meta 标签用于网页的<head>与</head>中,meta 的属性有两种:name和HTTP-equiv。name属性主要用于描述网页,以便于搜索引擎机器人查找、分类。HTTP-equiv顾名思义,相当于HTTP的文件头作用,它可以向浏览器传回一些有用的信息,以帮助正确和精确地显示网页内容,与之对应的属性值为 content,content中的内容其实就是各个参数的变量值。

meat标签的HTTP-equiv属性语法格式是:<meta HTTP-equiv="参数" content="参数变量值"> ;其中HTTP-equiv属性主要有以下几种参数:

A、Expires(期限)

说明:可以用于设定网页的到期时间。一旦网页过期,必须到服务器上重新传输。

用法:<meta HTTP-equiv="expires" content="Fri, 12 Jan 2001 18:18:18 GMT">

注意:必须使用GMT的时间格式。

B、Pragma(cache模式)

说明:禁止浏览器从本地计算机的缓存中访问页面内容。

用法:<meta HTTP-equiv="Pragma" content="no-cache">

注意:这样设定,访问者将无法脱机浏览。

C、Refresh(刷新)

说明:自动刷新并指向新页面。

用法:<meta HTTP-equiv="Refresh" content="2;URL=HTTP://www.webjx.com">

注意:其中的 2是指停留 2秒钟后自动刷新到URL网址。

D、Set-Cookie(cookie设定)

说明:如果网页过期,那么存盘的 cookie将被删除。

用法:<meta HTTP-equiv="Set-Cookie" content="cookievalue=xxx; expires=Friday, 12-Jan-2001

18:18:18 GMT; path=/">

注意:必须使用GMT的时间格式。

E、Window-target(显示窗口的设定)

说明:强制页面在当前窗口以独立页面显示。

用法:<meta HTTP-equiv="Window-target" content="_top">

注意:用来防止别人在框架里调用自己的页面。

F、content-Type(显示字符集的设定)

说明:设定页面使用的字符集。

Page 11: 消息的可缓存性V0 1

用法:<meta HTTP-equiv="content-Type" content="text/html; charset=gb2312">

我们在 index.htm中的<header>中加入了:

<meta HTTP-equiv="Expires" content="Wed, 24 Jun 2009 09:19:31 GMT\r\n"/>

但是用户访问网页时返回的 response的HTTP header中找不到 Expires。

接下来,介绍一下 heuristic expiration time的计算方法。

而 freshness_lifetime计算方法如下:

如果存在 cache-control的max-age(或者 s-maxage)值,则:freshness_lifetime = max_age_value

否则如果存在 Expires值,则:freshness_lifetime = expires_value - date_value

如果上述两个值都不存在,而且响应中也没有包含其他的限制条件时,cache服务器可以使用一种启发式规则来计算获得 freshness_lifetime(如果计算得到的 freshness_lifetime大于 24小时并且年龄值也超过 24

小时则必须在 response响应中增加warning 113),但响应中包含有 Last-Modified值时,原则上freshness_lifetime不应该超过从 Last-Modified到现在经过的时间值的一定比例(比如:10%)。这个计算freshness_lifetime启发式规则是由 cache服务器自己制定的。比如,squid的启发式规则主要是由用户制定的refresh_pattern规则指定。

3.3.3 过期或者保鲜

当 age值和 freshness_lifetime都得到了以后,计算一个响应是否过期就简单了:

response_is_fresh = (freshness_lifetime > current_age)

3.4 Validation验证

在HTTP1.1中对缓存进一步提出了验证的概念。验证的目的就是检验缓存项目是否在有效期内。当cache服务器存在一个过期的消息,并且对应的 request请求到达时,它应该首先向服务器或者链路上的其他保存有未过期的 cache服务器请求验证来确定本地的 response是否可用。这个过程就是一个 cache消息的验证过程。HTTP 1.1提供了有条件的请求返回方法(conditional methods),这样当本地 response是可用时就可以减少网络流量不用传输整个 response的信息,而当本地 response不可用时也可以减少链路上请求多一个来回的消耗。当源服务器生成了一个完整的 response时,它会附带一个验证子(validator);cache服务器可以保存它,在 response过期以后,可以利用它生成一个有条件的 request以向源服务器请求验证。而服务器(源服务器或者链路上保存有未过期的 cache服务器)收到这样的请求以后就可以用它与自己的validator比较,如果相等,那么只返回一个带有特定状态码(通常是:304 Not Modified),并且消息主体为空的 response,在这种情况下就减少了网络流量;如果两个 validator不相等就传输一个完整的 response,在这种情况下避免了客户端再次提交 request,从而减少了一次通讯往返。事实上,所谓的有条件的 request

和普通的 request是一样的,只是它包含了一个特殊的Header和 validator。并且有条件的验证包括正验证和负验证,如果 request中要求服务器与附带的 validator必须相等的是正验证,如果要求两者不相等的是指负验证。

validator主要包括 Last-Modified Dates和 Entity Tag Cache Validators两种,分别对应了"Last-

Modified"和"ETag"两个Header。当一个 response在"Last-Modified"之后没有被修改过可以认为它是有效的。它是被经常用来验证一个 response是否有效的 validator。它对应的对应的 request请求头包括:"If-Modified-

Since","If-Unmodified-Since"。但是,"Last-Modified"是有缺陷的,因为HTTP协议的时间值是以秒为单位的,

Page 12: 消息的可缓存性V0 1

如果一个 response在一秒内被修改了两次,那么验证某个 response是否一致就没有办法了。所以在这种情况下或者源服务器希望避免使用时间的修改来匹配两个数据时,就可以用"ETag"。"ETag"可以由源服务器指定计算方法,根据 response生成,它是一个不透明的 validator。对应的 request请求头包括:"If-Match","If-

None-Match","If-Range"。

两个 validator之间的比较可以分为强验证子比较或者弱验证子比较。强验证子比较表示每一个字节都要相等,而弱验证子比较主要是指实体相等,可以在不明显改变语义的基础上相互替换。弱验证子比较仅仅用于在弱验证子上的比较,比如:在 Entity Tag前面有"W/"则表示这是一个弱 validator。一个实体的修改时间可以被认为是弱验证子。弱验证子可以应用于不要求精确一致的情况下,强验证子比较应用比较广泛,几乎所有的场合都可以用。如果用户提交的 request只需要 response的一部分(sub-range)那么必须要保证使用强验证以获得正确的数据。

Page 13: 消息的可缓存性V0 1

4 其他建议

4.1 进一步工作

了解 apache和 squid的 cache实现以及相关配置,并结合本公司网站以及相关数据部署和测试。加快用户访问速度,提交同时可访问的用户数,加强它们的鲁棒形以及服务可用性。为以后公司的产品和项目提供支持。

另外,研究网页制作者增加缓存头部域需要遵守的规范,为网页制作者有意识的增加缓存,控制缓存时间等提供参考。

Page 14: 消息的可缓存性V0 1

5 相关文档列表

HTTP 1.1

Squid Cache 服务器安装配置与测试数据 squid 服务器用户手册 v0.2