[转]如何分离个人信息,缓存动态页面
2008-04-04 16:09
323 查看
如何分离个人信息,缓存动态页面
肖理达 (KrazyNio AT hotmail.com), 2005.06.07, 转载请注明出处一直想写一篇关于动态页面 cache 的文章,但每次“提笔”却又放弃,因为总是觉得准备得还不够充分。今天埋头写下,只是希望对自己的工作做一些笔录。
1、问题起源
我们经常会在一个动态页面中加入很多个人信息,以 CMS 首页为例,用户登录之前显示登录框,登录之后显示其用户名,并根据权限显示其可用模块的链接。由于每个用户登录之后,显示出来的动态信息都是不一样的,所以这部分无法进行 cache,我们将这部分信息定义为“个人信息”,它的特性是根据登录用户进行动态改变。
现在问题来了,就是一个 CMS 的首页,访问者的登录概率并不是百分百的,应该说有一大部分人访问首页是没有登录的,这个时候的首页是一个公共的页面,没有任何个人信息,或者说这时候首页的任何动态信息都是可以转换成静态的,也就是说这部分是可 cache 的。
2、使用 JavaScript 分离个人信息
解决这个问题的方法有很多种,一种是将个人信息和其他信息进行分离,如在 CMS 首页中加入一个外部的 JavaScript 文件,而这个文件的内容实际上是由 PHP 动态生成的。CMS 首页 index.php 代码片段:
....document.write(sUser);document.write(sLinks);
personal.php 代码片段:
sUser = "";sLinks = "";
这种方法比较适合个人信息较少,易于集中显示的情况。通过 JavaScript 外挂代码实现个人信息分离之后,personal.php 是永不 cache 的,这样也就可以放心地对 CMS 首页进行 cache 了,具体的 cache 方法可采用 304 HTTP 头与 Cache_Lite 相结合的方式,这在后边有详细代码示例。
3、选择性分离个人信息
一旦个人信息较多,很难对其进行分离的时候,上述方法实现起来就会比较麻烦了。接下来介绍一种比较放宽的 cache 方式,就是只对用户未登录的 CMS 首页进行 cache,一旦发现用户处于登录状态,则跳过 cache 部分,直接运行相关代码,我把这种方法称为“选择性 cache”。这种方法中,我们牺牲了一部分可 cache 的情况,但很大程度上提高了个人信息的可扩充性,也就是说个人信息的多少、显示的位置等等都不再受到限制,这是值得的,毕竟修改服务端代码要比修改大量的 JavaScript 代码要来得方便,而且 JavaScript 的调试也会比较麻烦。
分析一下这种 cache 方式,概要流程图如下:
代码片段如下:
这里需要说明的一点是,由于 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 则是由客户端往服务器发送的头,其工作原理图如下:
可以看到,再次请求本地存在的 cache 页面时,客户端会通过 If-Modified-Since 头将先前服务器端发过来的 Last-Modified 最后修改时间戳发送回去,这是为了让服务器端进行验证,通过这个时间戳判断客户端的页面是否是最新的,如果不是最新的,则返回新的内容,如果是最新的,则返回 304 告诉客户端其本地 cache 的页面是最新的,于是客户端就可以直接从本地加载页面了,这样在网络上传输的数据就会大大减少,同时也减轻了服务器的负担。想要详细查看 HTTP 头信息,可以在 Firefox 中安装 LiveHTTPHeaders 插件,安装完成之后按 Alt+L 就可以在 Sidebar 中看到了。
现在再来完善之前的 index.php 代码:
'./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 源代码 //from: http://www.infor96.com/~nio/comments.php?id=287_0_1_50_C1
相关文章推荐
- [转]如何分离个人信息,缓存动态页面
- [转]如何分离个人信息,缓存动态页面
- 如何用Python抓取动态页面信息
- MOSS如何将用户的个人信息,如部门,显示在页面上呢?
- 【phpcms-v9】如何在频道页面动态显示当前频道各个子栏目的部分信息
- Drupal是如何避免页面缓存保存Message信息的
- 如何动态不显示页面底部的版权所有等信息???
- 【转】如何避免IE对动态页面进行缓存?
- 如何在ashx页面获取Session值 (仅供个人参考)
- 禁用页面缓存的几种方法(静态和动态)
- 如何用js得到当前页面的url信息方法(JS获取当前网址信息)
- 动态配置信息需要提供一个重新缓存的按钮
- 如何用js得到当前页面的url信息方法(JS获取当前网址信息)
- 用户系列之一:用户登录后缓存用户信息在哪?如何修改用户登录方式?
- shiro安全框架扩展教程--如何动态控制页面节点元素的权限
- 如何从真实照片中分离高光和漫反射信息
- oscache如何缓存页面及如何强制清除指定页面的缓存
- 【spring】ApplicationListener传递参数到页面(解决静态+动态资源路径+静态文件的缓存控制)
- 如何让php对页面的缓存进行控制 php处理请求的浏览器缓存处理
- js如何准确获取当前页面url网址信息