import tornado.httpserver import tornado.ioloop import tornado.web import tornado.gen from tornado.httpclient import AsyncHTTPClient,HTTPRequest class Test1Handler(tornado.web.RequestHandler): NEED_SLEEP = False @tornado.gen.coroutine def get(self): http_client = AsyncHTTPClient() http_request = HTTPRequest(url="http://localhost:8899/test2", method='GET', request_timeout=120) response = yield http_client.fetch(http_request) #这个是异步处理的动做 #每次间隔的访问,使用tornado的睡眠机制 睡眠5秒中 if Test1Handler.NEED_SLEEP: yield tornado.gen.sleep(20) #这个是异步处理的动做 Test1Handler.NEED_SLEEP = not Test1Handler.NEED_SLEEP # 彻底转发报文头部和body for h in response.headers: self.set_header(h, response.headers[h]) return self.finish(response.body) class Test2Handler(tornado.web.RequestHandler): SEQ = 0 def get(self): Test2Handler.SEQ += 1 print(Test2Handler.SEQ) return self.finish('TEST2 {0}'.format(Test2Handler.SEQ)) class Application(tornado.web.Application): def __init__(self): handlers = [ (r"/test1", Test1Handler), (r"/test2", Test2Handler), ] tornado.web.Application.__init__(self, handlers) if __name__ == "__main__": port = 8899 application = Application() http_server = tornado.httpserver.HTTPServer(application, xheaders=True) http_server.listen(port) print('Listen on http://localhost:{0}'.format(port)) tornado.ioloop.IOLoop.instance().start()
向"/test1"发送请求时,Test1Handler 使用 AsyncHTTPClient 异步的http客户端转发给了"/test2",并把test2的完整结果所有回复给了"/test1"的请求方,使用浏览器打开多个标签页都访问 http://localhost:8899/test1,就能够看到效果了。html
tornado使用装饰器@tornado.gen.coroutine,来代表该请求里面可能有异步处理, 须要进行异步处理的动做前面会用yield来讲明。python
我在Test1Handler里面使用 yield tornado.gen.sleep(20) 来进行异步睡眠的操做, 这个睡眠操做不会阻塞整个python进程,tornado继续处理其余的请求。web
这个异步操做的方法极大的提升了效率,在单线程的python中,当你写爬虫操做的时候,就不须要等待前面一个请求有返回值以后再发送另一个请求,而是同时发送好几个请求,当其中的某些请求正常返回的时候tornado会自动进行下一步操做。浏览器
yield tornado.gen.sleep(20)app
这个睡眠不会阻塞python的线程,睡眠时tornado服务仍然在正常的运行异步
IOLoop.instance().add_callback(callback, *args, **kwargs)
将callback加入到tornado的加入到的处理队列里面。tornado
IOLoop.instance().call_later(delay, callback, *args, **kwargs)oop
延时delay秒以后,将callback加入到tornado的加入到的处理队列里面fetch
还有其余异步调用的方法:url
http://www.tornadoweb.org/en/stable/ioloop.html#running-an-ioloop
http://www.tornadoweb.org/en/stable/ioloop.html#tornado.ioloop.PeriodicCallback
tornado.ioloop.PeriodicCallback(callback, callback_time, io_loop=None)
callback设定定时调用的方法
callback_time设定每次调用之间的间隔
值得注意的是每次调用之间没有任何关系,若是上次的调用尚未处理完,本次的调用仍然会继续跑, 能够经过继承这个类,而后加入一些判断机制,来保证一次调用处理完,才能进行下一次调用。