《Introduction to Tornado》笔记07 — 异步web服务
异步web请求
大部分 Web 应用(包括我们之前的例子)都是阻塞性质的,也就是说当一个请求被处理时,这个进程就会被挂起直至请求完成。在大多数情况下,Tornado 处理的 Web 请求完成得足够快使得这个问题并不需要被关注。然而,对于那些需要一些时间来完成的操作(像大数据库的请求或外部 API),这意味着应用程序被有效的锁定直至处理结束,很明显这在可扩展性上出现了问题。
不过,Tornado 给了我们更好的方法来处理这种情况。应用程序在等待第一个处理完成的过程中,让 I/O 循环打开以便服务于其他客户端,直到处理完成时启动一个请求并给予反馈,而不再是等待请求完成的过程中挂起进程。
异步的一个实例 —— 异步的server与异步client爬虫
使用旧版本的写法:
原生协程VS装饰器协程
Python 3.5引入了async和await关键字(使用这些关键字的函数也称为“native coroutines”)。 为了与旧版本的Python兼容,您可以使用tornado.gen.coroutine装饰器来使用“decorated”或“yield-based”的协程。
尽可能使用原生协程。 仅在需要与旧版本的Python兼容时才使用装饰器协程。Tornado文档中的示例通常使用原生形式。
两种形式之间的转换通常很简单:
# Decorated: # Native: # Normal function declaration # with decorator # "async def" keywords @gen.coroutine def a(): async def a(): # "yield" all async funcs # "await" all async funcs b = yield c() b = await c() # "return" and "yield" # cannot be mixed in # Python 2, so raise a # special exception. # Return normally raise gen.Return(b) return b
其它两种形式的协程区别:
– 原生协程通常更快。
– 原生协程可以使用async for
和async
语句,这使得某些模式更加简单。
– 除非yield
或await
它们,否则原生协程根本不会运行。装饰器协程一旦被调用就可以“在后台”开始运行。请注意,对于这两种协程,使用await
或yield
很重要,这样任何异常才能正常抛出。
– 装饰器协程与concurrent.futures包有额外的集成,允许直接生成executor.submi
的结果。对于原生协程,请改用IOLoop.run_in_executor
。
– 装饰器协程通过产生列表或字典来支持等待多个对象的一些简写。使用tornado.gen.multi在原生协程中执行此操作。
– 装饰器协程可以支持与其他软件包的集成,包括通过转换函数注册表的Twisted。要在原生协程中访问此功能,请使用tornado.gen.convert_yielded
。
– 装饰器协程总是返回一个Future对象。原生协程返回一个不是Future的等待对象。在Tornado中,两者大多可以互换。
—— 摘自:https://www.shangyexin.com/2019/01/15/coroutines/