原因
Blog是一個(gè)更新并不很頻繁的一套系統(tǒng),但是每次刷新頁(yè)面都要更新數(shù)據(jù)庫(kù)反而很浪費(fèi)資源,添加靜態(tài)頁(yè)面生成是一個(gè)解決辦法,同時(shí)緩存是一個(gè)更好的主意,可以結(jié)合Memcached添加少量的代碼進(jìn)行緩存,而且免去去了每次更新文章都要重新生成靜態(tài)頁(yè)面,特別當(dāng)頁(yè)面特別多時(shí).
實(shí)現(xiàn)
主要通過(guò)頁(yè)面的uri進(jìn)行緩存,結(jié)合tornado.web.RequestHandler的prepare和on_finish方法函數(shù), prepare 主要是請(qǐng)求前執(zhí)行,on_finish()是請(qǐng)求結(jié)束之前執(zhí)行.在渲染模板時(shí)緩存頁(yè)面內(nèi)容,然后在請(qǐng)求前檢測(cè)是否有緩存,如果有直接輸出緩存,結(jié)束請(qǐng)求,在POST提交之后清空所有緩存,重新生成緩存,從而保證內(nèi)容實(shí)時(shí)性.由于登錄用戶和普通用戶的頁(yè)面不相同,所以不緩存登錄用戶頁(yè)面(代碼中沒(méi)有體現(xiàn),請(qǐng)自行實(shí)現(xiàn)).主要python代碼(省略了模板渲染的代碼):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
|
#!/usr/bin/env python # -*- coding:utf-8 -*- # # Author : cold # E-mail : [email protected] # 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請(qǐng)求基類,重寫 prepare和on_finish方法 """ cache = Memcached def render( self , template_path, * args, * * kwargs): """ 渲染模板 """ # 省略渲染模板代碼 content = '' # 渲染模板后的內(nèi)容 if self .request.method = = "GET" and CACHED and \ not self .request.path.startswith( "/admin" ): self .cache. set ( self .request.uri, content) # 將渲染后的內(nèi)容緩存起來(lái) self .write(content) def prepare( self ): super (BaseHandler, self ).prepare() # 如果請(qǐng)求是GET方法,而且不是請(qǐng)求后臺(tái) if self .request.method = = "GET" and CACHED and \ not self .request.path.startswith( "/admin" ): # 嘗試獲取當(dāng)前頁(yè)面的緩存 cache = self .cache.get( self .request.uri) # 獲取緩存則輸出頁(yè)面,結(jié)束請(qǐng)求 if cache: return self .finish(cache) def on_finish( self ): """ 重寫結(jié)束請(qǐng)求前的方法函數(shù) """ if self .request.method = = "POST" : # 如果遇到POST提交則清空緩存 self .cache.flush() |
緩存系統(tǒng)在redis和Memcached選擇了很久,因?yàn)橹皇菃渭兊木彺骓?yè)面所以最后選擇了memcached,使用pylibmc python庫(kù).
測(cè)試
使用webbench 網(wǎng)站壓力測(cè)試對(duì)比了緩存前后的結(jié)果: 使用緩存前
1
2
3
4
5
6
7
8
9
|
$ 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. |
使用緩存后:
1
2
3
4
5
6
7
8
9
|
$ 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. |
明顯快了很多...