tornado異步html
Tornado默認是單進程單線程。實時的web特性一般須要爲每一個用戶一個大部分時間都處於空閒的長鏈接. 在傳統的同步web服務器中,這意味着須要給每一個用戶分配一個專用的線程,這樣的開銷是十分巨大的。python
爲了減少對於併發鏈接須要的開銷,Tornado使用了一種單線程事件循環的方式. 這意味着全部應用程序代碼都應該是異步和非阻塞的,由於在同一時刻只有一個操做是有效的。web
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()
當異步函數有返回值時,接受該異步方法的函數也應該異步執行,用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併發