如何理解 Tornado ?

tornado 到底是個什麼東西呢?

  1. 如果它是個webserver ,那麼後端如何搭配Django使用 ,又能否搭配Node.js 或 PHP?

  2. 如果作為web框架,nginx對於她來說意義在哪裡? 在實際使用中是否會影響Tornado本身的非同步IO設計?

  3. Tornado與node.js 的實現的目的 ,和設計方式上的不同之處在哪裡 ( 不談語言 )?

-----------------------------

補充:以下是看官方說明和 Google 了一番後的理解:

  1. 它可以作為一個裸 webserver 來使用 ,就是說它的後端可以運行 Django、web.py。

  2. 它是一個簡單 Python 框架,url 基於正則,有自己的模板實現,但是沒有 orm。這部分看起來類似於 web.py。

  3. 非阻塞非同步 IO,類似於 node.js。

  4. 它的前端可以放 Nginx ,感覺類似於 Nginx、Apache 之於 Tomcat。

就是說它作為 web 框架比 Django 簡單,又支援非同步 IO,且更不需要前端的 webserver ?

我已經混亂了, Tornado是 Nginx、Django、Node.js 的結合體?又或是 Nginx * 20% + Django * 40% + Node.js * 40% ?


Tornado既是一個web server,也是web framework。而它作為web server 採用的是asynchronous IO的網路模型,這是一種很高效的模型。

