前回の続き
不動産屋の俺がGoogle App EngineでAPIもどきを作る件_01 - 不動産屋のラノベ読み
キャッシュを使ってみる
def get(self, rURL): try : sizeX, sizeY = map( (lambda x:int(x)), self.request.get('fit').split('x',2) ) except : sizeX, sizeY = [150, 150] resData = memcache.get( '%s%s%s' % (rURL, sizeX, sizeY) ) if not resData: result = urlfetch.fetch( urllib.unquote(rURL) ) if result.status_code == 200: img = images.Image(result.content) img.resize(width=sizeX, height=sizeX) resData = img.execute_transforms(output_encoding=images.JPEG) memcache.add( '%s%s%s' % (rURL, sizeX, sizeY), resData, 1209600 ) self.response.headers["Content-Type"] = "image/jpeg" self.response.out.write(resData)
キャッシュがなければ元画像にアクセスし、リサイズした画像をキャッシュするようにした。成功。
キャッシュのキーにはURLとサイズをくっつけたものにした。賞味期限は一週間で設定。画像だし、別にいいやみたいな。
だいたいの機能を満たしたので、ウチの会社サイトにこっそり仕込む。
動かない。
良く考えたら、画像のURIにはパラメタがくっついていたのだが、そこが取り出したURI文字列からすべて落ちてしまっていたらしい。
ので、一行追加。
rURL += '?' + self.request.query_string
動いた。
その他色々修正
会社サイトに仕込んだまま、一晩放置。
なにやらエラーが上がっている。
DownloadError: ApplicationError: 5
調べてみると、urlfetch.fetchはあっさりタイムアウトしてくれるらしい。例外拾ってもう一度urlfetch.fetchを走らせてもいいけど、なんか重くなりそうなのでやめる。
あと、予想よりリクエストが多くてびっくり。たぶん、ブラウザがキャッシュしてないんだろうと思い、Tamper Data :: Add-ons for Firefoxで調べてみた。予想通り、Cache-Control: maxtime=0だった。まあ、cgiなんだから当然といえば当然。ついでに静的ファイルはどうなのか調べてみると、こちらは600秒だった。これ、設定変えられるのかな。
で、とりあえず、Cache-Control: maxtime=1209600などする。あと、良く考えたら、今の状態だとmemcacheの賞味期限が切れるまで泣いて頼んでも同じ画像を送られてしまうので、no-cacheでのリクエストがあったときにキャッシュをリフレッシュするなどした。
def get(self, rURL): try : sizeX, sizeY = map( (lambda x:int(x)), self.request.get('fit').split('x',2) ) except : sizeX, sizeY = [150, 150] rURL += '?' + self.request.query_string if self.request.headers.get('Cache-Control') != 'no-cache': resData = memcache.get( '%s%s%s' % (rURL, sizeX, sizeY) ) else: resData = None if not resData: try : result = urlfetch.fetch( urllib.unquote(rURL) ) if result.status_code == 200: img = images.Image(result.content) img.resize(width=sizeX, height=sizeY) resData = img.execute_transforms(output_encoding=images.JPEG) memcache.set( '%s%s%s' % (rURL, sizeX, sizeY), resData, 1209600 ) else: self.response.set_status(result.status_code) return except : self.response.set_status(500) return expires_date = datetime.datetime.utcnow() + datetime.timedelta(7) expires_str = expires_date.strftime("%d %b %Y %H:%M:%S GMT") self.response.headers["Expires"] = expires_str self.response.headers["Cache-Control"] = "public, maxtime=1209600" self.response.headers["Content-Type"] = "image/jpeg" self.response.out.write(resData)
とりあえず完成
キャッシュを設定して2,3日様子を見たら、いい感じにリクエストが減ってる。ってことは、ウチの会社は新規ビジターが少ないってコトだよなあ、うーん。
とりあえず、アドレスを晒すので、「セキュリティ的にヤバイ」みたいなのがあれば教えていただけると嬉しい。
http://lhankor-mhy.appspot.com/resize/http://d.hatena.ne.jp/images/keyword/29472.jpg?fit=50x50
見ていただいたとおり、Google App Engineは非常に簡単にトライアンドエラーで作っていく事ができます。非プログラマの皆さん、一緒にどうですか?