用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实现把utf-8格式的文件转换成gbk格式的文件
Jan 22 Python
python检测远程udp端口是否打开的方法
Mar 14 Python
Python基于回溯法子集树模板实现图的遍历功能示例
Sep 05 Python
Queue 实现生产者消费者模型(实例讲解)
Nov 13 Python
Python 数据处理库 pandas进阶教程
Apr 21 Python
Python单元测试简单示例
Jul 03 Python
详解python中docx库的安装过程
Nov 08 Python
pycharm运行scrapy过程图解
Nov 22 Python
python实现超级马里奥
Mar 18 Python
Tensorflow安装问题: Could not find a version that satisfies the requirement tensorflow
Apr 20 Python
如何用 Python 处理不平衡数据集
Jan 04 Python
解决Python import .pyd 可能遇到路径的问题
Mar 04 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设计模式之责任链模式的深入解析
2013/06/13 PHP
php cli配置文件问题分析
2015/10/15 PHP
实例分析基于PHP微信网页获取用户信息
2017/11/24 PHP
js实现页面打印功能实例代码(附去页眉页脚功能代码)
2009/12/15 Javascript
JavaScript对象学习经验整理
2013/10/12 Javascript
jquery实现不同大小浏览器使用不同的css样式表的方法
2014/04/02 Javascript
使用变量动态设置js的属性名
2014/10/19 Javascript
Javascript快速排序算法详解
2014/12/03 Javascript
jQuery对指定元素中指定字符串进行替换的方法
2015/03/17 Javascript
JS建造者模式基本用法实例分析
2015/06/30 Javascript
JavaScript黑洞数字之运算路线查找算法(递归算法)实例
2016/01/28 Javascript
sso跨域写cookie的一段js脚本(推荐)
2016/05/25 Javascript
angularJs的ng-class切换class
2017/06/23 Javascript
vue2.X组件学习心得(新手必看篇)
2017/07/05 Javascript
pm2 部署 node的三种方法示例
2017/10/20 Javascript
微信小程序页面跳转功能之从列表的item项跳转到下一个页面的方法
2017/11/27 Javascript
Vue中的v-for循环key属性注意事项小结
2018/08/12 Javascript
Vue动态路由缓存不相互影响的解决办法
2019/02/19 Javascript
Nuxt.js实战和配置详解
2019/08/05 Javascript
vue利用全局导航守卫作登录后跳转到未登录前指定页面的实例代码
2020/05/19 Javascript
JavaScript实现像雪花一样的Hexaflake分形
2020/07/07 Javascript
VUE中setTimeout和setInterval自动销毁案例
2020/09/07 Javascript
Python文件操作,open读写文件,追加文本内容实例
2016/12/14 Python
Python3.4实现从HTTP代理网站批量获取代理并筛选的方法示例
2017/09/26 Python
Python多线程原理与用法实例剖析
2019/01/22 Python
详解python播放音频的三种方法
2019/09/23 Python
pyhton中__pycache__文件夹的产生与作用详解
2019/11/24 Python
Python实现隐马尔可夫模型的前向后向算法的示例代码
2019/12/31 Python
Python3标准库glob文件名模式匹配的问题
2020/03/13 Python
详解CSS透明opacity和IE各版本透明度滤镜filter的最准确用法
2016/12/20 HTML / CSS
Manuka Doctor美国官网:麦卢卡蜂蜜和蜂毒护肤
2016/12/25 全球购物
Hunkemöller瑞士网上商店:欧洲最大的内衣品牌之一
2018/12/03 全球购物
JSF如何进行表格处理及取值
2012/08/06 面试题
如何向接受结构参数的函数传入常数值
2016/02/17 面试题
高中运动会入场词
2014/02/14 职场文书
创业计划书之珠宝饰品
2019/08/26 职场文书