在动态生成网页时,通常使用模板语言来简化页面生成。 手动编写每个页面的日子已经过去了。 现代网页是从页面模板生成的,包括页眉、页脚、侧面菜单、工具栏、内容区域,甚至可能生成 JavaScript。
尽管能够动态生成内容,但 Fake Web Retailer 网站上提供的大部分页面在定期基础上变化不大。 当然,有些新商品会添加到目录中,旧商品会被删除,有时会有特价商品,有时甚至会有“热门商品”页面。 但实际上,只有少数帐户设置、过去订单、购物车/结帐和类似页面的内容需要在每次页面加载时生成。
通过查看他们的浏览量,Fake Web Retailer 确定他们提供的 95% 的网页最多每天更改一次,并且实际上不需要动态生成内容。 我们的工作是停止为每次加载生成 95% 的页面。 通过减少我们花费在生成静态内容上的时间,我们可以减少处理相同负载所需的服务器数量,并且我们可以更快地提供我们的站点。 (研究表明,减少用户等待页面加载的时间会增加他们使用网站的意愿并提高他们对网站的评分。)
所有标准的 Python 应用程序框架都提供了添加可以在处理时预处理或后处理请求的层的功能。 这些层通常称为中间件或插件。 让我们创建一个调用我们的 Redis 缓存功能的层。 如果无法缓存 Web 请求,我们将生成页面并返回内容。 如果可以缓存请求,我们将尝试从缓存中获取并返回页面; 否则,我们将生成页面,将结果缓存在 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(本地连接低于 1 毫秒,同一数据中心中彼此靠近的计算机低于 5 毫秒)。 对于过去需要访问数据库以获取数据的页面,这可以进一步减少页面加载时间和数据库负载。
现在我们已经减少了不经常更改的页面的加载时间,我们是否可以继续使用 Redis 来减少经常更改的页面的加载时间? 当然可以! 继续阅读以了解如何操作。