用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 相关文章推荐
简单介绍Python2.x版本中的cmp()方法的使用
May 20 Python
Python监控主机是否存活并以邮件报警
Sep 22 Python
Python2.7简单连接与操作MySQL的方法
Apr 27 Python
Python操作Excel插入删除行的方法
Dec 10 Python
【python】matplotlib动态显示详解
Apr 11 Python
python的常见矩阵运算(小结)
Aug 07 Python
开启Django博客的RSS功能的实现方法
Feb 17 Python
Python unittest 自动识别并执行测试用例方式
Mar 09 Python
Python selenium爬取微信公众号文章代码详解
Aug 12 Python
python实现文件分片上传的接口自动化
Nov 19 Python
Matplotlib配色之Colormap详解
Jan 05 Python
Python还能这么玩之只用30行代码从excel提取个人值班表
Jun 05 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
thinkphp中memcache的用法实例
2014/11/29 PHP
windows7下php开发环境搭建图文教程
2015/01/06 PHP
thinkPHP中验证码的简单使用方法
2015/12/26 PHP
让你的PHP7更快之Hugepage用法分析
2016/05/31 PHP
用Juery网页选项卡实现代码
2011/06/13 Javascript
基于Jquery实现的一个图片滚动切换
2012/06/21 Javascript
js中的前绑定和后绑定详解
2013/08/01 Javascript
3种不同方式的焦点图轮播特效分享
2013/10/30 Javascript
JavaScript闭包实例讲解
2014/04/22 Javascript
Javascript中判断对象是否为空
2015/06/10 Javascript
由ReactJS的Hello world说开来
2015/07/02 Javascript
JavaScript判断是否是微信浏览器
2016/06/13 Javascript
jquery实现上传文件大小类型的验证例子(推荐)
2016/06/25 Javascript
AngularJS教程之简单应用程序示例
2016/08/16 Javascript
vue2.0使用v-for循环制作多级嵌套菜单栏
2018/06/25 Javascript
jQuery实现为动态添加的元素绑定事件实例分析
2018/09/07 jQuery
小程序实现新用户判断并跳转激活的方法
2019/05/20 Javascript
javascript前端和后台进行数据交互方法示例
2020/08/07 Javascript
用Pygal绘制直方图代码示例
2017/12/07 Python
Numpy数组转置的两种实现方法
2018/04/17 Python
Pandas 按索引合并数据集的方法
2018/11/15 Python
详解python项目实战:模拟登陆CSDN
2019/04/04 Python
Python之修改图片像素值的方法
2019/07/03 Python
详解python中__name__的意义以及作用
2019/08/07 Python
详解基于python的多张不同宽高图片拼接成大图
2019/09/26 Python
python 命名规范知识点汇总
2020/02/14 Python
用python给csv里的数据排序的具体代码
2020/07/17 Python
css3圆角样式分享自定义按钮样式
2013/12/27 HTML / CSS
加拿大时尚床上用品零售商:QE Home | Quilts Etc
2018/01/22 全球购物
2014年实习班主任工作总结
2014/11/08 职场文书
房屋买卖协议样本
2014/11/16 职场文书
2015年党风廉政承诺书
2015/01/22 职场文书
2015年教育实习工作总结
2015/04/24 职场文书
敬老院志愿者活动总结
2015/05/06 职场文书
陪护人员误工证明
2015/06/24 职场文书
HTML5+CSS+JavaScript实现捉虫小游戏设计和实现
2021/10/16 HTML / CSS