暸解非同步機制:
Tornado 受歡迎的原因,在於它的設計著眼於處理 C10K 問題。舉例來說,當 Server 端接收到查詢資料庫的 Request,有許多時間是在等待資料庫的查詢結果而呈現 Blocking 的狀態。若我們可以利用這些等待的時間來處理其他的 Request,就可以增加整體的效能。所以同樣的 Request,在使用 Tornado 的非同步機制處理下,系統不會苦苦等到資料庫回應才繼續工作,而是將先前的請求暫存起來,先服務其他的 Request,等到資料庫查詢回應後繼續處理剛剛未完成的工作。
實作 Asynchronous :
Tornado 歷經多次重大更新,初期版本中實作非同步需要撰寫 callback 來達成目的,而這樣的方式也讓人詬病。因為你如果需要比較複雜的邏輯處理,可能需要多次的 callback 也造成閱讀、理解上的困難度。因此 Tornado 開發團隊提出了方便的 @gen.coroutine Decorator,接下來就直接使用它來示範,就不再示範前面版本的寫法。
開始實作,假設我們今天提供一個 RESTful 服務,內容包含擷取解析其他網站資訊,這時候我們就可以使用非同步機制來提升效能,程式內容參考如下:
#!/usr/bin/env python
import os
import tornado.web
import tornado.gen
import tornado.ioloop
import tornado.options
import tornado.httpclient
tornado.options.define("ip", default='1.1.1.x', help="message...")
tornado.options.define("port", default=8888, help="message...")
url='http://....'
class Async(tornado.web.RequestHandler):
    # 加入 Coroutine,宣告此函式為 Asynchronous
    # 使用時必須搭配 yield,Python3.5 可以使用 async 與 await
    @tornado.gen.coroutine
    def get(self):
        client = tornado.httpclient.AsyncHTTPClient()
        response = yield client.fetch(url)
        # 加入處理邏輯 ...
        self.write("...")
settings= {
    "debug": True,
    "autoreload": True
}
def main():
    tornado.options.parse_command_line()
    app = tornado.web.Application(
            [
                (r'/async', Async)
            ], **settings
        )
    app.listen(tornado.options.options.port, tornado.options.options.ip)
    tornado.ioloop.IOLoop.current().start()
if __name__ == "__main__":
    main()
Environment :
・ Arch Linux
・ Python 2.7
Reference :
・ Tornado
