1.同步和異步的概念web
**同步**編程
含義:指兩個或兩個以上隨時間變化的量在變化過程當中保持必定的相對關係服務器
現象:有一個共同的時鐘,按來的順序一個一個處理cookie
直觀感覺 :就是須要等候,效率低下網絡
**異步**session
含義 :雙方不須要共同的時鐘,也就是接收方不知道發送方何時發送,因此在發送的信息中就要有提示接收方開始接收的信息,如開始位,同時在結束時有中止位app
現象:沒有共同的時鐘,不考慮順序來了就處理異步
直觀感覺:就是不用等了,效率高async
2.阻塞調用和非阻塞調用異步編程
*阻塞調用**
含義 : 阻塞調用是指調用結果返回以前,當前線程會被掛起(線程進入非可執行狀態,在這個狀態下,CPU不會給線程分配時間片,即線程暫停運行)。函數只有在獲得結果以後纔會返回。
現象:讀套接字時沒有數據等數據來,寫套接字時寫不下了也一直等,等能寫下了往裏寫(套接字被寫滿的緣由不在本地,在於網絡另外一頭的套接字被寫滿了來不及讀出去,致使本地的套接字內容來發不出去堵住了)
直觀感覺:執着
**非阻塞調用**
含義 :非阻塞調用是指沒有調用結果當即返回,當前線程不被掛起,能夠繼續作其它工做
現象:讀套接字時沒有數據,不等直接返回幹別的事去,寫套接字寫不下了也不寫了,直接返回幹別的事去
直觀感覺:勤奮
3.tornado的異步編程
**1.經過回調實現異步編程**
首先是咱們來編寫一個同步的代碼:
import datetime import tornado.httpserver import tornado.ioloop import tornado.options import tornado.web from tornado.options import define,options from pycket.session import SessionMixin from data.user_modules import User,session define('port',default=8010,help='run port',type=int) class BaseHandler(tornado.web.RequestHandler,SessionMixin): def get_current_user(self): # current_user = self.get_secure_cookie('ID') current_user = self.session.get('user') if current_user: return current_user return None class AbcHandler(BaseHandler): def get(self): """測試路由""" self.write('ok') class SyncHandler(BaseHandler): def get(self): """同步代碼""" client = tornado.httpclient.HTTPClient() response = client.fetch("http://127.0.0.1:8000/sync?id=3") self.write(response.body) if __name__ == '__main__': tornado.options.parse_command_line() app = tornado.web.Application( handlers=[ (r'/abc',AbcHandler), (r'/sync',SyncHandler), ], template_path='templates', static_path='static', debug=True, ) app.db = {} http_server = tornado.httpserver.HTTPServer(app) http_server.listen(options.port) tornado.ioloop.IOLoop.instance().start()
咱們新啓一個服務,而後去請求咱們以前啓的另外一個服務,另一個服務有休眠,咱們用次來模擬程序的阻塞。
當請求`sync`這個的路由的時候,發生阻塞,應爲tornado是單線程的,因此這個時候去請求`abc`這個路由的時候也會發生阻塞。所以,咱們須要使用異步來幫助咱們避免阻塞,使用異步的方式有多種,咱們接下來分別來看一下。
**使用回調函數來實現異步**
# 導入模塊 import tornado.httpclient class CallbackHandler(BaseHandler): """經過回調函數來實現異步""" @tornado.web.asynchronous def get(self): client = tornado.httpclient.AsyncHTTPClient() # 異步的方法 client.fetch("http://127.0.0.1:8000/sync?id=2",callback=self.on_response) self.write('Ok!'+'<br>') def on_response(self,response): print(response) self.write(response.body) self.finish() # 必需要加上
**經過協程實現異步**
# 導入模塊 import tornado.gen class GenHandler(BaseHandler): """經過協程實現的異步""" @tornado.web.asynchronous @tornado.gen.coroutine # coroutine 協程 def get(self): client = tornado.httpclient.AsyncHTTPClient() response = yield tornado.gen.Task(client.fetch,"http://127.0.0.1:8000/sync?id=3") print(response) self.write(response.body)
**經過協程實現異步(自定義函數)**
class FuncHandler(BaseHandler): """經過協程實現的異步""" @tornado.web.asynchronous @tornado.gen.coroutine # coroutine 協程 def get(self): response = yield self.func() print(response) self.write(response.body) @tornado.gen.coroutine def func(self): #此處的函數只是簡單的演示,能夠爲複雜的邏輯進行實現 各個功能 client = tornado.httpclient.AsyncHTTPClient() response = yield tornado.gen.Task(client.fetch,"http://127.0.0.1:8000/sync?id=4") raise tornado.gen.Return(response)
**經過協程來實現異步(使用requests模塊)**
# 首先安裝模塊 # pip install futures # pip install requests # 導入模塊 from tornado.concurrent import run_on_executor from concurrent.futures import ThreadPoolExecutor import requests class MyFuncHandler(BaseHandler): """經過協程實現的異步""" executor = ThreadPoolExecutor() @tornado.web.asynchronous @tornado.gen.coroutine # coroutine 協程 def get(self): response = yield self.func() print(response) self.write(response.text) @run_on_executor def func(self): response = requests.get("http://127.0.0.1:8000/sync?id=4") return response
以上的這些實現異步的方式你們都是可使用的,也須要熟練掌握。
**總結**
由於tornado是單線程的,因此在路由層若是發生阻塞,那麼 整個服務器的會所以沒法訪問,爲了不這種事情的發生,咱們採用異步的這種方式來避免。
在tornado中實現異步的方式多樣的,你們須要記住上面給出的幾種方式,而且可以熟練使用。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
到此tornado的基礎部分已經基本完成,這些基礎知識會在以後的項目中用到,持續更新中.......