Tornado 結合memcached緩存頁面

緣由

Blog是一個更新並不很頻繁的一套系統,可是每次刷新頁面都要更新數據庫反而很浪費資源,添加靜態頁面生成是一個解決辦法,同時緩存是一個更好的主意,能夠結合Memcached添加少許的代碼進行緩存,並且免去去了每次更新文章都要從新生成靜態頁面,特別當頁面特別多時.python

實現

主要經過頁面的uri進行緩存,結合tornado.web.RequestHandler的prepare和on_finish方法函數, prepare 主要是請求前執行,on_finish()是請求結束以前執行.在渲染模板時緩存頁面內容,而後在請求前檢測是否有緩存,若是有直接輸出緩存,結束請求,在POST提交以後清空全部緩存,從新生成緩存,從而保證內容實時性.因爲登陸用戶和普通用戶的頁面不相同,因此不緩存登陸用戶頁面(代碼中沒有體現,請自行實現).主要python代碼(省略了模板渲染的代碼):linux

#!/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() 

緩存系統在redisMemcached選擇了好久,由於只是單純的緩存頁面因此最後選擇了memcached,使用pylibmc python庫.web

測試

使用webbench 網站壓力測試對比了緩存先後的結果: 使用緩存前redis

$ 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.
相關文章
相關標籤/搜索