一. web缓存总分类
-
数据库数据缓存
Web应用,特别是SNS类型的应用,往往关系比较复杂,数据库表繁多,如果频繁进行数据库查询,很容易导致数据库不堪重荷。为了提供查询的性能,会将查询后的数据放到内存中进行缓存,下次查询时,直接从内存缓存直接返回,提供响应效率。比如常用的缓存方案有memcached等。
-
服务器端缓存
-
代理服务器缓存
代理服务器是浏览器和源服务器之间的中间务器,浏览器先向这个中间服务器发起W eb求,经过处理后(比如权限验证,缓存匹配),再将请求转发到源服务器。代理 服务器存的运作原理跟浏览器的运作原理差不多,是规模更大。可以把它理解为一 个共享缓存不只为一个用户服务,一般为大量用户提供务,因此在减少相应时间和 带宽使用方面很效,同一个副本会被重用多次。常见代理服器缓存解决方案有Squid 等,这里不再详述。
-
CDN缓存-CDN缓存策略
CDN边缘节点缓存策略因服务商不同而不同但一般都会遵循http标准协议,通过http 响 应头中的Cache-control:max-age的字段来设置CDN边缘节点数据缓存间。
当客户端向CDN节点请求数据时,CDN节点会断缓存数据是否过期,若缓存数据并没 有 过期,则直接将缓存数据返回给客户端否则,CDN节点就会向源站发出回 源请求(bak to the sourcerequest),从源站拉取最新数据,更新本缓存,并将最新数据返回给 客户端。
CDN服务商一般会提供基于文件后缀、目录个维度来指定CDN缓存时间,为用户提供 更 精细化的缓存管理。
CDN缓存时间会对“回源率”产生直接的影响若CDN缓存时间较短,CDN边缘节点上的数 据 会经常失效,导致频繁回源,增加了源站的载,同时也增大的访问延时;若C DN缓存时 间太长,会带来数据更新时间慢的问题。发者需要增对特定的业务, 来做特定的数据 缓存时间管理。
CDN缓存刷新CDN边缘节点对开发者是透明的相比于浏览器Ctrl+F5的强制刷新来使浏 览 器本地缓存失效,开发者可以通过CDN务商提供的“刷新缓存”接口来达到清 理CDN边 节点缓存的目的。这样开发者在更新数据后可以使用“刷新缓存”功能来强 制CDN节点上 的数据缓存过期,保证客户端在访问,拉取到最新的数据。
-
Combo服务
Combo服务,也就是我们在最终拼接生成页资源引用的时候,并不是生成多个独立的 lin标签,而是将资源地址拼接成一个url路径请求一种线上的动态资源合并服务, 从而实减少HTTP请求的需求。 /??fle1,file2,file3,...的url请求响应就动态combo服务提供的,它的原理很简单 , 就是根据url找到对应的多个文件,合成一个文件来响应请求,并将其缓 存,以加访 问速度。
但它也存在一些缺陷:
浏览器有url长度限制,因此不能无限制的并资源。 如果用户在网站内有公共资源的两个页面间转访问,由于两个页面的combo的url不 一 样导致用户不能利用浏览器缓存来加快公共资源的访问速度。如果combo的 url中任何 一个文件发生改变,都会导致整个url存失效,从而导致浏览器缓存 利用率降低。
-
-
浏览器端缓存
浏览器缓存根据一套与服务器约定的规则进行工作,在同一个会话过程中会检查一次并确定缓存的副本足够新。如果你浏览过程中,比如前进或后退,访问到同一个图片,这些图片可以从浏览器缓存中调出而即时显现。
-
Web应用层缓存
应用层缓存指的是从代码层面上,通过代码逻辑和缓存策略,实现对数据,页面,图片等资源的缓存,可以根据实际情况选择将数据存在文件系统或者内存中,减少数据库查询或者读写瓶颈,提高响应效率。
前端包含浏览器端缓存和Web应用层缓存两部分。
二. http缓存
1. http缓存机制
缓存行为主要由缓存策略决定,而缓存策略由内拥有者设置。这些策略主要通过特定的HTTP头部清晰地表达。
当一个用户发起一个静态资源请求的时候,浏览会通过以下几步来获取资源:
-
本地缓存阶段:先在本地查找该资源,如果有现该资源,而且该资源还没有过期,就使用这一资源,完全不会发送http请求到服务器;
-
协商缓存阶段:如果在本地缓存找到对应的资,但是不知道该资源是否过期或者已经过期,则一个http请求到服务器,然后服务器判断这个请,如果请求的资源在服务器上没有改动过,则返304,让浏览器使用本地找到的那个资源;
-
缓存失败阶段:当服务器发现请求的资源已经修改过,或者这是一个新的请求(在本来没有找到资源),服务器则返回该资源的数据,并且返回200, 当然这个是指找到资源的情况下,如果服务器上没有这个资源,则返回404。
-
用户操作行为与缓存 浏览器中的操作对缓存的影响:
- 强制刷新 – 当按下ctrl+F5来刷新页面的时候, 浏览器将绕过各种缓存(本地缓存和协商缓存), 直接让服务器返回最新的资源;
- 普通刷新 – 当按下F5来刷新页面的时候,浏览器将绕过本地缓蹲来发送请求到服务器, 此时, 协商缓存是有效的
- 回车或转向 – 当在地址栏上输入回车或者按下跳转按钮的时候, 所有缓存都生效
1.1 本地缓存阶段(/强制缓存)
-
Expires指定缓存到期GMT的绝对时间,如果设max-age,max-age就会覆盖expires。如果expire到期需要重新请求。
Expires是HTTP/1.0控制网页缓存的字段,其值为服务器返回该请求结果缓存的到期时间,即再次发起该请求时,如果客户端的时间小于Expires的值时,直接使用缓存结果。
Expires是HTTP/1.0的字段,但是现在浏览器默认使用的是HTTP/1.1,那么在HTTP/1.1中 网页缓存还是否由Expires控制?
到了HTTP/1.1,Expire已经被Cache-Control替代,原因在于Expires控制缓存的原理是 使用客户端的时间与服务端返回的时间做对比,那么如果客户端与服务端的时间因为某 些原因(例如时区不同;客户端和服务端有一方的时间不准确)发生误差,那么强制缓 存则会直接失效,这样的话强制缓存的存在则毫无意义,那么Cache-Control又是如何控 制的呢?
-
Cache-Control
Cache-Control:这个是http 1.1中为了弥补Expires 缺陷新加入的。 对已缓存的内容进行控制:
-
public:表示缓存的版本可以被代理服务器或其他中间服务器识别,所有内容都将被缓 存(客户端和代理服务器都可缓存)。
-
private: 意味着这个文件对不同的用户是不的。只有用户自己的浏览器能够进行缓 存,公共的代理服务器不允许缓,即所有内容只有客户端可以缓存,Cache-Control的默 认取值。
-
no-cache: 客户端缓存内容,但是是否使用缓存则需要经过协商缓存来验证决定意味 着文件的内容不应当被缓存。在搜索或者翻页结果中非 常有用,因为同样的URL,对应的内容会发生变化。
-
max-age:指定缓存过期的相对时间秒数,max-ag=0或是负值,浏览器会在对应的存 中把Expires设置为1970-01-01 08:00:00 。max-age=xxx (xxx isnumeric):缓存内容将在xxx秒后失效。
-
s-maxage:类似于max-age,只用在共享缓存上,比如prxy.
-
public:通常情况下需要http身份验证的情况,响应不可cahce的,加上public可使 它被cache。
-
no-cache:强制浏览器在使用cache拷贝之前先提交一http请求到源服务器进行确。 这对身份验证来说是非常有用的,能比较好的遵守 (可以结合public进行考虑)。它对维持一个资源总是最新的也很有用,与此同时不完全 丧失cache带来的好处),因为它在本地是有拷贝的,但是在用之都进行了确认, 这样ht tp请求并未减少,但可能会减少一个响应体。
-
no-store:告诉浏览器在任何情况下都不要进行cache不在本地保留拷贝。所有内都不 会被缓存,即不使用强制缓存,也不使用协商缓存
-
must-revalidate:强制浏览器严格遵守你设置的cache规则。
-
proxy-revalidate:强制proxy严格遵守你设置的cache规则。
用法举例: Cache-Control: max-age=3600,must-revalidate
cache:使用本地缓存,不发生请求。
-
1.2 协商缓存阶段
-
Last-Modified &if-modified-sinceLast-Modified与If-ModifiedSince是一对报文头,属于http 1.0。 last-modified是WEB服务器认为对象的最后改时间,比如文件的最后修改时间,动态页的最后产生时间。
-
ETag & If-None-MatchETag与If-None-Match一对报文,属于http 1.1。 ETag可以用来解决这种问题。ETag是一个文的唯一标志符。就像一个哈希或者指纹,每文件都有一个单独的标志,只要这个文件发了改变,这个标志就会发生变化。 ETag机制类似于乐观锁机制,如果请求报文ETag与服务器的不一致,则表示该资源已经修改过来,需要发最新的内容给浏览器。 同时使用这两个报文头,在完全匹配If-Modiied-Since和If-None-Match即检查完修改时和Etag之后,如都与服务器的相符,服务器回304,否则,发送最新内容给浏览器。 Etag/lastModified过程如下:
1.客户端请求一个页面(A)。
2.服务器返回页面A,并在给A加上一个Last-odified/ETag。
3.客户端展现该页面,并将页面连同Last-Modified/ETag一起缓存。
4.客户再次请求页面A,并将上次请求时服器返回的Last-Modified/ETag一起传递给服 务器。
5.服务器检查该Last-Modified或ETag,并断出该页面自上次客户端请求之后还未被修 改,直接返回响应304和一个空的响应体。 304:通过If-Modified-Since If-Match判断资源是否修改,如未修改则返304,发生了一次请求,但请求内容长度为 0,节省了带宽。如果有多台负载均衡的服务器,不同服务器算出的可能不同, 这样就会造成资源的重复加载。
Etag 主要为了解决 Last-Modified无法解决的一些问题:
1、一些文件也许会周期性的更改,但是他内容并不改变(仅仅改变的修改时间),这个 时候我们并不希望客户端认为这个文件被修了,而重新GET;
2、某些文件修改非常频繁,比如在秒以下时间内进行修改,(比方说1s内修改了N次) ,If-Modified-Since能检查到的粒度是s的,这种修改无法判断(或者说UNIX记录MTIM E只能精确到秒);
3、某些服务器不能精确的得到文件的最后改时间。
其他标签 Content-Length:尽管并没有在缓存中明确及,Content-Length头部在设置缓存策略 时很重要。某些软件如果不提前获知内的大小以留出足够空间,则会拒绝缓存该内容 。
Vary:缓存系统通常使用请求的主机和路径为存储该资源的键。当判断一个请求是否 是请求同样内容时,Vary头部可以被用提醒缓存系统需要注意另一个附加头部。它通 常被用来告诉缓存系统同样注意Accept-Encding头部,以便缓存系统能够区分压缩和未 压缩的内容。
1.3 理解浏览器的内存和硬盘储存
-
内存缓存(from memorycache):内存缓存具有两个特点,分别是快速读和时效性:
-
快速读取:内存缓存会将编译解析后的文件,直接存入该进程的内存中,占据该进程一定的内存资源,以方便下次运行使用时的快速读取。
-
时效性:一旦该进程关闭,则该进程的内存则会清空。
-
-
硬盘缓存(from disk cache):硬盘缓存则是直接将缓存写入硬盘文件中,读取缓存需要对该缓存存放的硬盘文件进行I/O操作,然后重新解析该缓存内容,读取复杂,速度比内存缓存慢。
在浏览器中,浏览器会在js和图片等文件解析执行后直接存入内存缓存中,那么当刷新页面时只需直接从内存缓存中读取(from memory cache);而css文件则会存入硬盘文件中,所以每次渲染页面都需要从硬盘读取缓存(from disk cache)。
1.4 无法被浏览器缓存的请求
- HTTP信息头中包含Cache-Control:no-cache,pragma:no-cache,或Cache-Control:max-age=0等告诉浏览器不用缓存的请求
- 需要根据Cookie,认证信息等决定输入内容的动态请求是不能被缓存的
- 经过HTTPS安全加密的请求(有人也经过测试发现,ie其实在头部加入Cache-Control:max-age信息,firefox在头部加入Cache-Control:Public之后,能够对HTTPS的资源进行缓存,参考《HTTPS的七个误解》)
- POST请求无法被缓存
- HTTP响应头中不包含Last-Modified/Etag,也不包含Cache-Control/Expires的请求无法被缓存
参考文章
https://imweb.io/topic/55c6f9bac222e3af6ce235b9
https://juejin.im/entry/58ba3302570c350062124f68
http://www.alloyteam.com/2012/03/web-cache-3-how-to-build-cacheable-website/