web framework的定義(http://wiki.python.org/moin/WebFrameworks)

A Web framework is a collection of packages or modules which allow developers to write Web applications or services without having to handle such low-level details as protocols, sockets or process/thread management.

Tornado作為web server,提供了web framework的api,可以來直接構建自己的web程序。同時,Tornado支持WSGI ( http://www.python.org/dev/peps/pep-0333/ ),也就是說它可以有能力其它的一些python的框架一起使用,比如django, bottle, flask等。不妨看下bottle在不同server下的性能評測,其中就有tornado( http://bottlepy.org/page/2009-12-19_Comparing_HelloWorld_Performance )。額外說的是,WSGI的框架是不支持非同步的,所以如果有非同步調用的邏輯的web程序,Tornado也是選擇之一。

沒有使用過Node.js,但官網說:

Node.js is a platform built on Chrome"s JavaScript runtime for easily building fast, scalable network applications.

可以把Node.js理解成基於V8的javascript運行環境或工具包,它屬於偏底層的抽象,擴展了javascript寫服務端程序的能力。所以基於它也會有不同的web framework。從這個角度來看,Node.js和Tornado其實不在一個層次上。

不過相同的是 Node.js 和 Tornado都採用的的單進程單線程非同步IO的網路模型。它們都可以寫非同步非阻塞的程序,不過我覺得因為javascript的語言特性,Node.js對非同步回調非阻塞的風格堅持比Tornado更徹底一點。不過通常多進程時,一個進程的短時間阻塞也是可以接受的。

使用Nginx是因為一些單進程服務無法利用多核CPU,同時也會有單機的限制,所以通常會在多個伺服器啟動多個進程實例,使用Nginx在前端作為反向代理伺服器來分發web請求,同時負載均衡。Nginx是C寫的,有更好的並發性,可配置性,對靜態文件也有更好的支持。當然這是Nginx的常用情景,其實也可以直接使用Nginx來構建web應用,可以參考OpenResty項目( http://openresty.org/ )。

其實網路模型、web server、web framework是三個不同層次,它們之間並不衝突,是選擇的關係。理解前,不妨先理清概念:)


建議樓主閱讀一下這篇論文 C10K problem,雖然有點老了http://www.kegel.com/c10k.html

其實,你也可以說nginx是一個framework,不過是針對C的。

裸WebServer表示他支持HTTP協議,既然支持HTTP協議,你前面放啥反向都無所謂,nginx apache squid varnish。或者也可以用wsgi模塊,只是採用了特殊的通訊協議。

為什麼要在tornado前面放nginx,原因在於,Python雖然有多線程,但是Python的解釋器有GIL http://en.wikipedia.org/wiki/Global_Interpreter_Lock 這點非常影響了Python和Tornado利用多核的能力,所以只能通過多進程來利用多核。既然多進程,一般就需要在前端放置nginx haproxy做為負載均衡的反向代理,或是使用這些應用伺服器的wsgi模塊來管理進程的生命周期等等。另外對於靜態文件的服務,也是nginx之類的更具有優勢。(他們直接把請求轉發到tornado的進程中,你根本不用管請求怎麼來的,專心寫你的程序。)

其他很多腳本語言的框架都有類似問題,比如ruby,而Nodejs更加是連線程都沒有了。

Nodejs的核心在於,他使用了JavaScript天生擅長的事件/回調機制來實現非同步。

Python對於匿名函數和閉包支持不夠好,所以Tornado通過了類來和回調方法來實現非同步,這裡沒有事件的概念。(沒深入研究過Tornado,大致是這麼了解的)

另外Tornado封裝了很多常用的諸如靜態文件處理、Router、模板等等,而Nodejs基本上是一個純粹的協議框架,這些功能都需要自己去寫。Nodejs+Express差不多就可以等於Tornado的功能了。

而如果是要做一個中間件或中間層,做一些高級點的協議處理,可能nodejs更加能勝任。

在tornado裡面去調用用php或者nodejs所開發的服務,這是沒問題的,主要要看架構上如何設計。


1. 輕框架,從web.py開始,flask,bottle這些都是輕框架,tornado則是輕框架的代表

2. 高性能非同步框架,直接基於ioloop寫東西,你就覺得tornado不僅僅是web框架了

3. 隊列伺服器,我們實現一個兩級tornado伺服器模型,前面的負責web分配和並發,後面負責單線程高cpu計算,輕鬆解決了單線程高運算量的block問題

WSGI功能可以忽略不計了

理解了tornado的特性之後,我們發現唯一需要和tornado配合的就是nginx,既可以做負載均衡,又可以擋住靜態文件請求。除此以外你還需要個mysql,試試torndb。

使用tornado可以大大的減少web系統中使用的組件數量,用最少的代碼量和極其精簡的架構實現你的系統。


大家的回答都有點片面,更多的關注web框架成,其實tornado遠遠不止這些,且聽我慢慢到來

1.高性能的網路庫,這可以和gevent,twisted,libevent等做對。提供了非同步io支持,超時事件處理,在此基礎上提供了tcpserver,httpclient,尤其是curlhttpclient在現有http客戶端中肯定排第一。可以用來做爬蟲,遊戲伺服器,據我所知業界已有使用tornado作為遊戲伺服器

2.web框架,這可以和django,flask對。提供了路由,模板等web框架必備組件。與其他區別是tornado是非同步的,天然適合長輪訓,這也是friendfeed發明tornado的原因,

當前flask也可以支持,但必須借住gevent等

3.較為完備的http伺服器,這點可以和nginx,apache對比,但只支持http1.0,所以使用nginx做前段不僅是為了更好利用多核,也是讓其支持http1.1

4.完備的wsgi伺服器,這可以和gunicore,gevent wsgi server做對比,也就是說可以讓flask運行在tornado之上,讓tornado加速flask

5.提供了完備的websocket支持,這讓html5的遊戲等提供了便利。像知乎長輪訓就是使用了websocket,但websocket手機支持的不是很好,前段時間不得不使用定時ajax發送大量請求,期待手機瀏覽器趕快奮起直追

tornado,你值得擁有


tornado是一個非同步的http框架,fb最早是拿tornado做feed流上提醒用的,tornado內置了一個asynchttpclient,這個特別適合基於rest web service做網站,使用@gen.coroutine 和yield基本上就可以把非同步代碼變成同步代碼了。tornado代碼量不大,特別適合有興趣的人,自己研究用。

不過tornado問題也不小,做網站的話,最主要的是,tornado是單線程的(雖然可以通過fork來搞多進程),而web後端多用rdbms,特別是mysql主要的driver都是同步阻塞的,也就是說訪問資料庫會阻塞tornado,所以對做網頁的限制比較大。


首先我覺得web server和web框架這兩個功能本身並不衝突,因為http server的功能就是連接接入,業務邏輯處理,返回頁面。因此tornado, node.js, django, nginx都可以實現這樣的功能,只是使用場景的不同,導致他們或歸為web server或歸為web框架。

首先說說nginx,主要應用場景是反向代理,負責前端連接接入,繼而向後請求後端服務。而nginx本身提供一些負載均衡的功能可以加強web服務的負載能力。但同時nginx也可以作為web框架,只是其c語言開發成本較大,所以用的人比較少而已。不過@agentzh 開發的openresty可以用Lua去寫nginx的擴展,這也增強了nginx作為web框架處理業務邏輯的能力。

再說說node.js,node的定位並不完全是web server和web框架,它更多的是實現了一套javascript在伺服器上的運行時,但由於其本身非同步網路的特點,所以作為一個網路服務框架非常合適,可以看到node實現的httpserver實際上非常簡單,這也誕生了express這種目標就是web框架的中間件。

django我只有個大概的了解,感覺它的定位是一個web服務的全套解決方案(如rails),提供了orm,抽象後台管理等web服務常用的功能,因此它的目標定位是web框架,但由於是同步的(很多年沒關注了,現在改沒改不知道),所以比較影響接入能力,所以前面一般要掛個非同步反向代理。

而tornado的定位也更像是輕量級web框架,提供非同步能力,但對於業務邏輯處理的支持比django要簡單,因此和node一樣比較適合做服務中間件。

從業務邏輯處理的角度來說,雖然非同步處理能力已經有了比較大的提升,但node和tornado都是單進程的,因此一般要啟多個實例,前端再用nginx做接入和負載均衡。

所以從架構選型的角度,nginx做前端接入,後面服務邏輯的選擇就看需求了,如果只是最基本的web服務,如cms之類的,django比較方便,可以省下很多開發量。而node和tornado做複雜web系統的中間件比較合適……


我來回答一下答主補充的問題:

&> 就是說它作為 web 框架比 Django 簡單,又支援非同步 IO,且更不需要前端的 webserver ?

&> 我已經混亂了, Tornado是 Nginx、Django、Node.js 的結合體?又或是 Nginx * 20% + Django * 40% + Node.js * 40% ?

你需要搞清楚幾個概念:

1,web server是監聽埠,負責HTTP鏈接管理、數據收發、HTTP協議實現等底層上的處理。

2,Web框架定義的是單個HTTP請求處理的流程。

3,nginx是反向代理伺服器,是一個特殊的web server應用,和web server並不是同級的概念。

Tornado既是web server又是web框架,這兩者並不矛盾。

舉例來說,你寫了一個tornado應用之後,直接把tornado埠跑在8000,這個時候,通過localhost:8000/foo就能訪問到你的網頁。這裡分兩步,tornado完成了底部IO事件的監聽和數據接受等工作,這是tornado完成了其作為web server的使命。然後你通過按照tornado框架定義的流程,在對應的地方寫了個get函數,實現了這個頁面的具體內容,這是tornado作為web 框架體現了作用。

那麼nginx有什麼用?

他是個反向代理,反向代理顧名思義,其作用就是將接收到的HTTP請求按照一定的規則轉發給後端其他伺服器處理。

比如在你的一台機器上跑了三個tornado應用:foo1,foo2,foo3,埠分別為8000,8001,8003,你希望用戶可以直接通過80埠來訪問這些應用。這個時候你就可以用nginx來達到這個目的了。讓nginx跑在80埠,當他接收到請求時,如果是/foo1,就轉發給8000埠處理;如果是/foo2,就轉發給8001埠處理,foo3類似。

所以,tornado和nginx並沒有什麼聯繫。實際上,很多框架都實現了一些簡易web server,用於調試。tornado的web server是非同步的,以可以處理大量的非活躍長連接著稱。所以其web server是他的一個特性feature,在介紹的時候就會提及自己是一個很酷的webserver了。

回到主題,題主你在你機器上裝裝nginx、用tornado寫個hello world就都清楚了。

祝折騰快樂


Tornado是一種 Web 伺服器軟體的開源版本。Tornado 和現在的主流 Web 伺服器框架(包括大多數 Python 的框架)有著明顯的區別:它是非阻塞式伺服器,而且速度相當快。

得利於其 非阻塞的方式和對epoll的運用,Tornado 每秒可以處理數以千計的連接,因此 Tornado 是實時 Web 服務的一個 理想框架。

下載和安裝

自動安裝: Tornado 已經列入 PyPI ,因此可以通過 pip 或者 easy_install 來安裝。如果你沒有安裝 libcurl 的話,你需要將其單獨安裝到系統中。請參見下面的安裝依賴一節。注意一點,使用 pip 或 easy_install 安裝的 Tornado 並沒有包含源代碼中的 demo 程序。

手動安裝: 下載 tornado-1.2.1.tar.gz

tar xvzf tornado-1.2.1.tar.gz
cd tornado-1.2.1
python setup.py build
sudo python setup.py install

Tornado 的代碼託管在 GitHub 上面。對於 Python 2.6 以上的版本,因為標準庫中已經包括了對 epoll 的支持,所以你可以不用 setup.py 編譯安裝,只要簡單地將 tornado 的目錄添加到 PYTHONPATH 就可以使用了。

安裝需求

Tornado 在 Python 2.5, 2.6, 2.7 中都經過了測試。要使用 Tornado 的所有功能,你需要安裝 PycURL (7.18.2 或更高版本) 以及 simplejson (僅適用於Python 2.5,2.6 以後的版本標準庫當中已經包含了對 JSON 的支持)。為方便起見,下面將列出 Mac OS X 和 Ubuntu 中的完整安裝方式:

Mac OS X 10.6 (Python 2.6+)

sudo easy_install setuptools pycurl

Ubuntu Linux (Python 2.6+)

sudo apt-get install python-pycurl

Ubuntu Linux (Python 2.5)

sudo apt-get install python-dev python-pycurl python-simplejson

Hello, world

以下是經典的 "Hello, world" 示例:

import tornado.ioloop
import tornado.web
class MainHandler(tornado.web.RequestHandler):
def get(self):
self.write("Hello, world")

application = tornado.web.Application([
(r"/", MainHandler),
])
if __name__ == "__main__":
application.listen(8888)
tornado.ioloop.IOLoop.instance().start()

如果你還有學習Linux的興趣,可以看我們團隊整理的:【超全整理】《Linux雲計算從入門到精通》系列實戰筆記全放送 | Linux運維部落


Tornado 是一個web伺服器。django是一個快速web程序編寫框架。node.js是一種編程環境。你直接用Tornado 寫網站也可以,但是它只有最基本的功能,你寫個網站工作量不小,而DJANGO則可以幫助你快速的編寫網站程序,而後部署在Tornado 或者其他web伺服器上。node.js則是類似PYTHON的一種編程環境,它可以實現很多東西。我認為你要做個網站,真正現實的就是PHP、rails、django,真正重要的快速實現你的想法,性能之類的東西開始並不重要。


跟django搭配,實現wsgi就好;跟nginx使用,主要還是為了負載均衡,現在cpu多核,只跑一個tornado實例的話太浪費;非同步模型比同步模型資源利用率高


tornado自帶了一個web伺服器,性能不錯,但由於實現簡化了很多功能,建議跑在nginx後面

tornado本身又是一個web框架,但是沒有預先實現很多功能,只保留比較必要的組件,這個和Django就有點相反的思路。

雖然思路相反,但Django其實也是圍繞著一個設計精良的core來實現的,如果單獨把這個core抽取出來其實和Tornado的規模和功能都差不多。它的功能豐富(甚至是複雜)只不過是一種「一站式框架」的理念的體現而已。

簡單來說,就是它們一個是簡約框架,一個是把可能需要的組件都默認配給你的框架。喜歡用哪個看個人愛好。前者的麻煩是遇到某些問題要自己重新實現,後者的麻煩是如果它預置給你的不能滿足要求也要自己重新實現,歸根到底就是找到一個平衡點,盡量方便開發就可以了。

非同步方面個人不推薦node.js,js用在服務端還是很少的,很多組件都不齊全,要成熟還得比較久,用Python可以有很多現有的組件使用。

最後,如果關心性能,請嘗試pypy,在Linux下網路IO方面毫不遜色node.js,不過大部分情況下性能問題都不在Python寫的東西中,而在資料庫。


都是長篇啊。。其實把 epoll 了解了解,然後 tornado 里 ioloop 那裡看明白就好了


據說是使用非同步網路方式實現的全棧web開發框架,高並發,比較適用於提供長輪詢,websocket的應用,等有機會可以玩玩


1)web server在我們看來可能就是個http伺服器的別名,雖然有點偏離其原意,但是天朝碼農幾乎將他們划了等號。那麼從這點上看,nginx/tornado/node.js都是同一個層面的,他們都實現了http服務。tornado通過epoll/kqueue作為非同步事件庫的基礎,nginx不用提,自然是高性能的web server。node底層用的是libuv,其實就是作者重寫的libaio和libuv的結合體。node也實現了http 伺服器的功能。

2)web framework。何為框架,不正規的定義就是一些sdk的集合體。對於一個web框架就是提供了基本的url路由,模板功能,orm等等寫web app最常用功能的集合的一個大sdk。那麼從這個角度,tornado提供了這些(除了orm),node在js層面提供了,django無疑是提供的最為全面的。

