現在、「外部ID」(Facebook IDなど)を「内部(uu)ID」にマッピングする、小さくてシンプルな中央HTTPサービスを構築しています。これは、分析に役立つすべてのサービスで一意です。
「スタック」(flask + postgresql)の最初のプロトタイプは、1日以内に完了しました。ただし、サービスが(ほぼ)失敗せず、自動的にスケーリングされることを望んでいるため、GoogleAppEngineを使用することにしました。
1週間の読書、試行、ベンチマークの後に、この質問が浮かび上がります。
App Engine(NDBを使用)で「正常」と見なされる応答時間はどれくらいですか?
応答時間は、平均で一貫して500ミリ秒を超え、90パーセントで1秒をはるかに上回っています。
誰かが明らかな欠陥を指摘できることを期待して、以下にコードの簡略版を添付しました。自動スケーリングと分散ストレージは本当に気に入っていますが、私たちの場合、500msが実際に期待されるパフォーマンスであるとは想像できません。SQLベースのプロトタイプは、(ORMを使用している場合でも)無料のキャッシュレスpostgresqlを使用して、単一のHeroku dynoでホストされ、はるかに高速に(一貫して)応答しました。
以下のコードの同期バリアントと非同期バリアントの両方を試し、appstatsプロファイルを確認しました。非常に長い時間(50ms〜100ms)かかるのは常にRPC呼び出し(memcacheとデータストアの両方)であり、常に複数の呼び出しがあるという事実によってさらに悪化します(たとえば、mc.get()+ ds.get()+ ds.set( )書き込み時)。また、目立った増加なしに、タスクキューに可能な限り延期することを試みました。
import json
import uuid
from google.appengine.ext import ndb
import webapp2
from webapp2_extras.routes import RedirectRoute
def _parse_request(request):
if request.content_type == 'application/json':
try:
body_json = json.loads(request.body)
provider_name = body_json.get('provider_name', None)
provider_user_id = body_json.get('provider_user_id', None)
except ValueError:
return webapp2.abort(400, detail='invalid json')
else:
provider_name = request.params.get('provider_name', None)
provider_user_id = request.params.get('provider_user_id', None)
return provider_name, provider_user_id
class Provider(ndb.Model):
name = ndb.StringProperty(required=True)
class Identity(ndb.Model):
user = ndb.KeyProperty(kind='GlobalUser')
class GlobalUser(ndb.Model):
uuid = ndb.StringProperty(required=True)
@property
def identities(self):
return Identity.query(Identity.user==self.key).fetch()
class ResolveHandler(webapp2.RequestHandler):
@ndb.toplevel
def post(self):
provider_name, provider_user_id = _parse_request(self.request)
if not provider_name or not provider_user_id:
return self.abort(400, detail='missing provider_name and/or provider_user_id')
identity = ndb.Key(Provider, provider_name, Identity, provider_user_id).get()
if identity:
user_uuid = identity.user.id()
else:
user_uuid = uuid.uuid4().hex
GlobalUser(
id=user_uuid,
uuid=user_uuid
).put_async()
Identity(
parent=ndb.Key(Provider, provider_name),
id=provider_user_id,
user=ndb.Key(GlobalUser, user_uuid)
).put_async()
return webapp2.Response(
status='200 OK',
content_type='application/json',
body = json.dumps({
'provider_name' : provider_name,
'provider_user_id' : provider_user_id,
'uuid' : user_uuid
})
)
app = webapp2.WSGIApplication([
RedirectRoute('/v1/resolve', ResolveHandler, 'resolve', strict_slash=True)
], debug=False)
完全を期すために、(ほとんどデフォルトの)app.yaml
application: GAE_APP_IDENTIFIER
version: 1
runtime: python27
api_version: 1
threadsafe: yes
handlers:
- url: .*
script: main.app
libraries:
- name: webapp2
version: 2.5.2
- name: webob
version: 1.2.3
inbound_services:
- warmup