Google App Engineの無料分って実際どれほどつかえるんだろう?

GoogleAppEngine(GAE)って最近ハマりだしたんですが
よく
 サーバの準備が・・
とか
 コストが・・
とか
 費用対効果は?・・
とか言われちゃうんですよね。。
まあしょうがない。。そこは気持ちぐっとおさえて、
回避策はないかなーってさがすと、
現状ではGAEはベストすぎるんじゃないかなー


もちろんAmazonEC2で立てるのもアリなんだけど
スケールを考えると面倒も付きまとうしね
否定をしてるわけではなくてです。。はい。
案件次第で使い分けです。


で、そのGAEですが
無料分が付いていて、1日6.5cpu hourとか、43,200,000requestsとか、、
あるわけですが、これの規模感って漠然とすくないなーなのか
いやいやぜんぜん足りるよなのかが
ちょっと自分の中で計りきれていなかったので
ちょっとしたサンプルを用意して使い切るまでを試してみようと
思った次第。


作ったサンプルは
アクセスされたら、データ保存用のシーケンシャルなIDを採番して
データを保存。
保存データもID列+値4つ+日付け1つってな感じで、まあ大きくもなく
小さくもないような感じ。
で、保存されたデータを最大100件Tableで表示させる。
ってなコードです。(GAEのサンプルとしてもいいかも)

from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.ext import db

import sys
stdin = sys.stdin
stdout = sys.stdout
reload(sys)
sys.setdefaultencoding('utf-8')
sys.stdin = stdin
sys.stdout = stdout

class Testdata(db.Model):
  id = db.IntegerProperty()
  data1 = db.StringProperty(multiline=False)
  data2 = db.StringProperty(multiline=False)
  data3 = db.StringProperty(multiline=False)
  data4 = db.StringProperty(multiline=False)
  
  date = db.DateTimeProperty(auto_now_add=True)

class Execcount(db.Model):
  cnt = db.IntegerProperty()


class test(webapp.RequestHandler):
  def get(self):


    #ID用のユニークな値を作成する
    execcounts = db.GqlQuery("SELECT * FROM Execcount")
    cnt = 0

    for execcount in execcounts:
      cnt = execcount.cnt
      
    if cnt == 0 :
      cnt = 1
      execcount = Execcount()
      execcount.cnt=1
      execcount.put()
    else:
      cnt = cnt + 1
      execcount.cnt = cnt
      execcount.put()

    #DBにデータを保存
    testdata = Testdata()
    testdata.id = cnt;
    testdata.data1 = "1234567890"
    testdata.data2 = "2345678901"
    testdata.data3 = "3456789012"
    testdata.data4 = "4567890123"

    testdata.put()


    #表示 100件まで表示させる
    self.response.out.write('<html><body>')
    self.response.out.write(cnt)

      
    testdatas = db.GqlQuery("SELECT * FROM Testdata order by date desc")
      
    self.response.out.write( "<table border=1>" )
    self.response.out.write( "<tr>" )

    self.response.out.write( "<td>" )
    self.response.out.write( "No")
    self.response.out.write( "</td>" )

    self.response.out.write( "<td>" )
    self.response.out.write( "id")
    self.response.out.write( "</td>" )
    
    self.response.out.write( "<td>" )
    self.response.out.write( "data1" )
    self.response.out.write( "</td>" )
    
    self.response.out.write( "<td>" )
    self.response.out.write( "data2" )
    self.response.out.write( "</td>" )
    
    self.response.out.write( "<td>" )
    self.response.out.write( "data3" )
    self.response.out.write( "</td>" )
    
    self.response.out.write( "<td>" )
    self.response.out.write( "data4" )
    self.response.out.write( "</td>" )
    
    self.response.out.write( "<td>" )
    self.response.out.write( "date" )
    self.response.out.write( "</td>" )
      
      
      
    self.response.out.write( "</tr>" )

    linecnt = 0
    for testdata in testdatas:
      if linecnt>100:
        break
      linecnt = linecnt + 1
      self.response.out.write( "<tr>" )
      
      self.response.out.write( "<td>" )
      self.response.out.write( linecnt )
      self.response.out.write( "</td>" )

      self.response.out.write( "<td>" )
      self.response.out.write( testdata.id)
      self.response.out.write( "</td>" )
      
      self.response.out.write( "<td>" )
      self.response.out.write( testdata.data1)
      self.response.out.write( "</td>" )
      
      self.response.out.write( "<td>" )
      self.response.out.write( testdata.data2)
      self.response.out.write( "</td>" )
      
      self.response.out.write( "<td>" )
      self.response.out.write( testdata.data3)
      self.response.out.write( "</td>" )
      
      self.response.out.write( "<td>" )
      self.response.out.write( testdata.data4)
      self.response.out.write( "</td>" )
      
      self.response.out.write( "<td>" )
      self.response.out.write( testdata.date)
      self.response.out.write( "</td>" )
      
      
    self.response.out.write( "</table>" )

    self.response.out.write('</body></html>')




#URLハンドラ
application = webapp.WSGIApplication(
    [('/test', test)],
    debug=True)

def main():
  run_wsgi_app(application)

if __name__ == "__main__":
  main()

で、これを100回Wgetで連続して呼び出すシェルスクリプトを組んでで
2分おきに起動させてみています。


で2時間程度走らせてみたところ、こんな感じでした。


CPUTimeが一番消費が早い・・・
その反面ほかはまったく減らない・・


このようなプログラムだと、
一日の無料分では14000リクエスト処理が出来そうな様子ですね。
1分間10リクエスト程度。


メインでは使い切っちゃうけど、
限定的なアンケートとかほんのちょっとしたものなら
いけそうな雰囲気です。



1分間10リクエストから60リクエストくらい処理させたいなー
だったら、残り6.5cpuHour*5倍欲しいので
6.5*5=32.5cpuHour
32.5* $0.10/hour=$3.25 ( http://code.google.com/intl/ja/appengine/docs/billing.html#Billable_Quota_Unit_Cost )
$3.25*31day=$100.750
$100*90円=9000円


月額1万円くらいってところですね
なるーほど
レンタルサーバを借りる感じの予算感ですね


追伸
CPU使い切ると管理画面のDatastoreの閲覧も
出来なくなるのねorz


ほとんど使っていなくても・・・
Datastore CPU Time 0% 0% 5.64 of 2,487.70 CPU hours Limited