理解了前兩者,最後就是使用上的搭配了。

1)tronado搭配nginx主要是用nginx處理靜態內容和作為其前端代理,tornado是非同步的,但是他是單線程且阻塞式的結構,當處理db以及文件io就會塞住,所以將db以及文件io通過nginx代理或者tornado自己的http client路由給其他動態模塊處理。

tornado搭配django我社會經驗不足沒有見過。猜想可能是用tornado處理實時請求,django處理其他內容請求。這個時候可以把tornado當作django的補充或者插件來看。也有另一種可能就是tornado當一個代理,就和nginx和tornado搭配nginx處理靜態內容其他路由給tornado一樣,實時請求給到tornado,其他路由到django。

2)在這個層面上node本身有web server的功能,同時也有web framework的功能,所以它就和上面的tornado有點像,我想這也是人們比較他們的原因把。只是它一套比較的完善(功能上),所以沒有了那麼多搭配的選擇。同時node 不僅可以提供了很好的web server性能,同時它也能提供很好的tcp server性能,因此會看到基於它上的網易的開源遊戲後台伺服器。這個時候可以拿python的gevnet和twist來作比較。綜合來看,這個就是語言陣營上的差別把。

總的來說,根據需求選擇工具,適當的時候寫個例子作作對比,同時要接地氣,就是團隊是哪個陣營的/熟悉哪個就選擇哪個。


何必糾結幾個概念名詞呢,別把技術學死了,就像是我們如今對待設計模式一樣,別太認真,最重要的是認清楚那幾個設計原則,寫出來的代碼自然屬於某種模式。如果真有興趣,就去閱讀下tornado的源碼,是web server還是框架自然心中有數,如果可以,再去看看bottle,看看什麼才叫單純的框架,tornado擁有自身的處理http請求的能力,所以他就是一個web server,bottle之類的極其輕量級的東東是需要藉助於python的wsgi程序或者是uwsgi軟體來處理web接入的,之所以說是框架,是因為他給我們提供了我們自己業務程序的掛載和運行機制(所謂框架就是定義了流程,然後去在某一個環節執行我們自己寫的程序罷了,這跟平台的概念相反,是我的程序定義流程,然後去調用平台的庫),之所以要掛到nginx後面,那就當然了啊,你用python寫的業務邏輯不可能直接掛到nginx上面啊,nginx提供多進程worker模型,tornado是事件驅動的典型案例,單進程單線程性能的極致,配合nginx,是很完美的,再根據系統的CPU核數配置worker進程數,性能是很完美的。


Node.js可以當純HTTP伺服器,Tornado的話有些吃力了(對HTTP 1.1協議支持不夠,高並發上處理也會不足),兩者原生對多核利用效率都非常差。

