最近发现自己学习的东西太杂,不成系统,所以准备整理后再出发。整理也是一种升华。在学习的路上多总结,感觉很好!
这里从缓存开始说起,好久都没有写什么博客了,内容有不对的地方欢迎指正
好像大多问题都能通过加缓存解决,什么叫缓存呢,缓存就是把需要花费昂贵开销的计算结果保存起来,在之后访问直接取出,这个昂贵的开销可以是昂贵的计算,也可以是昂贵的带宽费用等等
从client端出发,首先来说说浏览器缓存,也许从某种角度上看,浏览器也是一个web服务器,也能算一级缓存,内部也存在的各种缓存协商的过程
last-modified
原理
这个从名字上就基本上能了解他是什么呢,最后一次修改时间,
流程图:
第一次访问的时候,web服务端首次返回给client端last-modified最后一次修改时间,然后再一次访问的时候,client请求头中就会以if-modified-since带入最后一次修改时间,用户询问web服务端,在这个时间之后有没有做过修改,如果没有,直接本地返回304状态,如果做了修改,从web服务端直接返回给用户,用户本地保存一份,然后下次已经这一次最后的修改时间为准!这个还是比较好理解!
配置
Apache last-modified是默认开启的
模块为:mod_headers.so
关闭方法
要关掉Last-Modified的方法麻烦点,先想好你要去掉Last-Modified 的标签.然后用header模块来控制
LoadModule headers_module modules/mod_headers.so <FilesMatch "\.(gif|jpg|png)"> Header unset Last-Modified < /FilesMatch>
不足
1、last-modified只能精确到秒,如果在秒内做了修改,是检测不到
2、如果是集群环境的话,相同文件的last-modified可能会不相同的,用户可能要缓存获取两次
3、不管你的内容有没有真正的修改
暂时只知道这几点不足
ETag
原理
ETag:网上的有很正确的理解,我个人的理解是在client端发起访问的时候,web服务端会在返回头中带入资源的ETag值(通过算法对内容进行一个计算得出的一个唯一id)客户端缓存这个资源,然后这个ETag值也会被保存,在再一次请求相同资源的时候,浏览器会把第一次服务端返回过来的值带入请求头中(if-none-match)如果服务端内容没有表换就返回304如果有变化就返回200内容从服务端返回,如果跟last-modified一起使用的话ETag优先级高于last-modified
配置
Apache
apache 默认开启Etag
格式:apache Etag由inode+大小+时间戳
关闭方式:
FileETag None
Header unset ETag
Header unset Last-Modified
nginx默认没有这个模块,需要重新编译进去
不足
1、没有进行实际的测试,感觉如果文件多了,大了,还有如果自己写的算法烂也会影响性能
expires
原理
这个最吊,直接可以不用跟web服务端进行缓存协商,本地协商就能完成,web服务端中返回head中带入过期时间,然后浏览器每一次只需要date与expires进行比较就好,如果过期就去服务端获取,如果没有过期就本地返回!
配置
Apache是通过expires模块实现
格式:
ExpiresActive on
ExpiresByType p_w_picpath/gif “access plus 1 month”
ExpiresByType p_w_picpath/jpg “access plus 1 month”
ExpiresByType p_w_picpath/jpeg “access plus 1 month”
。。。。。
nginx上面默认有的并开启状态
格式:
location ~ .*\.(js|css)?$
{
expires 1h;
}
不足:
1、expires受服务端跟client端时间影响,如果客户端时间如果慢了还是快了都会影响缓存的有效行,而客户端时间这种不可控的信息我们不能去实现时间一致
因为expires的不足,cache-control出来了
cache-control
原理
cache-control跟expires一样都是说明资源的一个有效时间,而不通的在于是expires是date时间到服务端给出的时间的一个有效时间,cache-control有效时间是client访问web服务端之后开始计算的一个时间内。如果max-ago=60 就是第一次访问后的60后资源过期,这样子就去除了expires依赖client时间的弊端,如果expires与cache-control同时存在,cache-control的优先级高于expires
nginx配置
if ($request_uri ~* "^/$|^arch/.+/|^/company/.+/") {
add_header Cache-Control max-age=3600;
}
if ($request_uri ~* "^arch-suggest/|^/categories/") {
add_header Cache-Control max-age=86400;
}
小注释:
浏览器的三种刷新方式:
使用浏览器的转到按钮、或者在地址栏直接回车、或者打开新窗口重新输入该网址
优先走浏览器本地缓存,如果本地有缓存则根本不会访问服务器
注:如果是chrome下,在本窗口下的地址栏直接回车,html不会走本地缓存,如果是新开窗口在地址栏输入网址回车,则html依然会走本地缓存。估计是chrome的策略,firefox下则都会走本地缓存
使用浏览器的刷新按钮、F5刷新或者是Mac Chrome下的Command + r刷新
不走浏览器本地缓存,不过会走服务端缓存,会返回304
使用浏览器的强制刷新,如Ctrl+ F5或者是Mac Chrome下的Command + Shift + r
既不走浏览器本地缓存,也不走服务端缓存,不返回304
无法被浏览器缓存的请求:
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的请求无法被缓存