用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中的__new__与__init__魔术方法理解笔记
Nov 08 Python
Python解析nginx日志文件
May 11 Python
Python网络爬虫项目:内容提取器的定义
Oct 25 Python
Laravel+Dingo/Api 自定义响应的实现
Feb 17 Python
python ddt数据驱动最简实例代码
Feb 22 Python
Python tkinter和exe打包的方法
Feb 05 Python
tensorflow 环境变量设置方式
Feb 06 Python
pytorch使用tensorboardX进行loss可视化实例
Feb 24 Python
详解使用python3.7配置开发钉钉群自定义机器人(2020年新版攻略)
Apr 01 Python
python正则表达式 匹配反斜杠的操作方法
Aug 07 Python
CocosCreator ScrollView优化系列之分帧加载
Apr 14 Python
Django中的JWT身份验证的实现
May 07 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
文件系统基本操作类
2006/11/23 PHP
利用ThinkPHP内置的ThinkAjax实现异步传输技术的实现方法
2011/12/19 PHP
thinkphp使用literal防止模板标签被解析的方法
2014/11/22 PHP
php中动态变量用法实例
2015/06/10 PHP
PHP Laravel 上传图片、文件等类封装
2017/08/16 PHP
PHP实现的各类hash算法长度及性能测试实例
2017/08/27 PHP
CSS心形加载的动画源码的实现
2021/03/09 HTML / CSS
javascript实现unicode和字符的互相转换
2007/07/18 Javascript
分享精心挑选的23款美轮美奂的jQuery 图片特效插件
2012/08/14 Javascript
js控制表单不能输入空格的小例子
2013/11/20 Javascript
利用javascript实现全部删或清空所选的操作
2014/05/27 Javascript
Javascript中的异步编程规范Promises/A详细介绍
2014/06/06 Javascript
js style动态设置table高度
2014/10/21 Javascript
ECMAScript6中Map/WeakMap详解
2015/06/12 Javascript
js获取及判断键盘按键的方法
2015/12/01 Javascript
微信小程序开发之圆形菜单 仿建行圆形菜单实例
2016/12/12 Javascript
angular.JS实现网页禁用调试、复制和剪切
2017/03/31 Javascript
Javascript之图片的延迟加载的实例详解
2017/07/24 Javascript
Vue实现一个返回顶部backToTop组件
2017/07/25 Javascript
Cropper.js 实现裁剪图片并上传(PC端)
2017/08/20 Javascript
浅析JavaScript异步代码优化
2019/03/18 Javascript
python实现简单的TCP代理服务器
2014/10/08 Python
使用Python的urllib和urllib2模块制作爬虫的实例教程
2016/01/20 Python
利用Python yagmail三行代码实现发送邮件
2018/05/11 Python
python配置文件写入过程详解
2019/10/19 Python
Python操作MongoDb数据库流程详解
2020/03/05 Python
Python新手学习装饰器
2020/06/04 Python
html Table 表头固定的实现
2019/01/22 HTML / CSS
html5指南-5.使用web storage存储键值对的数据
2013/01/07 HTML / CSS
Europcar德国:全球汽车租赁领域的领导者
2018/08/15 全球购物
如何通过 CSS 写出火焰效果
2021/03/24 HTML / CSS
会计学专业学生的求职信范文
2014/01/27 职场文书
开展批评与自我批评发言材料
2014/10/17 职场文书
魂断蓝桥观后感
2015/06/10 职场文书
深入浅出的讲解:信号调制到底是如何实现的
2022/02/18 无线电
Win10系统搭建ftp文件服务器详细教程
2022/08/05 Servers