Python 这是ndb异步urlfetch tasklet的一个很好的用例吗?
我想转到Python 这是ndb异步urlfetch tasklet的一个很好的用例吗?,python,google-app-engine,python-2.7,urlfetch,Python,Google App Engine,Python 2.7,Urlfetch,我想转到ndb,一直想知道是否使用asyncurlfetch。我不确定我是否完全理解它是如何工作的,因为文档有点糟糕,但是对于这个特定的用例来说,它似乎很有希望 目前我像这样使用asyncurlfetch。它与实际的线程化或并行代码相去甚远,但与仅顺序请求相比,它仍然显著提高了性能 def http_get(url): rpc = urlfetch.create_rpc(deadline=3) urlfetch.make_fetch_call(rpc,url) retur
ndb
,一直想知道是否使用asyncurlfetch
。我不确定我是否完全理解它是如何工作的,因为文档有点糟糕,但是对于这个特定的用例来说,它似乎很有希望
目前我像这样使用asyncurlfetch
。它与实际的线程化或并行代码相去甚远,但与仅顺序请求相比,它仍然显著提高了性能
def http_get(url):
rpc = urlfetch.create_rpc(deadline=3)
urlfetch.make_fetch_call(rpc,url)
return rpc
rpcs = []
urls = [...] # hundreds of urls
while rpcs < 10:
rpcs.append(http_get(urls.pop()))
while rpcs:
rpc = rpcs.pop(0)
result = rpc.get_result()
if result.status_code == 200:
# append another item to rpcs
# process result
else:
# re-append same item to rpcs
def http_get(url):
rpc=urlfetch.create_rpc(截止日期=3)
urlfetch.make_fetch_调用(rpc,url)
返回rpc
rpcs=[]
URL=[…]#数百个URL
rpcs<10时:
append(http_get(url.pop()))
而RPC:
rpc=rpcs.pop(0)
result=rpc.get_result()
如果result.status_code==200:
#将另一项附加到RPC
#过程结果
其他:
#将同一项重新附加到RPC
请注意,此代码已简化。实际的代码捕获异常,进行一些额外的检查,并且只尝试重新附加同一项几次。这对这个案子没有区别
我应该补充一点,处理结果不涉及任何
db
操作。实际上是的,在这里使用异步urlfetch是个好主意。工作原理(粗略解释):
-您的代码达到了异步调用的程度。它触发长后台任务,不等待结果,而是继续执行。
-任务在后台工作,当结果准备就绪时,它将结果存储在何处,直到您请求它为止
简单的例子:
def get_fetch_all():
urls = ["http://www.example.com/", "http://mirror.example.com/"]
ctx = ndb.get_context()
futures = [ctx.urlfetch(url) for url in urls]
results = ndb.Future.wait_all(futures)
# do something with results here
如果您想将结果存储在ndb中并使其更优化,那么最好为此编写自定义tasklet
@ndb.tasklet
def get_data_and_store(url):
ctx = ndb.get_context()
# until we don't receive result here, this function is "paused", allowing other
# parallel tasks to work. when data will be fetched, control will be returned
result = yield ctx.urlfetch("http://www.google.com/")
if result.status_code == 200:
store = Storage(data=result.content)
# async job to put data
yield store.put_async()
raise ndb.Return(True)
else:
raise ndb.Return(False)
在第一个示例中,您可以将这个tasklet与循环结合使用。您应该获得ther/false值的列表,指示获取成功
我不确定这将在多大程度上提高整体生产力(这取决于谷歌方面),但它应该这样做 如果您问在您的用例中使用ndb是否有性能,那么解决方案不是度量性能吗?不清楚你在问什么,我有个问题。在您的示例中,当我有100个URL并与列表理解一样使用urlfetch时,服务器不会立即启动100个连接吗?我是否可以将此限制为一次连接不超过10个(如我发布的代码中所示),以避免同时请求过多而使另一台服务器紧张?我可能只需要将
url
拆分为10个列表,但在处理结果后,我无法将列表重新填充为10个项目。看起来我可以把我的代码和自定义的Tasklet结合起来使用,但这可能没有任何好处。据我所知,如果你触发100个连接,你将无法控制它们。它们由异步控制。经纪人。所以,如果您需要将bulk限制为10,那么您需要获取前10个URL,将它们提交给处理,等待结果,然后获取下一个10,以此类推……实际上,您的代码实际上是在进行异步调用,所以在这里使用ndb的主要原因是——使保存数据也异步,但HTTP调用比存储数据长得多(我认为谷歌的云存储足够快),所以我认为您不会从中受益太多。我最好尝试调整批处理大小,看看它有什么帮助。嗯,您是对的。我希望这是一种更优雅的使用异步urlfetch的方法,但如果不涉及ndb
操作,则使用Tasklet似乎毫无意义。您实际上已经在使用异步urlfetch,因此无需添加任何内容。