缓存那些事
首先我画了一个粗糙的图形,用来表示我们使用web请求所经历的过程。大家将就看下 从图可以看出,当用户发起一个网络请求。首先会经过浏览器的缓存,然后经过静态资源的CDN缓存,然后是Nginx等反向代理缓存,再是web缓存,最后还有数据库缓存。下面我们一一来看。 一.Browser Cachehttp协议有自己的缓存协商机制。 对于http1.0 使用的是基于iso-time的 expired响应头去判断资源过期与否。 http1.1使用三种 1.是基于修改精确时间的Last-Modifie
2基于文件相对时间的max-age(这个资源你可以用多久) from cache 是没有和服务器确认,一般是运维去除了e-tag或者说是使用了长缓存 3.基于文件内容hash的 e-tag 另外一方面,可以把缓存分成三种策略,分别是存储策略,协商策略和过期策略。 last-modify,eTag属于协商策略,协商策略用于重新验证缓存资源是否有效, 需要发一次http请求,用于判断当前的缓存资源是否有效。 强缓存只有cache-control(http1.1) 和 pragma(http1.0)的 max-age等策略命中。 也就是说last-modify,eTag 这种协商缓存并不会减少http请求,而是减少了请求时间和字节数。
cache-control 指定缓存机制,需要单独看待,他可以覆盖其他header的值,何解? 语法为:"Cache-Control : cache-directive". Cache-directive共有如下12种(其中请求中指令7种,响应中指令9种):
二.CDN CacheCND是为了不同的网络环境都可以获得一致的高速体验而服务的。将一些静态资源放在cdn可以使用户访问这个静态资源的时候选择网络状态最好的。合理使用cdn可以大大提高访问速度。但是cdn也有很麻烦的地方,就是发布的时候,浏览器缓存可能读取的是旧版本的,这时候传统方法是使用query,但是query也有很多问题,文件发布顺序啥的会影响,而且需要手工加入版本号。 这里推荐webpack build 加hash。 我们目前是使用的webpack 插件 webpack-html-plugin 三.Revert Proxy Cache这里说的是反向代理(我觉得叫服务端代理可能更容易理解)反向代理有保护服务器安全(将外部请求转发给内部服务器,同时将内部服务器响应转发给Client),缓存加速和实现负载均衡的作用。现在我们的站点测试环境使用的是Nginx1.8.x 。而生产环境使用的是淘宝Tengineer 四.web Server Cache我们系统使用的tomcat服务器,所以在这里讲一下tomcat服务器的缓存策略。 tomcat默认是只对静态组员进行缓存对jsp是不缓存的。当前端发送一个请求时,服务端会根据这个资源的特征进行不同的缓存策略。 本质上是存到一个map中,将etag或者last-modified作为value(前面讲浏览器缓存有说过),将资源的url作为一个key存储,当资源发生变化的时候我们去更新这个map的value,当下次资源被请求会比较etag或者last-modified是不是最新的数据,如果是返回304.不是的话返回200和对应内容 tomcat源码中的!checkIfHeaders(request,response,cacheEntry.attributes)) 是整个机制的核心,用来判断资源是否需要重新获取,返回false就重新获取 protected boolean checkIfHeaders(HttpServletRequest request, 这里四个check都返回true(都认为资源被改变了),那么checkIfHeaders久返回true,对应就要重新获取而不走缓存 五.membercache,redis etc在这里使用memcached大大缓解了数据库的读压力,当然对于写还是会造成负担的(更新数据, 需要同时更新数据库和缓存),好在大部分应用都是读远大于写,使用simple spring memcached大大简化了缓存配置,ssm在key生成规则和list缓存上做的很好。有时间我也会进一步了解下。 六.code cache环境:reflux + react 使用react-router-loader实现按需打包加载运用在SPA一定程度解决了单页应用程序性能问题。使用后基本上每个页面初次访问都在200kb~300kb,而且静态资源可以得到缓存。但现在存在一个问题就是用户在多页面切换的时候回发送很多请求。以我的页面为例,每次要发送6个请求。可能就有600-700ms延迟。下图是切换三次页面的网络请求结果 在这里我打算做一次代码缓存,也就说只有第一次加载我从服务器拿,其他时候我是从code cache中拿。 只有用户强制刷新页面才去后台拿数据。 对于get操作首先将cache挂载到store上,这里利用了Store单例的特性,即应用只有一份数据,这样不会出现脏数据的情况,然后get之前判断缓存中有没有,如果有直接返回,否则发送一个网络请求 如果请求成功,并且缓存不存在就添加缓存(第一次请求缓存是不存在的)。如果存在缓存不做处理。 对于update操作直接在请求成功后的回调方法中更新对应缓存。 可以看下效果 博客不可以上传视频,悲哀啊。那就图片吧。 看下优化后的结果: 只有第一次请求会加载6次以后都是不会请求的 参考资料[浏览器缓存机制剖析](https://juejin.im/post/58eacff90ce4630058668257) (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |