tornado异步

tornado异步


  • Tornado默认是单进程单线程。实时的web特性通常需要为每个用户一个大部分时间都处于空闲的长连接. 在传统的同步web服务器中,这意味着需要给每个用户分配一个专用的线程,这样的开销是十分巨大的。

  • 为了减小对于并发连接需要的开销,Tornado使用了一种单线程事件循环的方式. 这意味着所有应用程序代码都应该是异步和非阻塞的,因为在同一时刻只有一个操作是有效的。

 

  • 当莫条请求被阻塞的时候,下一条请求将无法也会被阻塞住。针对这种情况,tornado提供了一种协程异步的方式来解决这种问题。
  •  1 from tornado.web import Application, RequestHandler
     2 from tornado.ioloop import IOLoop
     3 from tornado.httpserver import HTTPServer
     4 from tornado.httpclient import AsyncHTTPClient
     5 from tornado.options import options, define
     6 from tornado import gen
     7 
     8 define('port', default=80, type=int)
     9 
    10 
    11 
    12 class TestWebHandler(RequestHandler):
    13 
    14 
    15     """网络请求阻塞"""
    16     @gen.coroutine
    17     def get(self):
    18         client = AsyncHTTPClient()
    19         url = 'https://vdn1.vzuu.com/SD/bea84ccc-a09e-11e9-bf0c-0a580a436135.mp4?disable_local_cache=1&bu=com&expiration=1563118410&auth_key=1563118410-0-0-84c3390428629c25b0179da9964f294c&f=mp4&v=hw'
    20         res = yield client.fetch(url)
    21         with open('2.mp4', 'wb+') as f:
    22             f.write(res.body)
    23         self.write("下载完成!")
    24 
    25 class TestTimeHandler(RequestHandler):
    26 
    27     """time sleep阻塞"""
    28     @gen.coroutine
    29     def get(self):
    30         yield gen.sleep(5)
    31         self.write("TestTimeHandler page")
    32 
    33 
    34 class IndexHandle(RequestHandler):
    35     def get(self):
    36         self.write("index page")
    37 
    38 app = Application(
    39     handlers=[
    40         (r'/test', TestWebHandler),
    41         (r'/time', TestTimeHandler),
    42         (r'/', IndexHandle),
    43     ]
    44 )
    45 
    46 if __name__ == '__main__':
    47     options.parse_command_line()
    48     http = HTTPServer(app)
    49     http.listen(options.port)
    50     IOLoop.current().start()
  • 当网络阻塞的时候需要调用tornado的异步客户端,再调用gen.coroutine装饰器
  • 协同程序提供了一种在异步环境中工作比链接回调更简单的方法。使用协程的代码在技术上是异步的,但它是作为单个生成器而不是单独的函数集合编写的。
  • 当需要程序休眠的时候调用tornado内部提供的sleep方法,使用time.sleep不可以实现协程异步(time.sleep()是blocking的不支持异步操作)

 

  当异步函数有返回值时,接受该异步方法的函数也应该异步执行,用yield接受返回值

  

 1 from tornado.web import Application, RequestHandler
 2 from tornado.ioloop import IOLoop
 3 from tornado.httpserver import HTTPServer
 4 from tornado.options import options, define
 5 from tornado import gen
 6 
 7 define('port', default=80, type=int)
 8 
 9 
10 class Test:
11 
12     @classmethod
13     @gen.coroutine
14     def get(self):
15         yield gen.sleep(1)
16         return "返回值"  # python3.3之后可以直接使用return, 3.3以前使用raise gen.Return
17 
18 
19 class Index(RequestHandler):
20     # 接受异步方法返回值的方法也应该异步,并且使用yield接受参数
21     @gen.coroutine
22     def get(self):
23         resp =  yield Test.get()
24         self.write(resp)
25 
26 
27 
28 app = Application(
29     handlers=[
30 
31         (r'/', Index),
32     ]
33 )
34 
35 if __name__ == '__main__':
36     options.parse_command_line()
37     http = HTTPServer(app)
38     http.listen(options.port)
39     IOLoop.current().start()

 

 tornado协程的三种方式

 1 from tornado.web import RequestHandler, Application
 2 from tornado.httpserver import HTTPServer
 3 from tornado.ioloop import IOLoop
 4 from tornado.options import options
 5 from tornado import gen
 6 
 7 
 8 class IndexHandle(RequestHandler):
 9     @gen.coroutine
10     def get(self):
11         r1 = yield Index1Handle().get()
12         print(r1)
13         self.write(r1)
14         r2 = yield Index2Handle().get()
15         print(r2)
16         self.write(r2)
17         r3 = yield Index3Handle().get()
18         print(r3)
19         self.write(r3)
20 
21 
22 class Index2Handle:
23     @gen.coroutine
24     def get(self):
25         yield gen.sleep(5)
26         return "666"
27 
28 
29 class Index3Handle:
30     async def get(self):
31         await gen.sleep(5)
32         return "666"
33 
34 
35 class Index1Handle:
36     @gen.coroutine
37     def get(self):
38         yield gen.sleep(5)
39         raise gen.Return("666")
40 
41 
42 app = Application(
43     handlers=[
44         (r'/', IndexHandle),
45 
46     ]
47 )
48 
49 if __name__ == '__main__':
50     options.parse_command_line()
51     http = HTTPServer(app)
52     http.listen(80)
53     IOLoop.current().start()

 

 

  tornado官方文档:https://www.osgeo.cn/tornado/gen.html#decorators

 

 

 

 

 




 

posted @ 2019-07-14 23:04  Ivy丶  阅读(435)  评论(0编辑  收藏  举报