筆者因為工作的原因接觸到Tornado(/tɔrˈneɪdoʊ/, 龍卷風), 在學習的過程中參考不少文章, 雖然其中不乏優秀的文章, 但是内容大都是碎片化的, 缺少系統性, 而且不少關于異步應用的内容還是基于過時的舊版本. 是以打算寫一個Tornado應用筆記的系列文章, 即為了友善自己日後查閱, 也希望能夠幫助到和我一樣的Tornado的學習者. (注: 文章的代碼都是基于
Tornado 4.4+
&
Python 2.7
的, 隻要你的版本不是特别老舊, 都是可以正常運作的, 在下面的
Hello World
中有提及檢視版本的方法)
在Python Web架構中, 最為人熟知的三個是Django, Flask和Tornado, 前兩者是一重一輕的同步架構, 而後者則是以高性能著稱的異步架構. 在使用Tornado的開發團隊中, Quara和知乎是最常被提起的(參考: How-does-Quora-use-Tornado 和 知乎使用了哪些架構和開源庫?).
我想在正文開始之前, 需要說明的是, 請不要迷信架構所謂的”高性能”, 架構的作用是讓開發者更快速和便捷的建構起所需的應用, 而性能則是由包括系統架構和開發人員能力在内的諸多因素決定的. 況且, 在高性能伺服器價格相較開發人員的薪資”不值一提”和”面向上線時間程式設計”的今天, 過度追求高性能, 恐怕隻會弊大于利. 倘若你将Tornado作為一個同步架構使用, 并認為架構能夠”自主”實作高性能的話, 那我可真是無FUCK說了. 說到這裡又不得不提Instagram 在 PyCon 2017 的演講摘要, 其中分享了Instagram用一個以”慢”著稱的Django建構一個支撐着7億月活躍使用者應用的故事.
首先來看Tornado的簡介:
Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed. By using non-blocking network I/O, Tornado can scale to tens of thousands of open connections, making it ideal for long polling, WebSockets, and other applications that require a long-lived connection to each user.
Tornado是一個Python Web架構兼異步網絡庫, 最初由FriendFeed開發. 得益于非阻塞網絡I/O, Tornado可以支撐起數以萬計的連接配接, 是以它很非常适合開發長輪詢, WebSockets和那些需要與每個使用者建立持久連接配接的應用.
從簡介可以看出Tornado并沒強調自己Web架構的身份, 而是把重點放在建立長連接配接的特性上, 下面接着來看Tornado的Hello World.
# -*- coding: utf-8 -*-
# file: hello.py
import tornado.ioloop
import tornado.web
# 定義一個路由類, 隻能處理get請求, 請求傳回"Hello Tornado!"
class MainHandler(tornado.web.RequestHandler):
def get(self):
self.write("Hello Tornado!")
# 建立一個app, 并注冊路由
def make_app():
return tornado.web.Application([
(r"/", MainHandler),
])
if __name__ == "__main__":
# 擷取版本資訊, 最好還是4.2及以上的版本
print 'Tornado version is <%s>' % tornado.version
app = make_app()
# 監聽本地8888端口
app.listen()
print 'Tornado server is running at localhost:8888'
# 暫時不需要關心下面語句的細節, 隻需要知道其作用就是啟動服務
tornado.ioloop.IOLoop.current().start()
運作以後, 在浏覽器通路
localhost:8888
, 就能看到
Hello Tornado!
是的, 這個簡單的示例并沒有用到任何異步功能, 就是一個最基礎的阻塞應用.
本節内容就是這些, 下節将在
Hello World
的基礎上進行擴充, 介紹Tornado的路由類
tornado.web.RequestHandler
中的常用方法.