今天我們來討論一下、django、flask和tornado的部署對比:
1. 概述
在python的web開發框架中,目前使用量最高的幾個是django、flask和tornado, 經常會有人拿這幾個對比,相信大家的初步印象應該是 django大而全、flask小而精、tornado性能高。
tornado性能比django和flask高很多是因為tornado在底層io處理機制上和django以及flask有著根本的區別:
1\. tornado、gevent、asyncio、aiohttp:底層使用的是事件循環+協程
2\. django和flask: 傳統的模型,阻塞io模型
雖然django和flask比tornado和asyncio性能低,但是他們作為老牌的框架:生態豐富,代碼容易理解,簡單啊!但是我相信通過asyncio和tornado進行并發編程必定會成為未來的另一個主流方向。這里我個人更看好基于asyncio的框架。nodejs和go語言都得益于協程輕松實現了高并發。
但是今天我們要介紹的并不是協程,而是從這些框架的部署來進行對比:
2. django和flask
在django和flask部署中,我們經常會遇到以下幾個概念:
web框架、 wsgi、 uwsgi、 uWSGI、 nginx
這些概念是什么意思:
- WSGI:全稱是Web Server Gateway Interface,WSGI不是服務器,python模塊,框架,API或者任何軟件,只是一種規范,描述web server如何與web application通信的規范。要實現WSGI協議,必須同時實現web server和web application,當前運行在WSGI協議之上的web框架有Bottle, Flask, Django。
- uwsgi:與WSGI一樣是一種通信協議,是uWSGI服務器的獨占協議,用于定義傳輸信息的類型(type of information)
- uWSGI:是一個web服務器,實現了WSGI協議、uwsgi協議、http協議等。
- WSGI協議主要包括server和application兩部分:
- WSGI server負責從客戶端接收請求,將request轉發給application,將application返回的response返回給客戶端;
- WSGI application接收由server轉發的request,處理請求,并將處理結果返回給server。application中可以包括多個棧式的中間件(middlewares),這些中間件需要同時實現server與application,因此可以在WSGI服務器與WSGI應用之間起調節作用:對服務器來說,中間件扮演應用程序,對應用程序來說,中間件扮演服務器。
- WSGI協議其實是定義了一種server與application解耦的規范,即可以有多個實現WSGI server的服務器,也可以有多個實現WSGI application的框架,那么就可以選擇任意的server和application組合實現自己的web應用。例如uWSGI和Gunicorn都是實現了WSGI server協議的服務器,Django,Flask是實現了WSGI application協議的web框架,可以根據項目實際情況搭配使用。
像Django,Flask框架都有自己實現的簡單的WSGI server,一般用于服務器調試,生產環境下建議用其他WSGI server。比如django啟動 manage.py runserver 就是啟動的這個,這種只適用于本地開發的時候使用,線上運行還是需要配置nginx+uwsgi+django才行。
wsgi 除了解析 http 協議以及 http 端口偵聽外,還負責了流量轉發以及 wsgi application 進程管理的功能。一般 wsgi 框架內置的 wsgi server 都是一個單進程,一次只能處理一個請求。而目的通用的 wsgi server(gunicorn, uwsgi)都至少支持 pre fork 模型,這種模型會起一個 master 來偵聽請求,并啟動多個 slave(每個 slave 是一個 wsgi application), master 負責把請求轉發到空閑的 slave 上。除了這種傳統的基于進程的 pre fork 同步模型,不同的 wsgi server 也會支持一些其它模型,有基于線程的同步模型,也有基于 asyncio 的異步模型。
3. nginx又有什么用呢?
-
Ningx是一個反向代理服務器
什么是反向代理?
正向代理,例如FQ用的代理服務器就是正向代理,瀏覽器主動請求代理服務器,代理服務器轉發請求到對應的目標服務器
反向代理,部署在Web服務器上,代理所有外部網絡對內部網絡的訪問。瀏覽器訪問服務器,必須經過這個代理,是被動的。
正向代理的主動方是客戶端,反向代理的主動方是Web服務器。
-
主要是因為 wsgi server 支持的并發量比較低,一般會用一個專門的 http server 來做一層緩沖,避免并發量過大時直接服務掛掉。
反向代理的作用:
1. 安全,客戶端對Web服務器的訪問需要先經過反向代理服務器。這樣可以防止外部程序對Web服務器的直接攻擊。
2. 負載均衡,反向代理服務器可以根據Web服務器的負載情況,動態地把HTTP請求交給不同的Web服務器來處理,前提是要有多個Web服務器。
3. 提升Web服務器的IO性能。一個HTTP請求的數據,從客戶端傳輸給服務器,是需要時間的,例如N秒,如果直接傳給Web服務器,Web服務器就需要讓一個進程阻塞N秒,來接收IO,這樣會降低Web服務器的性能。如果使用反向代理服務器,先讓反向代理服務器接收完整個HTTP請求,再把請求發給Web服務器,就能提升Web服務器的性能。還有一些靜態文件的請求,可以直接交給反向代理來處理,不需要經過Web服務器。
Nginx是一個高性能的HTTP和反向代理服務器。
4. Nginx+uWSGI+應用程序的架構
5. django如何編寫異步代碼呢?
1\. 直接用傳統的異步編程(進程,線程,協程),雖然有些 wsgi server 支持 asynio 模型,但是這也需要用戶所寫的代碼做相應的支持。這就導致了如果我們在 wsgi application 的時候不能隨便使用線程和異步 IO ,如果用了就需要配置 wsgi server 使其支持我們自己的寫法。因此為了使得我們縮寫的 application 能部署在任意的 wsgi server(container)中,我們就只能寫同步代碼了。
2\. 使用分布式異步編程,使用類似 celery 的方式,將需要異步處理的東西發送到 worker 去處理。
python 傳統的這種 wsgi 模型,主要是為了方便框架開發者只需要專注框架層面,而非 http 處理層面。但這樣卻增加了服務部署的復雜度,需要同時部署和配置 http server 和 wsgi server ,如果想支持異步還要部署 worker ,而使用 tornado 或 go 開發的應用因為自己實現了高效 http 處理的應用只需要部署自己就可以了。
6. asyncio VS tornado
asyncio作為python的原始協程庫,也是python最具野心和將來會重點打造的模塊,asyncio提供了更多的基礎功能,tornado是web服務器和web框架,兩者原理是一樣的,都有很不錯的發展。
- twisted 這種模型:
這種模型和上面的傳統模型處于一個時期,這種模型和 nodejs 差不多,都是基于回調的模型,適用于高 IO 低 CPU 的場景。這種模型自己實現了一個基于回調 http server(event loop),每一個請求都被注冊成一個異步函數來處理,然后主循環來不斷的循環這些函數。這樣就和 pre fork 模型有了區別, pre fork 模型中每一個 slave 都是一個 wsgi application ,一個 wsgi application 都只能處理一個請求,而回調模型只有一個線程,不僅極大的減少了內存的分配還減小了進城以及線程間的切換開銷,從而可以支持高 IO 并發。但是這種模型也有很明顯的缺點,就是一旦應用程序有大量的 CPU 計算,就會讓這個線程堵住,所有的請求都會收到影響,如果應用在處理一個請求時崩潰,所有的請求也都會收到影響。
-
asyncio、tornado、gevent 這種模型:
因為回調的寫法不易讀也容易出錯,于是將回調的寫法改成了同步的寫法。這種模型和 koa2 和 go net/http 查不多, asyncio 提供了類似 go coroutine 的功能和寫法,而 aiohttp 則提供了類似 go 中的 net/http 的 http 處理庫。
想要徹底理解tornado這種模式以及想要自己去實現高并發的web服務器我們需要理解協程,協程理解比線程和進程難不少,最復雜的調度機制,通過asyncio去理解會相對容易
點擊查看更多內容
作者:bobby
鏈接:https://www.imooc.com/article/details/id/24759
來源:慕課網
本文原創發布于慕課網 ,轉載請注明出處,謝謝合作