GAE中的高端RPC调用是否正常?
我有几个问题希望能够巩固我对GAE“幕后”的理解。 目前在我的应用程序中,我需要检索一组258个实体大小的数据。 我已将indexed = False设置为此实体的Model类的相应属性。 我正在使用Nick Johnson博客描述的序列化/反序列化实体技术。 我为了示例的目的而将代码作为通用的:
def serialize_entities(models):
if not models:
return None
elif isinstance(models, db.Model):
return db.model_to_protobuf(models).Encode()
else:
return [db.model_to_protobuf(x).Encode() for x in models]
def deserialize_entities(data):
if not data:
return None
elif isinstance(data, str):
return db.model_from_protobuf(entity_pb.EntityProto(data))
else:
return [db.model_from_protobuf(entity_pb.EntityProto(x)) for x in data]
class BatchProcessor(object):
kind = None
filters = []
def get_query(self):
q = self.kind.all()
for prop, value in self.filters:
q.filter("%s" % prop, value)
q.order("__key__")
return q
def run(self, batch_size=100):
q = self.get_query()
entities = q.fetch(batch_size)
while entities:
yield entities
q = self.get_query()
q.filter("__key__ >",entities[-1].key())
entities = q.fetch(batch_size)
class MyKindHandler(webapp2.RequestHandler):
def fill_cache(self, my_cache):
entities = []
if not my_cache:
# retry in case of failure to retrieve data
while not my_cache:
batch_processor = BatchProcessor()
batch_processor.kind = models.MyKind
batch = batch_processor.run()
my_cache = []
for b in batch:
my_cache.extend(b)
# Cache entities for 10 minutes
memcache.set('MyKindEntityCache', serialize_entities(my_cache),
600)
for v in my_cache:
# There is actually around 10 properties for this entity.
entities.append({'one': v.one, 'two': v.two})
mykind_json_str = simplejson.dumps({'entities':entities})
# Don't set expiration - will be refreshed automatically when
# entity cache is.
memcache.set('MyKindJsonCache', mykind_json_str)
return mykind_json_str
def get(self):
my_cache = deserialize_entities(memcache.get('MyKindEntityCache'))
if not my_cache:
# Create entity & json cache
self.fill_cache(my_cache)
mykind_json_str = memcache.get('MyKindJsonCache')
if not mykind_json_str:
mykind_json_str = self.fill_cache(my_cache)
self.response.write(mykind_json_str)
当我看看appstats时,它显示了对检索这些数据的处理程序的ajax调用花费了大量的时间。 当该处理程序需要刷新数据存储区中的数据时(每10分钟实体缓存过期),将调用434个RPC调用,否则将有2个RPC调用检索每个memcaches。 用于刷新数据的appstats是:
real=10295ms cpu=13544ms api=5956ms overhead=137ms (434 RPCs) datastore_v3.Get 428 memcache.Get 2 memcache.Set 2 datastore_v3.RunQuery 2
我想我理解这些调用大部分都在做什么,但是,与datastore_v3.RunQuery关联的datastore_v3.Get调用会让我感到困惑,因为它们代表了我认为他们所做的事情。 它们是否意味着这些是对数据存储的单个.get()调用? 我认为当你调用.fetch(batch_size)时,你会收到一个带有1个调用的“批处理”......不仅如此,为什么这些调用的数量要比数据存储中的实体数量多150给定的种类?
作为一个方面说明,我在了解查询游标之前编写了BatchProcessor类,并尝试将它们交换出来以查看性能是否更好,但它不仅保持不变,而且因为将游标存储在memcache中而增加了RPC的数量。
任何对我可能忽略的东西的洞察力都非常感谢!
编辑 - 来自appstats的更多细节:
在测试这个并仔细检查appstats时,我发现在创建json响应字符串时,我对每个MyKind的.parent()调用都大大增加了RPC,并且每个MyKind都有2个ReferenceProperties,这些ReferenceProperties可变地具有或不具有有价值。 我使用这个.parent()调用来返回MyKind数据的响应中的公司名称,如果ReferenceProperties有值,我也可以获取它们的名称。 我没有意识到调用.parent().name,.refprop1.name和.refprop2.name会为每个数据存储的数据存储区执行一个单独的datastore_V3.Get。 我认为父母和引用属性的数据与MyKind对象的原始查询一起返回。 有没有办法实现这一点,或者我需要在MyKind中创建3个其他属性来有效访问这些名称属性?
链接地址: http://www.djcxy.com/p/23217.html上一篇: High # of RPC calls in GAE, is this normal?
下一篇: Google App Engine: efficient large deletes (about 90000/day)