用Python的Tornado框架结合memcached页面改善博客性能


Posted in Python onApril 24, 2015

原因

Blog是一个更新并不很频繁的一套系统,但是每次刷新页面都要更新数据库反而很浪费资源,添加静态页面生成是一个解决办法,同时缓存是一个更好的主意,可以结合Memcached添加少量的代码进行缓存,而且免去去了每次更新文章都要重新生成静态页面,特别当页面特别多时.
实现

主要通过页面的uri进行缓存,结合tornado.web.RequestHandler的prepare和on_finish方法函数, prepare 主要是请求前执行,on_finish()是请求结束之前执行.在渲染模板时缓存页面内容,然后在请求前检测是否有缓存,如果有直接输出缓存,结束请求,在POST提交之后清空所有缓存,重新生成缓存,从而保证内容实时性.由于登录用户和普通用户的页面不相同,所以不缓存登录用户页面(代码中没有体现,请自行实现).主要python代码(省略了模板渲染的代码):

#!/usr/bin/env python
# -*- coding:utf-8 -*-
#
#  Author :  cold
#  E-mail :  wh_linux@126.com
#  Date  :  13/01/14 09:57:31
#  Desc  :  
#
import config
import pylibmc
from tornado.web import RequestHandler
#### 省略Cache类定义 #####

class Memcached(object):
  _mc = pylibmc.client.Client(config.CACHE_HOST, binary = True)

  def __enter__(self):
    if config.CACHED:
      return Memcached
    else:
      return Cache()

  def __exit__(self, exc_type, exc_val, exc_tb):
    pass

  @classmethod
  def get_cache(cls):
    return cls._mc

  @classmethod
  def get(cls, key, default = None):
    r = cls._mc.get(key)
    if not r:
      r = default
    return r

  @classmethod
  def set(cls, key, value, timeout = 0):
    timeout = timeout if timeout else config.CACHE_TIMEOUT
    return cls._mc.set(key, value, timeout)

  @classmethod
  def delete(cls, key):
    return cls._mc.delete(key)

  @classmethod
  def flush(cls):
    return cls._mc.flush_all()

  def __getattr__(self, key):
    return Memcached.get(key)

  def __setattr__(self, key, value):
    return Memcached.set(key, value)


class BaseHandler(RequestHandler):
  """ 继承tornado请求基类,重写 prepare和on_finish方法 """
  cache = Memcached

  def render(self, template_path, *args, **kwargs):
    """ 渲染模板 """
    # 省略渲染模板代码
    content = ''   # 渲染模板后的内容
    if self.request.method == "GET" and CACHED and \
      not self.request.path.startswith("/admin"):
      self.cache.set(self.request.uri, content) # 将渲染后的内容缓存起来
    self.write(content)

  def prepare(self):
    super(BaseHandler, self).prepare()
    # 如果请求是GET方法,而且不是请求后台
    if self.request.method == "GET" and CACHED and \
      not self.request.path.startswith("/admin"):

      # 尝试获取当前页面的缓存
      cache = self.cache.get(self.request.uri)
      # 获取缓存则输出页面,结束请求
      if cache:
        return self.finish(cache)

  def on_finish(self):
    """ 重写结束请求前的方法函数 """
    if self.request.method == "POST":
      # 如果遇到POST提交则清空缓存
      self.cache.flush()

缓存系统在redis和Memcached选择了很久,因为只是单纯的缓存页面所以最后选择了memcached,使用pylibmc python库.
测试

使用webbench 网站压力测试对比了缓存前后的结果: 使用缓存前

$ webbench -c 500 -t 30 http://www.linuxzen.com/
Webbench - Simple Web Benchmark 1.5
Copyright (c) Radim Kolar 1997-2004, GPL Open Source Software.

Benchmarking: GET http://www.linuxzen.com/
500 clients, running 30 sec.

Speed=54 pages/min, 38160 bytes/sec.
Requests: 27 susceed, 0 failed.

使用缓存后:

$ webbench -c 500 -t 30 http://www.linuxzen.com/
Webbench - Simple Web Benchmark 1.5
Copyright (c) Radim Kolar 1997-2004, GPL Open Source Software.

Benchmarking: GET http://www.linuxzen.com/
500 clients, running 30 sec.

