第12节,tornado 使用AsyncHTTPClient 发送异步请求

AsyncHTTPClient 是tornado 的异步HTTP 客户端,如果你的服务需要访问其他的API接口,且希望是异步的进行,就必须使用AsyncHTTPClient,requests库虽然应用更广泛,但它本身并不支持异步。这就是人们对tornado理解的一个误区,tornado是一个异步框架,但这不意味你使用tornado开发时所做的每一个事情都是异步的,这依赖于你所使用的库是不是支持异步。

import tornado.ioloop
from tornado.web import RequestHandler, Application
from tornado.httpserver import HTTPServer
from tornado.httpclient import AsyncHTTPClient
from tornado.options import options, define

define('port', default=8000, help='监听端口')

async def asynchronous_fetch(url):
    """
    异步发起http请求
    :param url:
    :return:
    """
    http_client = AsyncHTTPClient()
    response = await http_client.fetch(url)
    return response


class HelloHandler(RequestHandler):
    async def get(self):
        response = await asynchronous_fetch('http://coolpython.net')
        self.write(response.body)


if __name__ == '__main__':
    options.parse_command_line()
    handlers_routes = [
        (r'/', HelloHandler)
    ]
    app = Application(handlers=handlers_routes)
    http_server = HTTPServer(app)
    http_server.listen(options.port)
    tornado.ioloop.IOLoop.current().start()

当用户的请求被HelloHandler 处理时,程序会异步的向coolpython.net发起请求,在实践中,往往是另一个服务提供的API接口,在这个示例中,使用的是我的个人博客。

单从代码来观察,并不能够看出异步与并发之间的关系,假设coolpython.net返回请求需要1秒钟的时间,而我们也没有使用这种异步的http客户端发送请求, 当10个用户同时访问 http://127.0.0.1:8000/ 时,10个用户都获得响应所需要的时间一定是大于等于10秒钟的,发送http请求是一个阻塞的过程,每个请求最少耗时是1秒,10个请求至少耗时10秒。

同样的并发场景下,使用AsyncHTTPClient 发送http请求,由于其异步的特性,尽管单次的请求是1秒钟,但这1秒钟的大部分时间都用在了io等待上,异步的情况下,他们彼此之间不会互相阻塞,这意味着他们几乎同时进入等待状态,因此最后的耗时一定是大于1秒钟小于10秒钟的。

究竟是2秒,还是3秒,主要取决于网络带宽和机器性能,从理论上来说,网络带宽越大,机器性能越好,整体的时间就越接近于1秒钟。

使用tornado开发web服务,想要访问msyql, redis, mongodb 等数据库,同样需要使用专门的支持异步的客户端,否则就无法利用tornado的异步特性,tornado也不适合做CPU 密集型的服务,异步是针对io而言的,对cpu无能为力,此时要考虑多进行部署。

扫描关注, 与我技术互动

QQ交流群: 211426309

加入知识星球, 每天收获更多精彩内容

分享日常研究的python技术和遇到的问题及解决方案