スキップしてメイン コンテンツに移動

投稿

[Python][Google App Engine]Google App Engineやめます。

Google App Engineは高すぎる。遅すぎる。 という訳でやめます。 大量のリクエストをさばくという意味では非常に有用なしくみなんですが、今のところオレオレシステムなので、Google App Engineが最適な仕組みとはいえない。 それに話題のNoSQLとかが使えない。 もちろんBig TableはKVS≒NoSQLなんですが、スピードが遅い、遅いせいで料金がかかる。 コレはいただけない。。。 とか言いながら戻ってくるかも知れませんけどねーw

[Python][Google App Engine][失敗]Backendsで無限ループ実装はダメ

昨日のポストでBackendsは「Instance時間による課金」と書きましたが、間違いでした。。。 Backendsは「Instance時間とCPU時間の両方で課金」が正しいみたいです。 昨日の実装で動かしているとQuotaのBackendsだけでなく、CPUTimeがどんどん消費されていき、最終的に無料割り当て分をすぐに食いつぶしてしまいました。 スケールするInstanceの方はログを見ても1時間に1回、1回あたり300ms程度しかCPU時間を消費していません。 明らかに想定外の動きでした。ログに出ない分意識しなかったというのが、敗因です。 BackendsのInstanceであっても、スケールする通常のInstanceであってもCPU時間での課金はあるので、無限ループの実装は不可能ということになります。 ということで、BackendsのAlwaysOnのオプションと違いを見いだせなくなってしまいました。 testBedを卒業して正式サービスに昇格する際には全てがInstance時間に対しての課金になるため、有効だとは思うんですが。。。

[Python][Google App Engine]Backendsで無限ループ実装

先日のGoogle App Engine SDK 1.5のリリースで処理時間に制限のないBackendsがリリースされ、さらにこれまで処理で利用したCPU時間に対して課金される仕組みが今後Instanceの起動(アサイン)時間に対して課金されるようになることが発表されました。 つまり、Instanceが1時間起動している間に100回リクエストを捌こうと10回捌こうと金額は変わらないということです。 従来であれば、cronでの最小間隔である1分間に1回処理を実行すると最初の数秒はCPU時間を消費して処理を実行して、残りの40~50秒は何もしない、イコール課金されないという方が理にかなっていました。 しかし、Instance時間になるとたとえ40~50秒間処理を行わなてもInstanceが起動されている間は常に課金されてしまいます。 そうなると、いかにCPUが働いていない40~50秒間を有効に使うか、ということが問題になります。 そこで考えたのが、無限ループです。 特定の処理を無限にループする事によって、Instanceの起動時間全てをループ内の処理に割り当てることができ、Instance時間を有効に活用することができます。 あいにく、まだInstance時間は通常のスケールするInstanceに対しては適用されませんが、BackendsではInstance時間でのQuotaの計算がされています。 将来的な変化に慣れるためにもちょっと実装してみました。 今回ははじめてFlaskというフレームワークを使って書いてみました。 これです。 ==========ここから========== @app.route('/') def put_queue():     taskqueue.add(url=url_for('work'),target='test')     return 'Done' @app.route('/work',methods=['POST']) def work():     for var in range(3600):         now = datetime.datetime.now() + d...

[Python][Google App Engine]db.Modelのput/getで勝手にmemcacheを使うよう拡張してみた

GAEを使う必ずみんな意識するのがDataStoreへのアクセスをいかに減らすか。 それすなわちキャッシュの使い方なり! と考えているわけですが、やることなんて以下の2点だと思います。 ・Model.put()するときにはmemcache.set()しろ ・Model.get()するまえにmemcache.get()しろ そこで、db.Modelを拡張しました。 まず、ModelAbsというdb.Modelを継承した中間のクラスを作って。 ========== class ModelAbs(db.Model):     def put_with_cache(self,key_name):         self.put()         memcache.set(key=key_name,value=self)         return self.key()     @classmethod     def get_with_cache(cls,key_names,**kwargs):         if isinstance(key_names,list) == False:             key_names = [str(key_names)]         models = list()         for key_name in key_names:             ent = memcache.get(key=key_name)             if ent == None:      ...

[Python][Google App Engine]Taskqueue.add()からのTaskqueue.add()-確認編-

以前POSTした 仮説 の確認編。 結論から言って、出来ました。 Taskqueue.add()した先の処理でさらにTaskqueue.add()した場合でも同じように非同期起動は可能でした。 バッチ処理の連携が可能になるわけですねー。 今の使い方は、こんな感じ。 cronでレート取得処理を起動 Taskqueue.add()でレート保存処理を起動 Taskqueue.add()でシグナル判定処理を起動 シグナル判定処理が1通貨ペアあたり複数あるので、シグナルごとにQueueを分けて実行しようと考えています。

[Python][Google App Engine]Taskqueue.add()からのTaskqueue.add()-仮説編-

非同期処理から非同期処理を起動したい。 なんてことがあるかどうかは知らないけど、気になってしまった。。。 データストアへのアクセスは遅いので、出来る限りTaskqueue.add()で非同期に寄せたい さらに並列処理もTaskqueue.add()で非同期に寄せたい この2点を満たそうとしてこんな構造にしてしまった。 cronからTaskqueue.add()で非同期処理を起動 DataStoreから後続の並列処理で共通で使うデータを取得 1段目の非同期処理で取得したデータを付加してTaskqueue.add()で後続の非同期処理を起動 雰囲気的にはできそう。考慮しなければいけない制約はこんな感じか。 リクエストのサイズに上限があるので、1段目の非同期処理から並列処理に全てのデータが渡せるか 処理するリクエストが増えて処理全体のオーバーヘッドが大きくなる 試してまた書きたい。

[Python][Google App Engine]Taskqueue.add()でTransientError

エラー対応メモ。 レート取得の飛び軽減対応を実施したあと昨日から運用していたレート取得で下記Errorがでた。 ========== "/base/python_runtime/python_lib/versions/1/google/appengine/api/taskqueue/taskqueue.py", line 1106, in __AddTasks     raise self.__TranslateError(e.application_error, e.error_detail) TransientError ========== 見るとどうやらTaskqueue.add()で出ているようだ。 リトライを書いたので、メモ。 count = 0 while True: try: taskqueue.add(queue_name='',url='',params={'':,'':,'':,'':,'':}) except TransientError: count += 1 if count <= 10: time.sleep(0.5) raise else: break 簡単だけどTransientErrorを拾って、10回までリトライ。 リトライ間隔は0.5秒。 この処理追加に当たってimport行の追加は以下。 import time from google.appengine.api.taskqueue.taskqueue import TransientError 以上です。