GAE Python で Task Queue
クラウドしたいということで、Google App Engine で遊びはじめた。
まず、たくさんのデータを登録するために、PythonでTask Queue APIを使ってみた。
例の動作内容
Task Queueに登録すると勝手に、CPUに割り当てて並列実行してくれる。無料版の場合、最大5個まで同時実行してくれる。並列に実行しているのを見ると楽しい。
DataStoreへの登録は1-10件/1秒らしく、200件で24秒かかる。分割を250件にすると30秒を超えてTaskが途中でkillされる。
DataStoreに5000件登録するだけで、無料版のCPU時間の2%を使ってしまう。ということは、無料版だと25万件登録するとCPU時間のQuota/1dayに引っ掛かるっぽい。
登録するだけなら簡単。だけど、DataStoreをどう使うかが悩ましい。
参考;
- Task Queue戦記 - スティルハウスの書庫の書庫
- TaskQueueをローカルでデバッグする方法 - yvsu pron. yas
- Offline Processing on App Engine: a Look Aheadを見たメモ - スティルハウスの書庫の書庫
#!/usr/bin/env python # -*- coding: utf-8 -*- import wsgiref.handlers from google.appengine.ext import webapp from google.appengine.ext import db from google.appengine.api import urlfetch from google.appengine.api import memcache from google.appengine.api.labs import taskqueue from xml.etree.ElementTree import fromstring import datetime Config = { 'User' : 'eggman_', 'split' : 200, } class Topmls(db.Model): created = db.DateTimeProperty(auto_now_add=True) user = db.StringProperty() url = db.StringProperty() title = db.StringProperty() def get_opml(url): outlines = memcache.get(url) if outlines is None: result = urlfetch.fetch(url, '', urlfetch.GET, headers={'User-Agent': 'http://twitter.com/eggman'}) elem = fromstring(result.content) outlines = list(reversed(elem.findall('./////outline'))) memcache.add(url ,outlines, 3600) return outlines class MainHandler(webapp.RequestHandler): def get(self): user = Config['User'] # url = 'http://reader.livedoor.com/user/' + user + '/opml' url = 'http://nolist.jp/opml' outlines = get_opml(url) for i in range(0, len(outlines), Config['split']): taskqueue.add(url='/insert_opml_worker', params={'url': url, 'user' : user, 'start' : i, }) class InsertOpmlWorker(webapp.RequestHandler): def post(self): user = self.request.get('user') url = self.request.get('url') start = int( self.request.get('start') ) outlines = get_opml(url) for o in outlines[start:start+Config['split']]: p = Topmls( title = o.get('title'), url = o.get('htmlUrl'), user = user, ) p.put() def main(): application = webapp.WSGIApplication([('/check', MainHandler), ('/insert_opml_worker', InsertOpmlWorker)], debug=True) wsgiref.handlers.CGIHandler().run(application) if __name__ == '__main__': main()