·您现在的位置: 云翼网络 >> 文章中心 >> 网站建设 >> 网站建设问答 >> 杨建:网站加速--Cache为王篇

杨建:网站加速--Cache为王篇

作者:佚名      网站建设问答编辑:admin      更新时间:2022-07-23

提升性能的同时为你节约10倍以上成本。

一.Cache,王道也

我觉得系统架构不应该仅仅是搭建一个强硬的能承受巨大并发压力的后台,前端页面也是需要架构的而且同等重要,不理解前台的的后台工程师是不合格的。中国人讲究钢柔相济,后台强硬只能说你内功深厚,前端用的巧,那叫四两拨千斤。

一般后台工程师很少关心前端如何使用自己的资源,而前端工程师,不知道自己的一个简单的用法会对后端造成多大影响。我会给出一些数据,来震撼下你的眼球。

二.Cache 基本原理介绍 (参考Caching Tutorial)

为什么使用Cache?

1.减少延迟,让你的网站更快,提高用户体验。

2.避免网络拥塞,减少请求量,减少输出带宽。

补充一个cache的原则:不更新的资源就不应该让它再次产生HTTP请求,如果强制产生了请求,那么就看看能否返回304。

Cache的种类?

浏览器Cache,代理Cache,网关Cache。

后端还有 disk cache ,server cache,php cache,不过不属于我们今天讨论范围。

Cache如何工作的?

1.如果响应头告诉cache别缓存它,cache不对它做缓存;

2.如果请求需要验证的或者是需要安全性的,它将不被缓存;

3.如果响应头里没有ETag或Last-Modifed header这类元素,而且也没有任何显式的信息告诉如何对数据保鲜,则它被认为不可缓存。

4.在下面情况下,一个缓存项被认为是新鲜的(即,不需到原server上检查就可直接发送给client):

它设置了一个过期时间或age-controlling响应头,而且现在仍未过期。

如果浏览器cache里有某个数据项,并且被被设置为每个会话(session)过程中只检查一次;

如果一个代理cache里能找个某个数据项,并且它是在相对较长时间之前更新过的。

以上情况会认为数据是新鲜的,就直接走cache,不再查询源server。

5.如果有一项过期了,它将会让原server去更新它,或者告诉cache这个拷贝是否还是可用的。

怎么控制你的Cache?

Meta tags :在html页面中指定,这个方法只被少数浏览器支持,Proxy一般不会读你html的具体内容然后再做cache决策的。

Pragma: no-cache : 一般被大家误用在http响应头中,这不会产生任何效果。而实际它仅仅应该用在请求头中。 不过google的Server: GFE/1.3 响应中却这样用,难道人家也误用了呢。

Date: 当前主机GMT时间。

Last-Modified : 文件更新GMT时间,我在响应头中带上这个元素的时候,通常浏览器在cache时间内再发请求都会稍带上If-Modified-Since,让我们判断需要重新传输文件内容,还是仅仅返回个304告诉浏览器资源还没更新,需要缓存策略的服务器肯定都得支持的。有了这个请求,head请求在基本没太多用处了,除非在telnet上调试还能用上。

If-Modified-Since : 用在请求头里,见Last-Modified 。

Etag: 标识资源是否发生变化,etag的生成算法各是各样,通常是用文件的inode+size+LastModified进行Hash后得到的,可以根据应用选择适合自己的。Last-Modified 只能精确到秒的更新,如果一秒内做了多次更新,etag就能派上用场。貌似大家很少有这样精确的需求,浪费了http header的字节数,建议不要使用。

更正:Etag 其实在某种情况下可以很好的减少数据传输。在stonehuang的提醒下我才恍然大悟,转眼好几个月了也一直忘记更新。Etag应用场景。比如,数据为php的动态输出。每次请求把上一次Etag带来,跟本次计算的Etag进行比较,相等就可以避免一次数据传输。(最后修改时间 2009.12.07)

Expires : 指定缓存到期GMT的绝对时间,这个是http 1.0里就有的。 这个元素有些缺点,一,服务器和浏览器端时间不一致时会有问题。 二,一旦失效后如果忘记重新设置新的过期时间会导致cache失效。三,服务器端需要根据当前Date时间 + 应该cache的相对时间去计算这个值,需要cpu开销。 我不推荐使用。

Cache-Control:

这个是http 1.1中为了弥补 Expires 缺陷新加入的,现在不支持http 1.1的浏览器已经很少了。

max-age: 指定缓存过期的相对时间秒数,max-ag=0或者是负值,浏览器会在对应的缓存中把Expires设置为1970-01-01 08:00:00 ,虽然语义不够透明,但却是我最推荐使用的。

s-maxage: 类似于max-age,只用在共享缓存上,比如proxy.

public: 通常情况下需要http身份验证的情况,响应是不可cahce的,加上public可以使它被cache。

no-cache: 强制浏览器在使用cache拷贝之前先提交一个http请求到源服务器进行确认。这对身份验证来说是非常有用的,能比较好的遵守 (可以结合public进行考虑)。它对维持一个资源总是最新的也很有用,与此同时还不完全丧失cache带来的好处,因为它在本地是有拷贝的,但是在用之前都进行了确认,这样http请求并未减少,但可能会减少一个响应体。

no-store: 告诉浏览器在任何情况下都不要进行cache,不在本地保留拷贝。

must-revalidate: 强制浏览器严格遵守你设置的cache规则。

proxy-revalidate: 强制proxy严格遵守你设置的cache规则。

用法举例: Cache-Control: max-age=3600, must-revalidate

其他一些使用cache需要注意的东西,不要使用post,不要使用ssl,因为他们不可被cache,另外保持url一致。只在必要的地方,通常是动态页面使用cookie,因为coolie很难cache。至于apache如何支持cache和php怎么用header函数设置cache,暂不做介绍,网上资料比较多。

如何设置合理的cache时间 ?

http://image2.sinajs.cn/newchart/min/n/sz000609.gif?1230015976759

拿我分时图举例,我们需要的更新频率是1分钟。但为了每次都拿到最新的资源,我们在后面加了个随机数,这个数在同一秒内的多次刷新都会变化。我们的js虽然能够很好的控制,一分钟只请求一次,但是如果用户点了刷新按纽呢?这样的调用是完全cache无关的,连返回304的机会都没有。

试想,如果很多人通过同一个代理出去的,那么所有的请求都会穿透代理,弄不好被网管封掉了。如果我们做只做一秒的cache,对直接访问源服务器的用户没太多影响,但对于代理服务器来说,他的请求可能会从10000 req/min 减少为 60 req/min ,这是160倍。

对于我们行情图片这样的情况,刷新频率为1分钟,比较好的做法是把后面的随机数(num)修改为 num=t-t%60 其中t是当前时间戳 ,这样你一分钟内刷这个url是不变的,下一分钟会增加1,会再次产生一个新请求。而我的max-age设置为默认59秒,即使设置120秒其实也没什么影响。可能你会说万一赶上临界点可能拿不到最新的数据,其实对用户来说,用那个多变的随即数和我这个分钟级的随即数,看到的效果是相同的下面我给你分析一下: 如果用户打开了我们的分时间页面,当前随即数对他来说是新的,所以他会拿到一个当前最新的图片,然后他点了刷新按纽,用户会产生http请求,即使url没变,服务器有最新图片也一定会返回,否则返回304,一分钟后js刷新图片,分钟数加了1,会得到全新资源。这和那个随时变化的随即数效果有区别吗?都拿到了最新的数据,但是却另外收益了cache带来的好处,对后端减少很多压力。