1. 程式人生 > >Nginx+uWSGI+Django原理(轉發)

Nginx+uWSGI+Django原理(轉發)

.html web服務器 開始 git 性能 ast host common protocol

Python的Web開發中,如果使用Django框架,那麽較為成熟穩定的服務器架構一般是Nginx+uWSGI+Django。而為什麽一定要三個結合在一起呢?直接使用Django的runserver來啟動服務器進程,或者uWSGI+Django可不可以呢?為什麽?
概念說明:

  • APP(應用程序),就是開發者寫的應用程序,例如django,bottle這些。記錄怎麽處理客戶端發來的請求的邏輯部分。
  • WSGI,是一個協議,Python用於Web開發的協議
  • uWSGI,是一個程序,充當Web服務器或中間件。
    • 如果架構是Nginx+uWSGI+APP,uWSGI是一個中間件
    • 如果架構是uWSGI+APP,uWSGI是一個服務器
  • uwsgi,是uWSGI程序實現的一個自有的協議。

Web協議出現順序:
CGI -> FCGI -> WSGI -> uwsgi

  1. CGI,最早的協議
  2. FCGI,比CGI快
  3. WSGI,Python專用的協議
  4. uwsgi,比FCGI和WSGI都快,是uWSGI項目自有的協議,主要特征是采用二進制來存儲數據,之前的協議都是使用字符串,所以在存儲空間和解析速度上,都優於字符串型協議.官方介紹

一、WSGI協議

瀏覽器請求一個頁面的流程:

  1. 瀏覽器發送請求給服務器,包含請求頭和請求體
  2. 服務器解析請求頭和請求體
  3. 服務器根據請求信息來處理請求,生成返回內容
  4. 服務器生成響應頭和響應體
  5. 服務器返回響應給瀏覽器,瀏覽器顯示給用戶

一個網站,一般有很多個不同的請求,在這些請求中,基本1,2,4,5部都是固定的,變的只有第三步,所以把這四步抽象出來,讓開發者只關註第三步,這樣就可以極大提升開發效率。所以WSGI協議誕生了。
WSGI,全稱 Web Server Gateway Interface。是Python專用的協議,其他語言沒有。用於處理Web服務器和應用程序(APP)的交互信息。很多Web框架(如:django)都會自帶WSGI服務器,但是性能不好,只作測試用途。

實現一個最簡單的服務器

  1. app.py
  1. import pprint
  2. def application(environ, start_response):
  3. pprint.pprint(environ)
  4. start_response(‘200 OK‘,[(‘Content-Type‘,‘text/html‘)])
  5. return‘<h1>Hello, web!</h1>‘
  • environ參數是一個字典對象,保存HTTP請求的信息。例如URL路徑,域名,請求頭,請求參數等
  • start_response參數是一個函數,用於向wsgiref提供響應頭的設置,只能調用一次。
  1. server.py
  1. # 從wsgiref模塊導入:
  2. from wsgiref.simple_server import make_server
  3. # 導入我們自己編寫的application函數:
  4. from app import application
  5. # 創建一個服務器,IP地址為空,端口是8000,處理函數是application:
  6. httpd = make_server(‘‘,8000, application)
  7. print"Serving HTTP on port 8000..."
  8. # 開始監聽HTTP請求:
  9. httpd.serve_forever()
  1. 啟動python server.py,就可以通過localhost:8000訪問了

wsgiref模塊是python提供的,用於測試和學習的簡單的WSGI服務器模塊。
這個模塊監聽8000端口,把Http請求,根據WSGI協議,轉換application函數中的environ參數,然後調用application函數。
wsgiref會把application函數提供的響應頭設置轉換為HTTP協議的響應頭,把application的返回(return)作為響應體,根據HTTP協議,生成響應,返回給瀏覽器。

技術分享

這樣,應用程序就不需要關註底層的HTTP協議細則了

二、CGI和FastCGI

CGI是Common Gateway Interface,即通用網關接口,是一個協議,是外部應用程序(CGI程序)與Web服務器之間的接口標準。該協議定義了Web服務器在調用應用程序時需要傳輸的參數和應用程序怎麽返回結果給Web服務器,其實跟WSGI類似。
CGI的一個特點是,對於每一個HTTP請求,Web服務器都會新建一個進程(fork),等應用程序返回結果後,這個進程就會結束。這樣的後果是,一旦HTTP請求多的時候,Web服務器會頻繁創建進程,大家都知道,創建進程的開銷是非常大的,所以這種做法會影響服務器的性能,所以就有了FastCGI。
FCGI的做法是在Web服務器啟動的時候,就創建多個應用程序進程,當Web服務器接收到HTTP請求時,就把請求分發給其中一個空閑的進程。相當於MYSQL連接池的原理。這樣就可以避免頻繁地fork進程。FCGI另一個特點是支持分布式,也就是Web服務器和應用程序可以在不同的機器。
CGI和WSGI的區別是

  • CGI的出現更加早,這個是通用的接口,應用程序可以是JAVA,Python,等多種語言程序
  • WSGI是Python專用的,在CGI的基礎上改進的協議

三、Nginx

Ningx是一個反向代理服務器
什麽是反向代理?

  1. 正向代理,例如FQ用的代理服務器就是正向代理,瀏覽器主動請求代理服務器,代理服務器轉發請求到對應的目標服務器
  2. 反向代理,部署在Web服務器上,代理所有外部網絡對內部網絡的訪問。瀏覽器訪問服務器,必須經過這個代理,是被動的。
    正向代理的主動方是客戶端,反向代理的主動方是Web服務器。
    結構圖:
    技術分享

反向代理的作用:

  1. 安全,客戶端對Web服務器的訪問需要先經過反向代理服務器。這樣可以防止外部程序對Web服務器的直接攻擊。
  2. 負載均衡,反向代理服務器可以根據Web服務器的負載情況,動態地把HTTP請求交給不同的Web服務器來處理,前提是要有多個Web服務器。
  3. 提升Web服務器的IO性能。一個HTTP請求的數據,從客戶端傳輸給服務器,是需要時間的,例如N秒,如果直接傳給Web服務器,Web服務器就需要讓一個進程阻塞N秒,來接收IO,這樣會降低Web服務器的性能。如果使用反向代理服務器,先讓反向代理服務器接收完整個HTTP請求,再把請求發給Web服務器,就能提升Web服務器的性能。還有一些靜態文件的請求,可以直接交給反向代理來處理,不需要經過Web服務器。

Nginx是一個高性能的HTTP和反向代理服務器。

Nginx+uWSGI+應用程序的架構:
技術分享

其中Nginx和uWSGI之間可以通過CGI,FCGI和uwsgi協議通信,當然uwsgi的性能是最好的。

四、總結

  1. uWSGI+Django比單獨使用Django的好處:
    • 支持的並發量更高
    • 方便管理多進程,發揮多核的優勢
    • 提升性能,因為uwsgi協議比WSGI協議有優勢
  2. Nginx+uWSGI+Django比uWSGI+Django好處(參考反向代理的作用):

最後附上一個介紹Nginx+uWSGI+Django的幻燈片

參考:
http://www.biaodianfu.com/cgi-fastcgi-wsgi.html
http://blog.csdn.net/qiaofeiw/article/details/9207359
http://www.cnblogs.com/wanghetao/p/3934350.html
http://book.51cto.com/art/201202/314840.htm
http://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/001386832689740b04430a98f614b6da89da2157ea3efe2000
https://www.douban.com/note/13508388/
http://www.nowamagic.net/academy/detail/1330308
http://www.itopers.com:8080/?p=586

Nginx+uWSGI+Django原理(轉發)