हम वर्तमान में एक छोटी और सरल केंद्रीय HTTP सेवा का निर्माण कर रहे हैं जो "बाहरी पहचान" (एक फेसबुक आईडी की तरह) को "आंतरिक (यूयू) आईडी" पर मैप करता है, जो विश्लेषिकी में सहायता के लिए हमारी सभी सेवाओं में अद्वितीय है।जीएई/एनडीबी से किस प्रतिक्रिया समय की उम्मीद की जा सकती है?
"हमारे स्टैक" (फ्लास्क + पोस्टग्रेस्क्ल) में पहला प्रोटोटाइप एक दिन के भीतर किया गया था। लेकिन चूंकि हम चाहते हैं कि सेवा (लगभग) कभी विफल न हो और स्वचालित रूप से स्केल न करें, हमने Google App Engine का उपयोग करने का निर्णय लिया।
& पढ़ने & इस सवाल बेंचमार्किंग की कोशिश कर के एक सप्ताह के बाद उभर रहे हैं:
क्या प्रतिक्रिया समय (NDB) के साथ अनुप्रयोग इंजन पर विचार कर रहे हैं "सामान्य"?
हम प्रतिक्रिया समय है कि अच्छी तरह 90percentile में 1s ऊपर पर औसत और लगातार ऊपर 500ms हैं हो रही है।
मैंने नीचे दिए गए हमारे कोड का एक अलग संस्करण संलग्न किया है, उम्मीद है कि कोई स्पष्ट दोष बता सकता है। हम वास्तव में ऑटोस्केलिंग और वितरित भंडारण पसंद करते हैं, लेकिन हम कल्पना नहीं कर सकते कि 500ms वास्तव में हमारे मामले में अपेक्षित प्रदर्शन है। एसक्यूएल आधारित प्रोटोटाइप ने मुफ्त, कैश-कम पोस्टग्रेस्क्ल (यहां तक कि एक ओआरएम के साथ) का उपयोग करके एक ही हरोकू डिनो पर होस्ट किया, जो बहुत तेज (लगातार) प्रतिक्रिया देता है।
हमने नीचे दिए गए कोड के सिंक्रोनस और एसिंक्रोनस वेरिएंट दोनों की कोशिश की और ऐपस्टैट प्रोफ़ाइल को देखा। यह हमेशा आरपीसी कॉल (मेमचेचे और डेटास्टोर दोनों) है जो बहुत लंबा (50 एमएमएस -100 एमएमएस) लेते हैं, इस तथ्य से भी बदतर बनाते हैं कि हमेशा कई कॉल होते हैं (उदाहरण के लिए 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
याप, आप dev_appserver के प्रदर्शन (ssd पर sqlite ...) के बारे में सही हैं, इसलिए हम उत्पादन (यहां तक कि भुगतान किए गए खाते) पर भी परीक्षण करते हैं। पुनरावृत्तियों के बारे में हम आमतौर पर परीक्षण लगभग 5 मिनट तक चलते रहते हैं। हम यह भी सुनिश्चित करने का प्रयास करते हैं कि प्रत्येक रन में हिट/मिस की तुलनीय मात्रा होती है (रन के बीच डेटास्टोर/मेमकैच खाली करके या 'provider_user_id' श्रेणी के साथ खेलकर)। – selkie
एक नोट: यदि आप एक बड़ा बेंचमार्क चला रहे हैं, तो आपको धीरे-धीरे अपने ट्रैफिक को स्पिन करना होगा (5-10 मिनट कहें) और फिर यथार्थवादी प्रभावों को मापने के लिए इसे थोड़ी देर (अन्य 5-10 मिनट) तक बनाए रखें। जब आपका लोड 0 से 100 हो जाता है तो ऐप इंजन तत्काल आवश्यक उदाहरणों को नहीं बढ़ाएगा; अस्थिरता से बचने के लिए इस प्रक्रिया पर "गवर्नर" है। –
मैंने अभी एचआरडी के "एक प्रति प्रति समूह समूह" व्यवहार के बारे में पढ़ा है। उपरोक्त कोड में, क्या वह हमारे मुद्दों की व्याख्या नहीं करेगा? वहां केवल कुछ मुट्ठी भर प्रदाता (ज्यादातर फेसबुक) हैं, और _Identity_ में माता-पिता के रूप में _Provider_ है, जिससे उन्हें _entity group_ बना दिया जाता है? – selkie