App Engine Dev Server数据存储区的更新速度不够快?

时间:2013-09-01 23:00:11

标签: python google-app-engine google-cloud-datastore

问题:数据存储更新速度太慢 - 在提交创建实体的表单后,需要在显示数据存储区中的实体的结果页面上点击重新加载。

预期行为:实体应该出现在查询中,因为我正在使用NDB来自动缓存数据存储。

问题重播步骤

  1. 在MacApp的GoogleAppEngineLauncher 1.8.3中创建一个默认项目(我的操作系统版本是10.8.4)并将下面的代码粘贴到“main.py”
  2. 运行项目并访问根URL。
  3. 在表单中输入一个数字,然后点击提交。
  4. 您会看到文本“这是实体列表:...结束列表。”
  5. 在您的浏览器上点击重新加载。
  6. 现在您将看到文本“这是实体列表:[您输入的数量] ...结束列表。”
  7. 预期行为的说明

    由于NDB自动使用内存缓存,因此不应执行步骤4和步骤5。单击表单上的“提交”后,您输入的数字应该会显示出来。我也使用常规的appengine DB观察了这种行为,我知道我可以用memcache解决它。

    以下是一些代码,您可以使用AppEngineLauncher创建的默认main.py来复制此问题:

    import webapp2
    from google.appengine.ext import ndb
    
    class SmallModel(ndb.Model):
        n = ndb.IntegerProperty(required=True)
        stamp = ndb.DateTimeProperty(auto_now_add=True)
    
    class MainHandler(webapp2.RequestHandler):
        def get(self):
            self.response.write('Hello world. Simple form. <form method="post"><input name="n" type="number"><input type="submit"></form>')
        def post(self):
            entity = SmallModel(n=int(self.request.get('n')))
            entity.put()
            self.redirect('/list')
    
    class List(webapp2.RequestHandler):
        def get(self):
            self.response.out.write("here's a list of entities:")
            entities = SmallModel.query()
            for entity in entities.iter():
                self.response.out.write(" %s " % entity.n)
            self.response.out.write("...end list.")
    
    app = webapp2.WSGIApplication([
        ('/', MainHandler),
        ('/list',List)
    ], debug=True)
    

    任何帮助/建议?先感谢您!我已经能够在我测试的两个浏览器中重现这个问题 - Chrome和Safari。

4 个答案:

答案 0 :(得分:3)

我设法得到了我预期的行为,我的更新代码如下。我从具有我期望的行为的“留言板”示例代码中提取了一个提示,并设置了父键。我还深入研究了NDB文档。设置父键可以实现我期望的一致性,但限制写入每秒一次(我假设这意味着给定父键的所有子项,而不是给定模型的所有实体)。

这是我改变以消除步骤4和5.我只是在新实体上设置父键,并使用此父键执行祖先查询。 (当然,这是用于说明一点的超级最小代码,我对创建数字列表的模型没有真正的兴趣。;))

import webapp2
from google.appengine.ext import ndb

def parent_key():
    return ndb.Key('My','Entities')

class SmallModel(ndb.Model):
    n = ndb.IntegerProperty(required=True)
    stamp = ndb.DateTimeProperty(auto_now_add=True)

class MainHandler(webapp2.RequestHandler):
    def get(self):
        self.response.write('Hello world. Simple form. <form method="post"><input name="n" type="number"><input type="submit"></form>')
    def post(self):
        entity = SmallModel(parent=parent_key(),n=int(self.request.get('n')))
        entity.put()
        self.redirect('/list')

class List(webapp2.RequestHandler):
    def get(self):
        self.response.out.write("here's a list:")
        entities = SmallModel.query(ancestor=parent_key())
        for entity in entities.iter():
            self.response.out.write(" %s " % entity.n)
        self.response.out.write("...end list.")

app = webapp2.WSGIApplication([
    ('/', MainHandler),
    ('/list',List)
], debug=True)

感谢阅读和参与。

答案 1 :(得分:2)

这是最终一致性的行为。我不确定你要做什么,也许你可以改变你的数据建模,所以fetch总是非常一致。

在您的数字列表示例中,您可以将它们存储在一个实体的ListProperty中,这样您就可以始终以强一致的方式获取它

答案 2 :(得分:1)

ndb非常明确,它不会在memcache中查找查询结果。只有get()从memcache中获取实体。

特别是文档说 -

  

查询不会在任何缓存中查找值。但是,查询结果   如果缓存策略这样说,则写回到上下文缓存中   (但永远不要Memcache)。

https://developers.google.com/appengine/docs/python/ndb/cache无文字缓存部分。

另见这个关于同一个ndb和memcache的问题,How automatic NDB caching works?

您可能会在生产中发现同样的问题。这是因为最终在开发环境中模拟了最终的一致性。您需要使用get来确保一致性或处理查询结果的潜在延迟。

答案 3 :(得分:1)

我遇到了类似的问题。谢谢你的解决方案。 顺便说一下,我认为GAE文档已经从原来的解决方案中改变了。

对于这一行:

entities = SmallModel.query(ancestor=parent_key())

应该是:

entities = SmallModel.ancestor(parent_key())