http://www.cnblogs.com/wuvist/archive/2011/06/28/django-and-tornado.html
介紹兩個Python web架構:Django & Tornado
在各種語言平台中,python湧現的web架構恐怕是最多的;猜想原因應該是在py中構造架構十分簡單,使得輪子不斷被發明。
這裡記述一下我了解過的兩個py web架構,供大家參考,希望能起他山之石的作用。
====== Django ======
Django 應該是最出名的py架構,Google App Engine甚至Erlang都有架構受它影響。
Django是走大而全的方向,它最出名的是其全自動化的管理背景:隻需要使用起ORM,做簡單的對象定義,它就能自動生成資料庫結構、以及全功能的管理背景。
Django提供的友善,也意味着Django内置的ORM跟架構内的其他子產品耦合程度高。
應用程式必須使用Django内置的ORM,否則就不能享受到架構内提供的種種基于其ORM的便利;理論上可以切換掉其ORM子產品,但這就相當于要把裝修完畢的房子拆除重新裝修,倒不如一開始就去毛胚房做全新的裝修。
Django的賣點是超高的開發效率,其性能擴充有限;采用Django的項目,在流量達到一定規模後,都需要對其進行重構,才能滿足性能的要求。
這方面的經驗可以參考:http://www.slideshare.net/zeeg/djangocon-2010-scaling-disqus
Ruby的Rails也有類似的問題;以Twitter為例,推特到了今日的規模,不要說Rails,甚至是連Ruby都需要抛棄重來。
就我的感覺Django适用的是中小型的網站,或者是作為大型網站快速實作産品雛形的工具。
快速推出産品是王道:
Believe it or not, the bigger problem isn't scaling, it's getting to the point where you have to scale. Without the first problem you won't have the second. - http://gettingreal.37signals.com/ch04_Scale_Later.php
===== Django 模闆 =====
Django的模闆系統設計十分有意思,也應該其架構内影響最大、争議最大的部分。
Django模闆的設計哲學是徹底的将代碼、樣式分離;asp.net提倡将代碼/模闆分離,但技術上還是可以混合;而Django則是從根本上杜絕在模闆中進行編碼、處理資料的可能。
比方說,asp.net模闆中可以寫:
<%
int i;
for(i==0;i<10;i++){
....
}
%>
Django是徹底不支援嵌入類似上面的代碼,僅能使用其模闆内置的函數;這實際上,是為其模闆構造了一種“新語言”;由于此“新語言”十分簡單,是以也能夠将其模闆移植到不同平台。
大多數情況下,Django的模闆功能是足夠的,但對于特殊(有時“特殊”也不是十分特殊)的情況,還是需要在模闆中嵌入代碼,那麼就需要根據其模闆系統的規則做模闆擴充。有時候,模闆中直接寫一行代碼能夠解決的問題,用模闆擴充實作後,會變成十幾行代碼。
是否容忍在模闆中程式設計,正是Django模闆争議最大之處。
====== Tornado ======
Tornado( http://www.tornadoweb.org )是Facebook開源出來的架構, 其哲學跟Django近乎兩個極端。
Tornado走的是少而精的方向,它也有提供模闆功能;雖然不鼓勵,但作者是可以允許在模闆進行少量編碼(直接嵌入單行py代碼)的。
如果跟asp.net相比,Tornado有點類似僅實作了AsyncHttpHandler;除此之外,全部需要自己去實作。
好吧,其實它有模闆,有國際化支援,甚至還有内置的OAuth/OpenID子產品,友善做第三方登入,它其實也直接實作了Http伺服器。
但它沒有ORM(僅有一個mysql的超簡單封裝),甚至沒有Session支援,更不要說Django那樣自動化的背景。
ORM對象關系映射,面向對象是從軟體工程基本原則(如耦合、聚合、封裝)的基礎上發展起來的,而關系資料庫則是從數學理論發展而來的,兩套理論存在顯著的差別。為了解決這個不比對的現象,對象關系映射技術應運而生。
你用O/R Mapping儲存,删除,讀取對象,O/R Mapping負責生成SQL,你隻需要關心對象就好。
假設是一個大型網站,在高性能的要求下,架構的各個部分往往都需要定制,可以複用的子產品非常少;一個以Django開發的網站,各部分經過不斷的定制,Django架構剩下的,很有可能也就是tornado一開始所能提供的這部分。
殊途同歸。
===== HTTP伺服器 =====
Tornado為了高效實作Comet/後端異步調用HTTP接口,是直接内嵌了HTTP伺服器。
前端無需加apache / lighttpd / nginx等也可以供浏覽器通路;但它并沒有完整實作HTTP 1.1的協定,是以官方文檔是推薦使用者在生産環境下在前端使用nginx,後端反向代理到多個Tornado執行個體。
Tornado本身是單線程的異步網絡程式,它預設啟動時,會根據CPU數量運作多個執行個體;充分利用CPU多核的優勢。
===== 單線程異步 =====
網站基本都會有資料庫操作,而Tornado是單線程的,這意味着如果資料庫查詢傳回過慢,整個伺服器響應會被堵塞。
資料庫查詢,實質上也是遠端的網絡調用;理想情況下,是将這些操作也封裝成為異步的;但Tornado對此并**沒有**提供任何支援。
這是Tornado的**設計**,而不是缺陷。
一個系統,要滿足高流量;是必須解決資料庫查詢速度問題的!
資料庫若存在查詢性能問題,整個系統無論如何優化,資料庫都會是瓶頸,拖慢整個系統!
異步并**不能**從本質上提到系統的性能;它僅僅是避免多餘的網絡響應等待,以及切換線程的CPU耗費。
如果資料庫查詢響應太慢,需要解決的是資料庫的性能問題;而不是調用資料庫的前端Web應用。
對于實時傳回的資料查詢,理想情況下需要確定所有資料都在記憶體中,資料庫硬碟IO應該為0;這樣的查詢才能足夠快;而如果資料庫查詢足夠快,那麼前端web應用也就無将資料查詢封裝為異步的必要。
就算是使用協程,異步程式對于同步程式始終還是會提高複雜性;需要衡量的是處理這些額外複雜性是否值得。
如果後端有查詢實在是太慢,無法繞過,Tornaod的建議是将這些查詢在後端封裝獨立封裝成為HTTP接口,然後使用Tornado内置的異步HTTP用戶端進行調用。