三通IT学院 门户 技术频道 服务器 查看内容

2014-7-22 15:12
详解HTTP缓存工作流程

摘要 : HTTP缓存工作流程详解HTTP首部信息request请求首部格式methodurlversionheaders#通常需要跟主题之间有一空白行host:www.test.comAccess-Encoding:gziprsponse起始格式versioncodereasonphressheadersHTTP协议本身是 ...

时光与梦2014-7-22 15:129790

HTTP缓存工作流程详解

HTTP首部信息

request请求首部格式

     method url version

     headers #通常需要跟主题之间有一空白行

          host:www.test.com 

          Access-Encoding:gzip    

rsponse 起始格式

     <version> <code> <reasonphress>

     <headers>

HTTP协议本身是无状态的,必须要基于tcp协议进行工作,无状态导致了每个资源的请求

    比如:每个页面包含了很多图片的资源,每个图片都是一个资源,在一个页面中包含了几十个图片,每个图片都是单独请求的,也可能包含了css或xml等 每个都需要单独请求,也就意味着打开一个页面需要N次的tcp三次握手 四次断开,因此有了keepalive,通过keepalive机制进行长连接,tcp三次握手后可以请求N个资源然后断开,所以这使得了tcp加速其性能的机制

    但是用户的每次访问这个页面包括刷新以后,而后又重新打开,如果每次访问到同一网站某些相同资源的时候,都需要到服务器上去请求,无论对客户端服务器端甚至是带宽等都会是资源浪费,因此要提高用户体验,加速资源访问的效率,我们都应该提供缓存机制

 

private cache (私有缓存)

    用户访问的资源有可能是私有信息,因此可以在用户的浏览器中开辟一私有缓存空间。用户每次访问资源取到以后将其资源存放在浏览器空间里,但是这样只能为单一用户实现加速目的,私有缓存主要目的就是用来缓存私有缓存对某个用户自身访问从而起到加速作用

 

public cache 公用缓存

    面对客户端的是缓存代理,代理可以进行缓存的功能。首先代理能够接收到用户的请求,请求进来后先检索本地是否将请求缓存下来,如果缓存中有数据,那么直接将缓存的数据返回给用户,否则由代理服务器到原始服务器取数据,如果可以缓存,先缓存本地然后响应给客户端。在此同时,其他客户端进来请求,查找本地缓存发现缓存中存在数据则时间返回给用户。

 

那么如何实现让客户端都使用同一缓存

如下所示

public cache 公用缓存

面对客户端的是缓存代理,代理可以进行缓存的功能,首先代理能够接收到用户的请求,请求进来后先检索本地是否将请求缓存下来

如果缓存中有数据,那么直接将缓存的数据返回给用户,否则由代理服务器到原始服务器取数据,如果可以缓存,先缓存本地然后响应给客户端

同时,其他客户端进来请求,查找本地缓存发现缓存中存在数据则时间返回给用户

可以设置二级代理缓存,直接与客户端连接,由二级缓存直接去源站或一级缓存去取数据

首先用户发起请求,先到离自己最近的代理,代理服务器先检索本身缓存,如果存在则直接返回;

如果没有数据,则直接去找另外离自己最近的节点服务器,如果存在则返回如果没有则到源站找数据;

那么这时源站的前端也有缓存服务器,如果缓存中有则直接返回,如果没有数据则去查询后端服务器,最后缓存本地返回结果

 

但问题是如何保证不同的客户端访问的是不同的服务器

可以对其做智能DNS,域名都是同样的,域名解析的时候能够判断用户的来源(view),如果来源是同一区域的解析的固然是这个域名则返回的是离客户最近的服务器的地址,而不是原始服务器地址

同样的其他组返回的是离最近的服务器地址,那从而这么几个缓存本身之间可以共享缓存的话那么效果会更好

 

首先,第一组服务端发现没有数据则去取数据,缓存后而后第二个服务端去请求离它最近的服务端,而后发现没有但是这个服务器发现它去访问另外一个与它对等的服务器的速度比较快,而源站的服务器较慢,如果在较快的缓存服务器取得数据会更快,而这些缓存服务器的关系是对等的,这样我们可以成为源站的代理为一级代理,其他为二级代理

那么所有的二级代理的层次都是一样的,被称为兄弟服务器(sibling server)

 

这些兄弟服务器之间是完全可以共享缓存对象的

而且只要跟缓存服务器本身定制好策略,它也会知道哪个服务器最近、哪个代价最大、哪个服务器最快等

这样的网络被称为CDN

 

 

缓存命中率

缓存命中率计算方式:请求总次数 和 缓存服务器上的缓存次数 对比 即可

命中率越高就说明缓存服务器的返回比例越高,命中率越高越好

如果前端服务器命中率在70% 而在源站代理服务器命中率在90% 那么缓存服务器还能接收多少个请求:

大多数的事情都能在代理上解决 ,到原始服务器的流量就可能很小了,

 

缓存的失效

毕竟缓存不是权威的,比如图片删除 文章删除等

但如果说此前的缓存的对象已经被缓存下来,而后在源站已经将资源删除了,情况很常见

那么这时候需要设置缓存时间周期

 

