Pulpcode

捕获,搅碎,拼接,吞咽

0%

tornado并行多个异步请求的坑

之前的博客,写到过这个技巧,就是tornado可以让多个请求,并行发出。

只所以这样,是因为比如你要n个接口的返回结果:

1
2
3
4
response1 = yield http_client.fetch(url1)
response2 = yield http_client.fetch(url2)
...
responsen = yield http_client.fetch(urln)

那么你这样实现之后,虽然你的服务是异步的,但是却假定他们的请求之间存在某种先后关系,也就是说response1获得了,才可以获得response2。
但是实际上n个异步请求是可以并行的,而且tornado也支持这种写法(列表和字典都可以):

1
response1, response2,... responsen = yield [http_client.fetch(url1) ,  http_client.fetch(url2), ...... ,http_client.fetch(url2) ]

但是有一个坑,就是如果其中一个请求抛异常了,那么你的其它请求也就被“污染”了,你无法获得其它可用的结果,这种场景类似于解析很多的数据行,即使有几条坏数据会让你抛异常,但你完全可以跳过它们。

这个有一个技巧就是对每个请求进行一次包装。

1
2
3
4
5
6
7
8
9
10
11
@gen.coroutine
def safty_fetch(fetch_routine):
try:
response = yield fetch_routine
except Exception as exc:
raise gen.Return(exc)
else:
raise gen.Return(response)


response1, response2,......, responsen = yield [safty_fetch(http_client.fetch(url1)), safty_fetch(http_client.fetch(url2)), ......, safty_fetch(http_client.fetch(urln)) ]

这样,你就可以对每个请求进行筛选判断了。

1
2
3
4
if isinstance(response1, Exception):
...
else:
...