Tornado包含一個AsyncHTTPClient類,可以執(zhí)行異步HTTP請求。
關(guān)鍵字: @tornado.web.asynchronous,self.finish()
import tornado.web
import tornado.httpclient
class IndexHandler(tornado.web.RequestHandler):
# @tornado.web.asynchronous裝飾器告訴Tornado保持連接開啟。
@tornado.web.asynchronous
def get(self):
query = self.get_argument('q')
client = tornado.httpclient.AsyncHTTPClient()
#fetch方法并不返回調(diào)用的結(jié)果,而是使用callback指定的函數(shù)處理response。
client.fetch(url,callback=self.on_response)
def on_response(self, response):
...
pass
self.finish()
#顯式地告訴Tornado關(guān)閉連接
1.調(diào)用@tornado.web.asynchronous裝飾器
2.必須調(diào)用 self.finish() 已完成 HTTTP 請求,否則 用戶的瀏覽器會一直處于等待服務(wù)器響應(yīng)的狀態(tài)
記住當你使用@tornado.web.asynchonous裝飾器時,Tornado永遠不會自己關(guān)閉連接。你必須在你的RequestHandler對象中調(diào)用finish方法來顯式地告訴Tornado關(guān)閉連接。(否則,請求將可能掛起,瀏覽器可能不會顯示我們已經(jīng)發(fā)送給客戶端的數(shù)據(jù)。)
上面的方法有些麻煩,為了處理請求 ,把代碼分割成兩個不同的方法,當有兩個或更多的異步請求要執(zhí)行的時候,編碼和維護都顯得非常困難。
一個更整潔的方式來執(zhí)行異步請求————異步生成器
關(guān)鍵字:@tornado.gen.engine
使用時@tornado.gen.engine緊挨著函數(shù),這將提醒Tornado這個方法將使用tornado.gen.Task類。
import tornado.gen
class IndexHandler(tornado.web.RequestHandler):
@tornado.web.asynchronous
@tornado.gen.engine
def get(self):
query = self.get_argument('q')
client = tornado.httpclient.AsyncHTTPClient()
#yield的使用返回程序?qū)ornado的控制,允許在HTTP請求進行中執(zhí)行其他任務(wù)。
#當HTTP請求完成時,RequestHandler方法在其停止的地方恢復。然后繼續(xù)運行。
response = yield tornado.gen.Task(client.fetch,url)
body = json.loads(response.body)
...
self.finish()
#顯示關(guān)閉請求連接
使一切異步————異步訪問數(shù)據(jù)庫
一個重要的例子是bit.ly的asyncmongo,它可以異步的調(diào)用MongoDB服務(wù)器。這個庫是我們的一個非常不錯的選擇,因為它是專門給Tornado開發(fā)者開發(fā)提供異步數(shù)據(jù)庫訪問的,不過對于使用其他數(shù)據(jù)庫的用戶而言,在這里也可以找到不錯的異步數(shù)據(jù)存儲庫的選擇。
提示:如果你正在設(shè)計一個希望客戶端瀏覽器來執(zhí)行搜索請求,而讓Web服務(wù)器轉(zhuǎn)向提供其他請求。在大多數(shù)情況下,你至少希望將結(jié)果緩存以便兩次相同搜索項的請求不會導致再次向遠程API執(zhí)行完整請求。
Tornado與WebSockets
WebSockets是HTML5規(guī)范中新提出的客戶-服務(wù)器通訊協(xié)議。提供了在客戶端和服務(wù)器間持久連接的雙向通信。協(xié)議本身使用新的ws://URL格式,但它是在標準HTTP上實現(xiàn)的。通過使用HTTP和HTTPS端口,它避免了從Web代理后的網(wǎng)絡(luò)連接站點時引入的各種問題。
參看:http://demo.pythoner.com/itt2zh/ch5.html#ch5-3