作为缓存服务器来讲,静态内容可以缓存,动态内容也可以缓存,但是有些动态内容不能永久缓存也不应该永久缓存

比如:

在论坛发布一篇帖子,帖子下面有两个回复,用户刷新后可能出现10个回复,这种内容就不能长久缓存,但是原始帖子本身倒是可以缓存,那么就会出现这种结果:

·有些内容可缓存,而有些不能缓存;

·有些内容可以缓存几分钟,而有些内容可以缓存很长时间;

 

所以作为web对象来讲,因为一个web页面有多个对象的组成的从而根据对象的生成的工作原理不一样,那么它的缓存的时间也不一样的

当客户端请求的时候就算没有共享缓存服务器,那也必须控制缓存时长的

当客户端请求的时候就算没有公共缓存服务器,也必须控制缓存机制的,因为客户端浏览器也是有缓存的,所以缓存几乎在web服务上是恒久存在的

 

服务器端如果是动态页面的话,那么每个页面生成的时候,可以自行控制它的缓存时长,通过http首部告诉客户端如何进行缓存

在http1.0 也支持缓存,只不过缓存首部非常粗糙

http 1.1 极大增强了缓存能力的,增加了很多可以灵活控制缓存的机制

http 1.1在缓存服务器上尽管服务器告知浏览器可以缓存多久,但公用服务器应该缓存其数据

作为管理人员来讲必须去定制缓存策略,不应该遵循源站给出的策略

 

条件式请求首部

if-modified-since

服务器将缓存文件的缓存时间与请求本地时间戳比较后,如果发现没有改认为此资源可以继续使用,而且不用再次通知客户端被称为 not-modified

所以not- modified的响应码是304 只要客户端收到304响应码就认为没有改变,那么它的缓存将会继续使用,由于发一次新请求就意味着页面缓存时长又可以继续使用

如果资源在设置时长周期内更改了资源,那么客户端则不会知道其已经过期,会仍然用之前的数据使用的,这就是非条件式的劣势了

有了条件式请求,那么我们每次都可以发起新请求,服务器也不用响应内容只告知我们是否更改即可,所以这种情况下对服务器带宽占用量是非常小

因此尽可能得到比较新的结果

 

因此我们如果使用expires(HTTP1.0较弱的缓存控制机制)还有一些缺陷,比如:

有些服务器时间是不一致的,所有的结果都是根据本地的时间返回的,所以用这种计时法也不是非常靠谱

所以在http1.1中又引入一个新的机制,为cache-cotrol

 

cache-cotrol

其有了一个新的机制为max-age,最大缓存时长,这就是一个相对计时方法

所以是说http 1.1对缓存功能做了极大的改进,就算具备了条件式请求功能,if modified since

但有些网站内容的修改频度非常高,因为有些内容是动态生成的 以毫秒级别来管理

第一次请求给了时间戳,第二次请求虽然内容改了 但是最近一次修改时间戳没有变

例:

假如目前时间是10:00:00

但是出于第1毫秒上,请求的页面,其将页面返回给我们,他们将页面最近一次修改时间10:10:00 返回给我们的资源,到10:10:10 又去请求此资源,那么他的时间戳还是10:00:00 

这时我们去请求,首先询问服务器:在10:00:00后是否被修改,服务器端虽然修改了资源但是会对比时间戳,发现时间戳没有改变,那么直接返回响应代码,但实际上资源已经改变了

如果对于某些频度变化非常高的站点来讲,有可能不适用的

那http1.1又引入了一个新的机制叫Etag

 

Etag

一旦时间发送改变,则etag也随之发生改变,当客户端请求的时候不再去对比时间戳,而是询问egtag标签是否对应

如果对应则返回not-modified

如果不对应则返回新的数据,所以新的客户端请求用的是新的首部

 

最常用的请求首部

Not-modified/If-modfied-since

Etag/If-none-match

都是缓存中要用到的跟缓存相关的http首部信息,除此之外,尤其是第一组Not-modified/If-modfied-since用到是最多的

 

 

缓存相关的http首部

HTTP协议提供了多个首部用以实现页面缓存及缓存失效的相关功能,这其中最常用的有:
(1)Expires:用于指定某web对象的过期日期/时间,通常为GMT格式;一般不应该将此设定的未来过长的时间,一年的长度对大多场景来说足矣;其常用于为纯静态内容如JavaScripts样式表或图片指定缓存周期;

(2)Cache-Control:用于定义所有的缓存机制都必须遵循的缓存指示,这些指示是一些特定的指令,包括public、private、no-cache(表示可以存储,但在重新验正其有效性之前不能用于响应客户端请求)、no-store、max-age、s-maxage以及must-revalidate等;Cache-Control中设定的时间会覆盖Expires中指定的时间;


(3)Etag:响应首部,用于在响应报文中为某web资源定义版本标识符;

(4)Last-Mofified:响应首部,用于回应客户端关于Last-Modified-Since或If-None-Match首部的请求,以通知客户端其请求的web对象最近的修改时间;

(5)If-Modified-Since:条件式请求首部,如果在此首部指定的时间后其请求的web内容发生了更改,则服务器响应更改后的内容,否则,则响应304(not modified);


鲜花

握手

雷人

路过

鸡蛋
收藏 分享 邀请

最新评论