在Google App Engine中,调用put_async()需要get_result()吗?
随着GAE 1.5.0的新版本发布,我们现在有了一种简单的方法来进行异步的数据存储调用。请问在调用了put_async之后,我们是否需要调用get_result()
?
举个例子,如果我有一个叫MyLogData
的模型,我能否在我的处理程序返回之前直接调用:
put_async(MyLogData(text="My Text"))
而不调用相应的get_result()
呢?GAE会在将结果发送给客户端之前自动等待任何未完成的调用吗?
需要注意的是,我并不太关心处理错误的情况。也就是说,我不介意这些存储操作中有些失败。
3 个回答
我也不太清楚,但这样做是有效的:
import datetime
from google.appengine.api import urlfetch
def main():
rpc = urlfetch.create_rpc()
urlfetch.make_fetch_call(rpc, "some://artificially/slow.url")
print "Content-type: text/plain"
print
print str(datetime.datetime.now())
if __name__ == '__main__':
main()
这个远程网址会先等待3秒钟,然后给我发一封邮件。App Engine的处理程序会立刻返回,而远程网址会按预期完成。因为这两个服务使用的是相同的底层RPC框架,所以我猜测数据存储的行为也差不多。
这是个好问题。不过,也许Nick或者其他谷歌的员工能给出明确的答案。
我觉得要确定 get_result()
是否必要,可能没有什么确凿的方法,除非GAE团队的人来确认。不过我觉得它可能不是必需的。下面是我测试的过程。
我写了一个简单的处理程序:
class DB_TempTestModel(db.Model):
data = db.BlobProperty()
class MyHandler(webapp.RequestHandler):
def get(self):
starttime = datetime.datetime.now()
lots_of_data = ' '*500000
if self.request.get('a') == '1':
db.put(DB_TempTestModel(data=lots_of_data))
db.put(DB_TempTestModel(data=lots_of_data))
db.put(DB_TempTestModel(data=lots_of_data))
db.put(DB_TempTestModel(data=lots_of_data))
if self.request.get('a') == '2':
db.put_async(DB_TempTestModel(data=lots_of_data))
db.put_async(DB_TempTestModel(data=lots_of_data))
db.put_async(DB_TempTestModel(data=lots_of_data))
db.put_async(DB_TempTestModel(data=lots_of_data))
self.response.out.write(str(datetime.datetime.now()-starttime))
我在一个高复制应用上运行了很多次。
每次数据都能成功写入,这让我相信,除非数据存储那边出现故障(这种情况不太可能),数据应该会被写入。
有个有趣的地方是,当我用 put_async()
写入数据时(?a=2
),处理请求的时间平均比用 put()
(?a=1
)快大约2到3倍(这不是一个很科学的测试,只是我大致观察的结果)。
但是 cpu_ms
和 api_cpu_ms
对于 ?a=1
和 ?a=2
是一样的。
从日志来看:
ms=440 cpu_ms=627 api_cpu_ms=580 cpm_usd=0.036244
对比
ms=149 cpu_ms=627 api_cpu_ms=580 cpm_usd=0.036244
在客户端,看请求的网络延迟时,结果也是一样的,也就是说 ?a=2
的请求至少快了2倍。对客户端来说绝对是个好消息……但在服务器端似乎没有什么好处。
有没有GAE团队的人愿意评论一下?