Tornado异步的使用
作者:向前的步伐 / 发表: 2019年8月19日 22:32 / 更新: 2019年8月19日 23:14 / tornado / 阅读量:752
Tornado最受关注的功能,就是它的异步处理web请求的能力,它使得处理非阻塞请求更加容易,最终导致更高效的处理以及更好的可扩展性。
大部分web应用都是阻塞的,就是说当一个请求被处理时,这个进程就会被挂起直到请求处理完成。在大多数情况下,只要这个请求处理的足够快,这个阻塞的问题就不需要被关注。但是对于一些需要一定时间来完成的请求,这意味着如果下个请求需要等待前一个请求完成才可继续,那性能上就明显有很大的问题。
不过,Tornado给了我们更好的方式来处理这种情况。应用程序在处理等待第一个处理完成的过程中,让IO循环打开以便服务与其他的客户端请求,直到处理完成时启动一个请求并给予反馈,而不是等待请求完成的过程中挂起程序。
异步回调的方式
class AsyncHandler(tornado.web.RequestHandler):
@tornado.web.asynchronous
def get(self):
http_client = AsyncHTTPClient()
http_client.fetch("http://example.com",
callback=self.on_fetch)
def on_fetch(self, response):
do_something_with_response(response)
self.write("hello")
self.finish()
AsyncHTTPClient的fetch方法并不返回调用结果。取而代之的是它指定了一个callback参数,这里指定的方法将在HTTP请求完成时被调用,并使用HTTPResponse作为其参数。
Tornado默认情况下,在方法返回时会关闭客户端的连接。但是在我们处理回调函数的异步请求时,我们需要保持连接状态直到回调执行完毕。代码中@tornado.web.asynchronous装饰器就是来告诉Tornado保持连接状态,此时Tornado将不会自己关闭连接。而我们需要在回调函数显示的调用finish()方法来告诉Tornado关闭连接。
异步生成器的方式
class GenAsyncHandler(tornado.web.RequestHandler):
@tornado.web.asynchronous
@tornado.gen.engine
def get(self):
http_client = AsyncHTTPClient()
response = yield http_client.fetch("http://example.com")
do_something_with_response(response)
self.write("hello")
self.finish()
这里我们使用yield关键字以及AsyncHTTPClient的实例对象,允许在HTTP请求进行中执行其他任务。当HTTP请求完成时,RequestHandler方法在其停止的地方继续执行,这种方式使代码更像按顺序执行,也更容易理解。
当然在Tornado3.1以上的版本,可以直接使用@tornado.gen.coroutine 来代替 @tornado.web.asynchronous,代码如下:
class GenAsyncHandler(tornado.web.RequestHandler):
@tornado.gen.coroutine
def get(self):
http_client = AsyncHTTPClient()
response = yield http_client.fetch("http://example.com")
do_something_with_response(response)
self.write("hello")