Google App Engine ( python ) で memcached を使って HTML 自体をキャッシュする
Webアプリにおけるキャッシュ。オレオレ事例 - ゆーすけべー日記 の「ページのHTMLをキャッシュする」をみて、試すのにちょうどいい機会があったので、Google App Engine + python + memcached でやってみました。
実際に GAE 上で動いているコードがこれ。
main.py
# coding:utf-8
import sys
import os
root_dir = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, os.path.join(root_dir, 'lib'))
from google.appengine.ext.webapp.util import run_wsgi_app
from flask import Flask, render_template
from google.appengine.api import urlfetch
from google.appengine.api import memcache
from xml.dom import minidom
from datetime import datetime
app = Flask(__name__)
app.debug = True
_RSS = 'http://example.com/rss'
_LIMIT = 3
_EXPIRES_IN = 60 * 60 # 1hour
@app.route('/')
def index():
title = u'Indexページ'
cur = 'index'
html = memcache.get(cur)
if html is None:
html = render_template('index.html', title = title, cur = cur, entries = get_entries(_RSS, _LIMIT))
memcache.add(cur, html, _EXPIRES_IN)
return html
def get_entries(rss, limit):
res = urlfetch.fetch(rss)
dom = minidom.parseString(res.content)
# parse feed
blog_title = dom.getElementsByTagName('channel')[0].getElementsByTagName('title')[0].firstChild.data
items = dom.getElementsByTagName('item')
entries = []
for i, item in enumerate(items):
if i != limit:
entry = {}
entry['title'] = item.getElementsByTagName('title')[0].firstChild.data
entry['link'] = item.getElementsByTagName('link')[0].firstChild.data
entry['date'] = item.getElementsByTagName('pubDate')[0].firstChild.data
entries.append(entry)
else:
break
return entries
run_wsgi_app(app)
軽量ウェブアプリケーションフレームワークの Flask を使っていて、Jinja2 というテンプレートエンジンが使われています。そんなに更新頻度の高くない、別ドメイン&サーバで動いているブログの RSS を取得、配列にして、その他の情報とともに最新エントリー3件をテンプレートに渡しているのですが、冒頭のリンク先にある通り、
- ネットワークを使って外部にアクセスするので時間がかかる
- 更新頻度が高くないので毎回情報を更新させる必要がない
ので 有効期限を1時間としてキャッシュするようにしました。これにより毎回テンプレートから HTML を生成するという手間を省くことができました。こんな流れに。
-
要求があったページの HTML 文字列が memcache にあるかどうか調べる
-
HTML 文字列が memcache にあれば、その HTML 文字列を使用する
-
HTML 文字列が memcache になければ、example.com からフィードを取得、テンプレートに渡して HTML を生成、その結果を今後の要求に備えて memcache に保存する
main.py の先頭で、
from google.appengine.api import memcache
とするだけですぐ memcached が使えるのはかなり手軽で素晴らしかったです。ちなみにローカルに memcached 環境が無くとも GoogleAppEngineLauncher で同じコードを起動できました。
GAE + memcached の情報は本家 Google の情報が詳しかったです。
Memcache の使用方法 - Google App Engine — Google Developers
効果的な Memcache の使用 - Google App Engine — Google Developers