wata.dev

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

ブログの記事一覧