2,3か月前に作成したサーバの監視アプリのソースコードを紹介します。5分間隔で数百件程度のURLにリクエストを投げ、そのレスポンスタイムを取得するだけの単純なアプリなので、機能としては単純なのですが、性能面の制約に苦しみました。今でこそ、CronやTaskQueueから実行したリクエストは、最大で10分間実行できますが、当時は30秒制限があったため、容易に制限時間を超えてしまったのです。平均1秒だとしても30秒の時間制限内には到底処理が終わりません。いろいろ考えた末、Cron関数内で5URLずつまとめてTaskQueueに投げ込むことにしました。その結果、当時の厳しい実行時間制約(30秒)の中、無事に要件を満たすことができました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | class Cron(webapp.RequestHandler): def get(self): size = 5 sites = db.GqlQuery("SELECT * FROM Site ORDER BY date DESC") for i in range(0, sites.count(), size): # i = 0, 5, 10, 15, ...... params = {} for j in range(0, size): #j = 0, 1, 2, 3, 4 if i + j >= sites.count(): break params["url"+str(j)] = sites[i+j].url taskqueue.add(url='/worker', params = params) # taskqueueにタスクを追加 class Worker(webapp.RequestHandler): def post(self): if(int(self.request.headers.environ['HTTP_X_APPENGINE_TASKRETRYCOUNT']) > 0): return # エラー発生時の、リトライ防止 for key in self.request.arguments(): try: url = self.request.get(key) fetchAndLog(url) # レスポンスタイムの測定と記録。5秒を超えると例外を投げる。 except: pass |