[性能优化系列] 03. 文件缓存

前文介绍了通过gzip减少流量传输,通过设置Cache-Control减少静态资源的请求,本文继续探讨,如何通过缓存的方式,减少对数据库的压力,从而提升页面响应时间。 ##动态页面性能损耗分析 以Typecho为例(大部分的cms类站点都是类似的架构),用户的http请求,从`index.php`进入web服务,然后PHP代码加载各种组件,接着路由到具体的action或者controller,并在...

前文介绍了通过gzip减少流量传输,通过设置Cache-Control减少静态资源的请求,本文继续探讨,如何通过缓存的方式,减少对数据库的压力,从而提升页面响应时间。 ## 动态页面性能损耗分析 以Typecho为例(大部分的cms类站点都是类似的架构),用户的http请求,从`index.php`进入web服务,然后PHP代码加载各种组件,接着路由到具体的action或者controller,并在controller中加载model,查询数据库,组装页面,最后渲染模板并输出给浏览器。 ![request_flow.png][1] 但是,对于大多数页面或者post,作者完成创作之后,绝大部分时间都不会再改变的了,但每次请求这个文章(举例,譬如:https://www.typechodev.com/servers/aliyun_coupons.html)的时候,都需要走一次所有流程,并从数据库查询文章内容,明显是不合适的。因此,我们可以在整个网站的入口处做优化,将文章内容缓存起来,下次请求过来时,如果发现有缓存,则直接返回缓存内容,从而减少对后端数据库等的压力,从而提升响应时间和网站并发处理能力。 ## 动手实现自己的缓存逻辑 ####首先我们测试一下启用文件缓存前的接口性能 网上有很多已经做好的文件缓存插件,同学们可以自己去找找。笔者没有用过这类插件,所以没办法给什么建议。不过这种页面缓存技术非常简单,我们也可以自己简单实现一下。 首先我们看一下typecho的入口文件: begin(); /** 开始路由分发 */ Typecho_Router::dispatch(); /** 注册一个结束插件 */ Typecho_Plugin::factory('index.php')->end(); 这个时候,使用`ab -n 1000 -c 100 "https://www.typechodev.com/theme/56.html"`命令进行测试,测试结果: Concurrency Level: 100 Time taken for tests: 27.302 seconds Complete requests: 1000 Failed requests: 994 (Connect: 0, Receive: 0, Length: 994, Exceptions: 0) Total transferred: 28776775 bytes HTML transferred: 28576775 bytes Requests per second: 36.63 [#/sec] (mean) Time per request: 2730.203 [ms] (mean) Time per request: 27.302 [ms] (mean, across all concurrent requests) Transfer rate: 1029.31 [Kbytes/sec] received ####接着我们修改index.php逻辑,增加文件缓存机制 修改后的`index.php`: begin(); /** 开始路由分发 */ Typecho_Router::dispatch(); /** 注册一个结束插件 */ Typecho_Plugin::factory('index.php')->end(); $content = ob_get_contents(); ob_end_clean(); file_put_contents($tmp_file, $content); echo $content; 我们再通过diff看看两者的差异,更清楚看到改动的内容: ![index_diff.png][2] 可见,改动的地方非常少,总括来说就是: 1. 页面开始的地方判断是否有缓存文件,有则直接输出 2. 页面最后将内容缓存起来,以供下次请求使用 同样使用`ab -n 1000 -c 100 "https://www.typechodev.com/theme/56.html"`命令进行测试,结果如下: Concurrency Level: 100 Time taken for tests: 2.658 seconds Complete requests: 1000 Failed requests: 0 Total transferred: 28786000 bytes HTML transferred: 28640000 bytes Requests per second: 376.22 [#/sec] (mean) Time per request: 265.803 [ms] (mean) Time per request: 2.658 [ms] (mean, across all concurrent requests) Transfer rate: 10575.99 [Kbytes/sec] received 缓存前后对比,接口成功率大幅上升(缓存前成功率不到10%,缓存后成功100%),请求平均耗时大幅降低(缓存前平均耗时2730ms,缓存后平均耗时265ms,不到1/10)。 #### 小结 通过上述这种简单的方式,可以10倍提升网站的处理能力。同学们可以自动动手试试。代码能力强的同学,甚至可以加各种缓存策略,进一步优化缓存效果,这个就看自己需求了。 [1]: https://www.typechodev.com/usr/uploads/2017/12/4143749164.png [2]: https://www.typechodev.com/usr/uploads/2017/12/3119693559.png