這兩個在入門的時候可以學著用來裸跑,但是真正開發的時還候是強烈推薦前端用Nginx之類高效成熟的HTTP伺服器做代理,穩定和效率並存。


跟傳統web框架最大的區別就是單線程和多線程的區別:

1、傳統多線程框架是接受一個請求,創建一個線程處理,N個並發請求就是N個線程,多線程框架的優勢很明顯,線程內部變數、IO連接獨享,容易理解,也容易開發,缺點就是單個伺服器的線程數是有限的,如果太多的空閑連接就浪費線程資源了,而且共享變數的並發訪問和可見性都是問題,還有線程調度的開銷。

2.tornado是個基於epoll的單線程web框架,tornado的核心是ioLoop,ioLoop的核心epoll是個IO多路復用器,如果你知道JAVA的基於epoll的nio的話,應該會知道,一個io管道是一個channel,channel註冊在selector上,如果channel有接收完數據後會處於就緒狀態,應用只需一個主線程輪詢selector取出已就緒狀態的chennel來處理,就可以做到單線程處理所有io事件的目的。可能即便這麼說,大家可能還是迷糊,可以把它想像成一個接話員(主線程),你(io管道)需要聯繫他的時候(io管道消息接受完畢)就在他的小本子寫下自己的號碼(註冊),接話員從早到晚就在小本子上上找號碼(輪詢)並打過去和你交流(執行消息處理),然後交流完了再去小本子上找電話。

