tornado異步

tornado異步html


  • Tornado默認是單進程單線程。實時的web特性一般須要爲每一個用戶一個大部分時間都處於空閒的長鏈接. 在傳統的同步web服務器中,這意味着須要給每一個用戶分配一個專用的線程,這樣的開銷是十分巨大的。python

  • 爲了減少對於併發鏈接須要的開銷,Tornado使用了一種單線程事件循環的方式. 這意味着全部應用程序代碼都應該是異步和非阻塞的,由於在同一時刻只有一個操做是有效的。web

 

  • 當莫條請求被阻塞的時候,下一條請求將沒法也會被阻塞住。針對這種狀況,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併發

相關文章
相關標籤/搜索