个人博客

Tornado异步的使用

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")
相关标签
回到顶部