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

[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() + datetime.timedelta(hours=9)
        str_now = datetime.datetime.strftime(now,'%Y%m%d%H%M%S')
        logging.info(str_now)
        key = 'SPOTS:'+str_now
        logging.info(key)
        rate = GetCurrentRate()
        logging.info(str(rate))
        SPOTS(key_name=key
              ,update=now
              ,USDJPY = rate['USDJPY']
              ,EURJPY = rate['EURJPY']
              ,EURUSD = rate['EURUSD']
              ,AUDJPY = rate['AUDJPY']
              ,GBPJPY = rate['GBPJPY']
              ,NZDJPY = rate['NZDJPY']
              ,CADJPY = rate['CADJPY']
              ,CHFJPY = rate['CHFJPY']
              ,HKDJPY = rate['HKDJPY']
              ,GBPUSD = rate['GBPUSD']
              ,USDCHF = rate['USDCHF']
              ,ZARJPY = rate['ZARJPY']).put_with_cache(key_name=key)
        time.sleep(0.7)
    return 'Done'
==========ここまで==========

簡単なもんです。
まず、通常のcronでput_queue()を叩きます。
次にBackends側でTaskQueueのTaskを受け取り(POST)、3600回繰り返し実行します。

ループの中では為替レートの取得、DataStoreへのput()を行っています。

ログで見る限り、DataStoreへのput()にかかるCPU時間が400~600ms程度。
そこにtime.sleep(0.7)で0.7秒=700msの待ちを加えて約1000~1300ms間隔で実行します。

DataStoreを見るとループ1回で実質1.1秒程度かかっていて、ちょうど1秒間隔の為替レートが取得できています。

上記実行回数(3600回)を考えればもうお分かりのように、1時間に1回cronでput_queue()を叩いてやるように設定してやるだけです。

これでBackendsでの無限ループ処理を簡単に実装できますね。

コメント

このブログの人気の投稿

[Python]redis-pyでRedis Pub/Sub実装

前から面白そうと思っていたRedisのPub/Sub機能。 redis-pyでどう実装すれば使えるか確認してみた。 ■Pub/Subについて http://ja.wikipedia.org/wiki/出版-購読型モデル ■pub.py from redis import StrictRedis def publish(channel,msg): """ redis-pyにはPUBLISHするためのメソッドがないので、 Redisのコマンドをそのまま実行する為のクラスを使う。 """ sr=StrictRedis() """ 第1引数にRedisのコマンド、第2引数以降は そのコマンドの引数をそのままセット """ sr.execute_command("PUBLISH",channel,msg) if __name__=="__main__": # チャネル"hoge"に"Hello"というメッセージを出版(Publish) publish("hoge","Hello") ■sub.py from redis import Redis def listen(channel): r=Redis() ps=r.pubsub() ps.subscribe(channel) while True: for i in ps.listen(): print i["data"] if __name__=="__main__": # チャネル"hoge"を購読(Subscribe) listen("hoge") ■実行方法・実行結果 (ターミナル1-準備) [user@localhost ~]# python sub.py 1 # => チャネ

[Python]ポートフォリオの達人ランキング取得プログラム

今日は、投資ブログで公開している三菱UFJ投信主催の「投資にチャレンジ!!ポートフォリオの達人」から毎日更新される運用成績を取得するプログラムを作りました。これまで毎日コンテストの個人ページからコピー&ペーストして作成していた記事の成績部分をプログラムを実行するだけで作成できます。 ■投資ブログの記事 この記事の作成を効率化します。 http://mockuninvestment.blogspot.jp/2013/06/201367.html ■コマンド実行方法 取得したい参加者の個人ページのURLをプログラムに渡してあげるだけ。 python muam_contest.py http://contest.muam.jp/app/ranking/detail?dsp=eac8d83669d6cca1 ■出力内容 コマンド入力後、Enterを押して実行すると以下のフォーマットが出力されます。 2013/6/7更新 ポートフォリオの達人ランキング ========== ランキング(6/7更新):198位 評価額:100,357円 リターン:0.47% リスク:10.63% リターン ÷ リスク:0.04(0.04435225290) ========== http://contest.muam.jp/app/ranking/detail?dsp=eac8d83669d6cca1 あとはブログに張り付けるだけです。投稿用のアドレスにメール送信するプログラムと組み合わせれば、完全自動化できてしまいますね。 ■ソース #!/usr/local/bin/python #coding: utf-8 from bs4 import BeautifulSoup import urllib2,re,unicodedata,sys template=u"""2013/%(date)s更新 ポートフォリオの達人ランキング ========== ランキング(%(date)s更新):%(rank)s 評価額:%(amount)s リターン:%(ret)s リスク:%(risk)s リターン ÷ リスク:%(riskreturnratio)s ========== %(url)s""&

[OS]VirtualBoxでCentOS6.5(x86_64)がKernel panicを起こした

完全に対処療法。 恥ずかしながら自分では原因がわかっていない。 忘れないようにメモしておく。 いろいろ設定したあと、何度目かの再起動のタイミングでKernel panicが発生して起動しないという事象が発生。 こちらの方法でなんとか起動させて。 [CentOS] SELinux 無効化後のカーネルパニック http://kuni255.blogspot.jp/2013/04/centos-selinux.html こちらの通り、/boot/grub/grub.confに設定を追加。 Kernel panic – not syncing: Attempted to kill init! http://h2np.net/mynotebook/post/130 設定変更後、以下の操作をそれぞれ10回ほど試した限りでは再発していません。  (1)halt+起動 (2)reboot 追記:と思ったらまた発生した。なんかもう解決できる気がしない。