Speed=256 pages/min, 238544 bytes/sec.
Requests: 128 susceed, 0 failed.

明显快了很多...

Python 相关文章推荐
Python探索之爬取电商售卖信息代码示例
Oct 27 Python
R语言 vs Python对比:数据分析哪家强?
Nov 17 Python
基于Django filter中用contains和icontains的区别(详解)
Dec 12 Python
Python数据分析之双色球统计两个红和蓝球哪组合比例高的方法
Feb 03 Python
Python采集代理ip并判断是否可用和定时更新的方法
May 07 Python
python实现Windows电脑定时关机
Jun 20 Python
python 读写文件,按行修改文件的方法
Jul 12 Python
django框架基于queryset和双下划线的跨表查询操作详解
Dec 11 Python
Python with标签使用方法解析
Jan 17 Python
使用Python将语音转换为文本的方法
Aug 10 Python
python安装mysql的依赖包mysql-python操作
Jan 01 Python
Python3使用tesserocr识别字母数字验证码的实现
Jan 29 Python
使用Python编写一个在Linux下实现截图分享的脚本的教程
Apr 24 #Python
修改Python的pyxmpp2中的主循环使其提高性能
Apr 24 #Python
Python的Tornado框架异步编程入门实例
Apr 24 #Python
使用Python的Tornado框架实现一个简单的WebQQ机器人
Apr 24 #Python
Python程序中使用SQLAlchemy时出现乱码的解决方案
Apr 24 #Python
简单说明Python中的装饰器的用法
Apr 24 #Python
使用基于Python的Tornado框架的HTTP客户端的教程
Apr 24 #Python
You might like
随机头像PHP版
2006/10/09 PHP
PHP判断远程图片或文件是否存在的实现代码
2014/02/20 PHP
php导出excel格式数据问题
2014/03/11 PHP
jQuery TextBox自动完成条
2009/07/22 Javascript
关于scrollLeft,scrollTop的浏览器兼容性测试
2013/03/19 Javascript
nodejs获取本机内网和外网ip地址的实现代码
2014/06/01 NodeJs
原生Javascript封装的一个AJAX函数分享
2014/10/11 Javascript
javascript实时显示北京时间的方法
2015/03/12 Javascript
JavaScript实现函数返回多个值的方法
2015/06/09 Javascript
JavaScript驾驭网页-获取网页元素
2016/03/24 Javascript
jQuery模仿阿里云购买服务器选择购买时间长度的代码
2016/04/29 Javascript
Jquery中map函数的用法
2016/06/03 Javascript
关于Javascript中document.cookie的使用
2017/03/08 Javascript
使用3D引擎threeJS实现星空粒子移动效果
2020/09/13 Javascript
node.js中fs文件系统目录操作与文件信息操作
2018/02/24 Javascript
JavaScript 中定义函数用 var foo = function () {} 和 function foo()区别介绍
2018/03/01 Javascript
JS查找孩子节点简单示例
2019/07/25 Javascript
JS Generator 函数的含义与用法实例总结
2020/04/08 Javascript
在Vue中使用HOC模式的实现
2020/08/23 Javascript
vue 数据遍历筛选 过滤 排序的应用操作
2020/11/17 Javascript
简介Python中用于处理字符串的center()方法
2015/05/18 Python
老生常谈python函数参数的区别(必看篇)
2017/05/29 Python
用Python删除本地目录下某一时间点之前创建的所有文件的实例
2017/12/14 Python
python实现一个简单的udp通信的示例代码
2019/02/01 Python
python、Matlab求定积分的实现
2019/11/20 Python
Django的CVB实例详解
2020/02/10 Python
在Mac中PyCharm配置python Anaconda环境过程图解
2020/03/11 Python
python调用有道智云API实现文件批量翻译
2020/10/10 Python
马来西亚户外装备商店:PTT Outdoor
2019/07/13 全球购物
数字漫画:comiXology
2020/06/13 全球购物
大整数数相乘的问题
2012/07/22 面试题
八皇后问题,输出了所有情况,不过有些结果只是旋转了90度
2016/08/15 面试题
How to spawning asynchronous work in J2EE
2016/08/29 面试题
个人收入证明范本
2014/01/12 职场文书
周年庆典答谢词
2015/01/20 职场文书
2015民办小学年度工作总结
2015/05/26 职场文书