在动态生成网页的时候,通常会使用模板语言【templating language】来简化网页的生成操作。需要手写每个页面的日子已经一去不复返:现在的Web页面通常由包含首部、尾部、侧栏菜单、工具条、内容域的模板生成,有时候模板还用于生成JavaScript。
尽管【Fake Web Retailer】也能够动态地生成内容,但这个网站上的很多页面实际上并不会经常发生大的变化:虽然会向分类中添加新商品、移除旧商品、有时有特价促销、有时甚至还有【热卖商品】页面,但是在一般情况下,网站只有账号设置、以往订单、购物车【结账信息】以及其他少数几个页面才包含需要每次载入都要动态生成的内容。
假设:通过对浏览数据进行分析,我们发现我们网站所处理的95%的Web页面每天最多只会改变一次,这些页面的内容实际上并不需要动态生成,而我们的工作就是想办法不再生产这些页面。减少网站的动态生成内容上面所花的时间,可以降低网站处理相同负载所需的服务器数量,并让网站的速度变得更快。【研究表明,减少用户等待页面载入的时间,可以增加用户使用网站的欲望,并改善用户对网站的印象。】
所有标准的Python应用框架都提供了在处理请求之前或者之后添加层【layer】的能力,这些层同城被称为中间件【middleware】或者插件【plugin】。我们将创建一个这样的层来调用Redis缓存函数:对于一个不能被缓存的请求,函数将直接生成并返回页面;而对于可以被缓存的请求,函数首先尝试从缓存里面取出并返回被缓存的页面,如果缓存页面不存在,那么函数会生成页面并将其缓存在Redis里面5分钟,最后再将页面返回给调用者。
def cache_request(conn,request,callback):
if not can_cache(conn,request):
#对于不能被缓存的请求,直接调用毁掉函数
return callback(request)
#将请求转换成一个简单的字符串建,方便之后进行查找
page_key='cache:'+hash_request(request)
#尝试查找被缓存的页面
content=conn.get(page_key)
if not content:
#如果页面没有被缓存,那么生成页面
content=callback(request)
#将新生成的页面存放到缓存里面
conn.setex(page_key,content,300)
return content
对于我们的网站上面95%的可被缓存并且频繁被载入的内容来说,上面缓存函数可以让网站在5分钟之内无须再为它们动态生成视图页面。取决于网页的内容有多复杂,这一改动可以将包含大量数据的页面的延迟值从20~50毫秒降低至查询一次Redis所需的时间:查询本地Redis的延迟值通常低于1毫秒,而查询位于同一数据中心的Redis的延时值通常低于5毫秒。对于那么需要访问数据库的页面来说,这个缓存函数对于减少页面载入时间和降低数据库负载的作用会更加显著。
在这一节中,我们学习了如何使用Redis来减少载入不常该表页面所需的时间,那么对于那些经常发生变化的页面,我们是否也能够使用Redis来减少他们的载入时间呢?
答案是肯定的,接下来我们将介绍实现这一目标的具体做法。