用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中__init__和__new__的区别详解
Jul 09 Python
Python functools模块学习总结
May 09 Python
Python中方法链的使用方法
Feb 23 Python
python 寻找优化使成本函数最小的最优解的方法
Dec 28 Python
如何使用Python的Requests包实现模拟登陆
Apr 27 Python
Python中pillow知识点学习
Apr 30 Python
Python中字符串与编码示例代码
May 20 Python
Python列表与元组的异同详解
Jul 02 Python
Pytorch加载部分预训练模型的参数实例
Aug 18 Python
Python对称的二叉树多种思路实现方法
Feb 28 Python
PyCharm2020.3.2安装超详细教程
Feb 08 Python
Python中使用ipython的详细教程
Jun 22 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
模拟用户操作Input元素,不会触发相应事件
2007/05/11 Javascript
用户注册常用javascript代码
2009/08/29 Javascript
js 刷新页面的代码小结 推荐
2010/04/02 Javascript
Bootstrap自定义文件上传下载样式
2016/05/26 Javascript
浅析JavaScript中命名空间namespace模式
2016/06/22 Javascript
如何实现星星评价(jquery.raty.js插件)
2016/12/21 Javascript
jquery与ajax获取特殊字符实例详解
2017/01/08 Javascript
vue.js中过滤器的使用教程
2017/06/08 Javascript
vue element项目引入icon图标的方法
2018/06/06 Javascript
解决vue单页路由跳转后scrollTop的问题
2018/09/03 Javascript
JavaScript中的回调函数实例讲解
2019/01/27 Javascript
基于iview的router常用控制方式
2019/05/30 Javascript
ES6小技巧之代替lodash
2019/06/07 Javascript
js设置默认时间跨度过程详解
2019/07/17 Javascript
vue 通过base64实现图片下载功能
2020/12/19 Vue.js
Python流行ORM框架sqlalchemy安装与使用教程
2019/06/04 Python
Python3中urlencode和urldecode的用法详解
2019/07/23 Python
python中自带的三个装饰器的实现
2019/11/08 Python
python 字段拆分详解
2019/12/17 Python
6行Python代码实现进度条效果(Progress、tqdm、alive-progress​​​​​​​和PySimpleGUI库)
2020/01/06 Python
Python SSL证书验证问题解决方案
2020/01/13 Python
dpn网络的pytorch实现方式
2020/01/14 Python
AUC计算方法与Python实现代码
2020/02/28 Python
python和php学习哪个更有发展
2020/06/17 Python
Python 防止死锁的方法
2020/07/29 Python
Python 图片处理库exifread详解
2021/02/25 Python
Python .py生成.pyd文件并打包.exe 的注意事项说明
2021/03/04 Python
html5自带表单验证体验优化及提示气泡修改功能
2017/09/12 HTML / CSS
使用HTML5做个画图板的方法介绍
2013/05/03 HTML / CSS
行政助理岗位职责
2013/11/10 职场文书
班主任寄语大全
2014/04/04 职场文书
交通事故赔偿协议书范本
2014/04/15 职场文书
市场营销专业自荐书
2014/06/10 职场文书
处级干部反四风个人对照检查材料思想汇报
2014/09/27 职场文书
办理信用卡工作证明
2014/09/30 职场文书
2016银行招聘自荐信
2016/01/28 职场文书