`

[转]如何分离个人信息,缓存动态页面

 
阅读更多

如何分离个人信息,缓存动态页面


肖理达 (KrazyNio AT hotmail.com), 2005.06.07, 转载请注明出处

一直想写一篇关于动态页面 cache 的文章,但每次“提笔”却又放弃,因为总是觉得准备得还不够充分。今天埋头写下,只是希望对自己的工作做一些笔录。

1、问题起源

我们经常会在一个动态页面中加入很多个人信息,以 CMS 首页为例,用户登录之前显示登录框,登录之后显示其用户名,并根据权限显示其可用模块的链接。由于每个用户登录之后,显示出来的动态信息都是不一样的,所以这部分无法进行 cache,我们将这部分信息定义为“个人信息”,它的特性是根据登录用户进行动态改变。

现在问题来了,就是一个 CMS 的首页,访问者的登录概率并不是百分百的,应该说有一大部分人访问首页是没有登录的,这个时候的首页是一个公共的页面,没有任何个人信息,或者说这时候首页的任何动态信息都是可以转换成静态的,也就是说这部分是可 cache 的。

2、使用 JavaScript 分离个人信息

解决这个问题的方法有很多种,一种是将个人信息和其他信息进行分离,如在 CMS 首页中加入一个外部的 JavaScript 文件,而这个文件的内容实际上是由 PHP 动态生成的。CMS 首页 index.php 代码片段:
<script language="JavaScript" src="/js/personal.php"></script>
....
<script language="JavaScript">
document.write(sUser);
document.write(sLinks);
</script>

personal.php 代码片段:
<?php
session_start();
header("Cache-Control: no-store, no-cache, must-revalidate");
?>
sUser = "<?php echo $_SESSION['USER']; ?>";
sLinks = "<?php echo addslashes($_SESSION['LINKS']); ?>";

这种方法比较适合个人信息较少,易于集中显示的情况。通过 JavaScript 外挂代码实现个人信息分离之后,personal.php 是永不 cache 的,这样也就可以放心地对 CMS 首页进行 cache 了,具体的 cache 方法可采用 304 HTTP 头与 Cache_Lite 相结合的方式,这在后边有详细代码示例。

3、选择性分离个人信息

一旦个人信息较多,很难对其进行分离的时候,上述方法实现起来就会比较麻烦了。接下来介绍一种比较放宽的 cache 方式,就是只对用户未登录的 CMS 首页进行 cache,一旦发现用户处于登录状态,则跳过 cache 部分,直接运行相关代码,我把这种方法称为“选择性 cache”。这种方法中,我们牺牲了一部分可 cache 的情况,但很大程度上提高了个人信息的可扩充性,也就是说个人信息的多少、显示的位置等等都不再受到限制,这是值得的,毕竟修改服务端代码要比修改大量的 JavaScript 代码要来得方便,而且 JavaScript 的调试也会比较麻烦。

分析一下这种 cache 方式,概要流程图如下:

image

代码片段如下:
<?php
session_cache_limiter("must-revalidate"); 
session_start();
if (empty($_SESSION['USER'])) { //未登录时才使用 cache
    ....    //输出 cache
} else {
    //  直接输出页面内容,此条件下与未使用 cache 时一样
    $data =& get_data();
    echo $data;
}   //end if 
?>

这里需要说明的一点是,由于 PHP 在使用 SESSION 时,php.ini 中默认设置的 session.cache_limiter 为 nocache,所以需要修改 cache_limiter,设置成 must-revalidate,使得客户端再次浏览当前页时必须发送相关 HTTP 头信息到服务器进行验证,然后才决定是否加载客户端本地 cache。不要把客户端本地 cache 与服务器端 cache 搞混,之后的代码片段中会充分利用客户端 cache 和 服务器端 cache 机制达到缓存的目的。关于 must-revalidate,请参考 HTTP 规格说明书 RFC 2612 的 14.9.4 章节

上边的代码并不完整,接下来是更加深入的探讨客户端 cache 机制了,利用客户端 cache,可以有效地减轻服务器端负载。首先了解一下 HTTP 头:Last-Modified 与 If-Modified-Since。简单的说,Last-Modified 与If-Modified-Since 都是用于记录页面最后修改时间的 HTTP 头信息,只是 Last-Modified 是由服务器往客户端发送的 HTTP 头,而 If-Modified-Since 则是由客户端往服务器发送的头,其工作原理图如下:
image
可以看到,再次请求本地存在的 cache 页面时,客户端会通过 If-Modified-Since 头将先前服务器端发过来的 Last-Modified 最后修改时间戳发送回去,这是为了让服务器端进行验证,通过这个时间戳判断客户端的页面是否是最新的,如果不是最新的,则返回新的内容,如果是最新的,则返回 304 告诉客户端其本地 cache 的页面是最新的,于是客户端就可以直接从本地加载页面了,这样在网络上传输的数据就会大大减少,同时也减轻了服务器的负担。想要详细查看 HTTP 头信息,可以在 Firefox 中安装 LiveHTTPHeaders 插件,安装完成之后按 Alt+L 就可以在 Sidebar 中看到了。

现在再来完善之前的 index.php 代码:
<?php
session_cache_limiter("must-revalidate"); 
session_start();

function &get_data()
{
    //此函数用于获取本页面的输出内容
    //....
}   //end function

if (empty($_SESSION['USER'])) { //未登录时才使用 cache
    //====================================================
    //  1. 检查 HTTP 头是否符合 304 的条件
    //====================================================
    //get_last_modified() 函数需要另外单独实现,此函数用于获取服务器端 cache 文件的最后修改时间,可将时间戳保存在数据库中。
    $last_modified = get_last_modified();
    $headers = getallheaders();
    if (strtotime($headers['If-Modified-Since']) == $last_modified) {
        //  返回 304 并结束程序运行
        header('HTTP/1.1 304 Not Modified');
        exit;
    }   //end if
    header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $last_modified) . ' GMT');
    //====================================================
    //  2. 检查 cache 文件是否存在
    //====================================================  
    require_once 'Cache/Lite.php';
    //  参数设置
    $options = array(
        'cacheDir' => './cache/',
        'lifeTime' => 86400, //最大 cache 一天时间
        'fileNameProtection'   => false //使用 CMS 自身提供的 id 作为名字
    );
    $cache = new Cache_Lite($options);  //创建 Cache_Lite 对象
    $id = md5($_SERVER['REQUEST_URI']); //生成对应于 cache 文件的 ID
    if ($data = $cache->get($id)) {   //存在 cache 文件,获取内容,直接输出
        echo $data;
    } else {
        $data =& get_data();
        echo $data;
        flush();
        $cache->save($data);    //保存 cache
    }   //end if
} else {
    $data =& get_data();
    echo $data;
}   //end if
?> 

测试时可以使用 LivHTTPHeaders 插件,你将会看到第一次访问时是返回 200,第二次到第N次访问时则返回了 304,而登录之后,则一直都返回 200,因为我们选择性 cache 之后,对登录之后一律运行程序输出,而不使用 cache,如果之后需要对输出的个人信息进行修改,只需要改函数 get_data() 即可,也避免了 JavaScript 的调试。

总结

除此之外,还有其它方法可以实现分离个人信息,缓存动态页面的目的。而且为了提高服务器运行效率,还可以使用数据库 cache、Squid 反向代理等,如 ADOdb 的 cache。目前用的比较多的 Drupal 应用的就是本文中提到的第二种方法。

参考资料

HTTP Caching & Cache-Busting for Content Publishers
Hypertext Transfer Protocol -- HTTP/1.1
PHP Anthology, Volume 2: Applications. Chapter 5: Caching
Caching Tutorial for Web Authors and Webmasters
Drupal 源代码
分享到:
评论

相关推荐

    基于J2EE框架的个人博客系统项目毕业设计论文(源码和论文)

    可以在管理页面上添加博文的分类,可以上传图片和游览自己的相册,在上传过程中可以将一张图片定义为自己的签名,在个人管理页面中注册用户还可以修改自己的个人信息。博文管理,友情链接管理及博文分类管理,用例图...

    Java项目源码之网上购物系统的实现(JavaBean+Servlet+jsp).zip

    页面缓存:利用页面缓存技术提高页面加载速度,减轻服务器压力。 网上购物系统的实现旨在为用户提供便捷、安全的在线购物体验,帮助用户方便快捷地浏览和购买商品,同时为管理员提供有效的商品管理和订单处理功能,...

    烟雨逍遥个人blog系统 v2.1.1.rar

    2、使用active dll组件服务器组件技术 3、系统对任何页面提交的数据进行严格的格式验证,sql注入无从下手 4、文章的tag使用,使得相关联的文章浏览更方便 5、使用缓存技术,减少页面时间及服务器的负重 6、支持wap...

    烟雨个人博文系统 Build 2.1.1.rar

     5、使用缓存技术,减少页面时间及服务器的负重  6、支持wap访问  7、支持多站多目录使用,各系统直接不相关联  8、支持rss订阅  9、后台密码使用MD5加密算法  10、支持access、mssql数据库  11、导航...

    KooCMS网站内容管理系统 v1.2.9.12.zip

    KooCMS同时支持动态页页和生成静态页面,并可以随时在两者之间进行切换,对于动态页面,KooCMS内置支持伪静态。 4、灵活的插件机制。 KooCMS内置支持插件的开发,只需要将模板页面放到插件目录,系统会自动将此...

    基于SpringBoot+Mybatis+SpringSecurity+Redis+ElasticSe的个人博客系统(源码)

    使用Spring Data集成全文搜索搜索引擎ElasticSearch,实现文章信息的快速搜索和关键字的高亮显示。 前台前端使用HTTP客户端Axios进行异步请求,使用Vue完成数据的绑定和渲染,实现前后端的半分离。 前台静态页面来自...

    Java毕业设计-基于springboot开发的JS个人云盘管理系统设计与实现-毕业论文(附毕设源代码).rar

    该系统采用前后端分离的开发模式,前端使用JavaScript进行页面渲染与交互,后端基于Spring Boot框架搭建RESTful API,实现文件上传、下载、删除、预览等功能。在系统设计上,充分考虑了用户体验与数据安全性,采用了...

    geek_blog-front-v2.zip

    个人博客系统说明 项目介绍 使用当前流行的框架组合SpringBoot+Mybatis,同时整合MybatisPlus插件取代常用的CRUD,简化开发。 基于RBAC模型构建权限管理模块,并集成安全框架SpringSecurity,实现用户的认证和授权...

    基于SSM+Vue的基于web的邮票鉴赏系统及实现(源码+部署说明+系统介绍+源码解释).zip

    在实现过程中,我们使用了MySQL数据库来存储用户信息、商品信息、订单信息等数据,并采用了Redis缓存来提高系统的性能。同时,我们还使用了支付宝接口来进行支付功能的开发。 总体来说,基于SSM+Vue的邮票鉴赏系统...

    基于SSM+Vue的健身国际俱(源码+部署说明+系统介绍+源码解释).zip

    在实现过程中,我们使用了MySQL数据库来存储用户信息、健身课程信息、会员卡信息等数据,并采用了Redis缓存来提高系统的性能。同时,我们还集成了支付宝接口来进行支付功能的开发。 总体来说,基于SSM+Vue的健身...

    工程硕士学位论文 基于Android+HTML5的移动Web项目高效开发探究

    6.4.3 个人信息模块 39 6.4.4页面自适应 40 6.5 本章小结 41 第七章 总结与展望 43 7.1 工作总结 43 7.2 研究展望 44 致谢 47 参考文献 49 第一章 绪论 1.1 研究背景与意义 目前市场业务中在产品以及其他项目的...

    ASP个人网站建设设计(源代码+thesis).zip

    缓存管理:为了提高应用程序的性能,我们将使用ASP.NET提供的缓存机制来缓存常用的数据和页面。这将减少对数据库和服务器的访问次数,提高应用程序的响应速度和吞吐量。 异步编程:我们将使用ASP.NET提供的异步编程...

    毕业设计基于Springboot+Vue高校学生社团管理系统源码+sql数据库+项目说明.zip

    技术栈: Springboot+vue前后端分离技术,spring security角色权限安全框架,redis缓存用户访问令牌!前台基于vue设计,使用了elementui组件。 ## 具体要求: 页面要求: 首页:图片轮播(5张图片),社团列表的...

    淘宝天猫电商商城 SpringBoot 基于前后端分离+源代码+文档说明

    SPRINGBOOT天猫整站,基于 前后端分离思想, 由于该商城高并发的特点,后端框架便使用了方便维护的 SpringM VC、SpringBoot框架,而前端框架则选择了主流的BootStrap、Vue.js,JQuery三大前端框架,页面使用...

    ASP基于BS架构个人网站毕业设计(源代码+thesis).zip

    缓存管理:为了提高应用程序的性能,我们将使用ASP.NET提供的缓存机制来缓存常用的数据和页面。这将减少对数据库和服务器的访问次数,提高应用程序的响应速度和吞吐量。 异步编程:我们将使用ASP.NET提供的异步编程...

    ASP个人日志系统的设计与实现(源代码+thesis).zip

    缓存管理:为了提高应用程序的性能,我们将使用ASP.NET提供的缓存机制来缓存常用的数据和页面。这将减少对数据库和服务器的访问次数,提高应用程序的响应速度和吞吐量。 异步编程:我们将使用ASP.NET提供的异步编程...

    ASP基于WEB个人博客网页设计(源代码+thesis+reply).zip

    缓存管理:为了提高应用程序的性能,我们将使用ASP.NET提供的缓存机制来缓存常用的数据和页面。这将减少对数据库和服务器的访问次数,提高应用程序的响应速度和吞吐量。 异步编程:我们将使用ASP.NET提供的异步编程...

    烟雨逍遥个人blog系统 v2.1.1

    5、使用缓存技术,减少页面时间及服务器的负重 6、支持wap访问 7、支持多站多目录使用,各系统直接不相关联 8、支持rss订阅 9、后台密码使用MD5加密算法 10、支持access、mssql数据库 11、导航插件管理,使得...

    基于SSM+mysql的健身国际俱乐部系统设计与实现(源码+部署说明+视频演示).zip

    在实现过程中,我们使用了MySQL数据库来存储用户信息、健身课程信息、会员卡信息等数据,并采用了Redis缓存来提高系统的性能。同时,我们还集成了支付宝接口来进行支付功能的开发。 总体来说,基于SSM+Vue的健身...

    基于springboot+vue的游戏交易系统.zip

    SEO优化:前端页面采用服务端渲染(SSR),提高页面加载速度,有利于搜索引擎优化。总结:基于springboot+vue的游戏交易系统是一个功能完善、性能优越的全栈项目,适合作为学习和商业应用的基础。通过该系统,用户...

Global site tag (gtag.js) - Google Analytics