ioLoop封裝epoll,實現所有的非同步事件可以註冊到IOLoop上,主線程不停輪詢ioLoop取出已就緒的非同步事件來處理。

tornado就是封裝了使用IOLoop的過程,一個主線程可處理所有的非同步事件(server涉及的IO都已被封裝成非同步事件),而且還讓你可以以可讀性更高的協程方式編寫代碼。這麼做的好處,沒有線程切換,沒有多餘線程,理論上只要內存足夠,並發連接數無上限。

聽不懂沒關係,但是用的是時候千萬注意以下幾點。

①tornado是單線程框架,所有IO連接(redis、mysql等)請用非同步連接器,如果沒有可以用線程池來做非同步,不然是會阻塞主線程的。

②非常耗時CPU密集型任務也可以交由線程池來做,不然其他請求要等他執行完才會繼續。

③建議伺服器有幾個核,就起幾個tornado實例

④如果項目很龐大,建議配合任務隊列來玩,如Celery

我目前用的個人blog就是用tornado寫的,也是我自己寫的,放在GitHub上,可以給大家參考,也可以給我多提提意見。

blog:https://blog.52xtg.com/

GitHub:https://github.com/xtg20121013/blog_xtg


Tornado是個博大精深的庫,主要體現在:

  1. 設計模式玩得很溜,而且逼著用戶也要用這套設計模式才能往下寫。
  2. 內置各種常見網路協議的支持:HTTP、FTP、SMTP……
  3. 同時他還是個Web開發框架,當然功能很簡單,但是性能不錯,很適合來做API。

同時由於Tornado跟gevent這種用了大量的C實現的框架不同,是純Python實現的。所以Tornado + PyPy是個絕佳的搭配。

英語好的話可以看一下這篇文章,會讓你很有收穫:Python Libraries - Django, Twisted, Tornado, Flask, Cyclone and Pyramid


一直在用flask和django,看了關於tomado的回答,思路開闊些


這個應用場景不太多,具體還真不是很清楚


學習了,最近在看這個,感覺看了諸多回答之後,思路清晰了很多!謝謝~


是一個很簡單,容易搭建的web server,用來處理些簡單http請求,簡單網站還是不錯的,跟nodejs類似,nodejs比它強點,不過Python庫多


推薦閱讀:

如何快速學會一個web框架?
如何開發一個Python web框架?
什麼時候應該從python2轉向python3?
Python系統實現可插拔python插件?
Django 的最佳開發實踐有哪些?

TAG:Web開發 | Python | Tornado | Nginx | 非同步IO | Python框架 | 非阻塞 |