為什么需要uWSGI?
在生產(chǎn)環(huán)境中部署Python Web項(xiàng)目時(shí),uWSGI負(fù)責(zé)處理Nginx轉(zhuǎn)發(fā)的動(dòng)態(tài)請求,并與我們的Python應(yīng)用程序溝通,同時(shí)將應(yīng)用程序返回的響應(yīng)數(shù)據(jù)傳遞給Nginx。
。
客戶端 <-> Nginx <-> uWSGI <-> Python應(yīng)用程序(Django, Flask)
或許你要問了,Nginx本身就是Web服務(wù)器,我們?yōu)槭裁催€需要uWSGI這個(gè)Web服務(wù)器呢?
Django不是自帶runserver服務(wù)器?
Flask不是自帶Werkzeug嗎?
答案是Nginx處理靜態(tài)文件非常優(yōu)秀,卻不能直接與我們的Python Web應(yīng)用程序進(jìn)行交互。Django和Flask本身是Web框架,并不是Web服務(wù)器,它們自帶的runserver和Werkzeug也僅僅用于開發(fā)測試環(huán)境,生產(chǎn)環(huán)境中處理并發(fā)的能力太弱
為了解決Web 服務(wù)器與應(yīng)用程序之間的交互問題,就出現(xiàn)了Web 服務(wù)器與應(yīng)用程序之間交互的規(guī)范。最早出現(xiàn)的是CGI,后來又出現(xiàn)了改進(jìn) CGI 性能的FasgCGI,Java 專用的 Servlet 規(guī)范。在Python領(lǐng)域,最知名的就是WSGI規(guī)范了。
WSGI 全稱是 Web Server Gateway Interface,
也就是 Web 服務(wù)器網(wǎng)關(guān)接口,是一個(gè)web服務(wù)器(如uWSGI服務(wù)器)與web應(yīng)用(如用Django或Flask框架寫的程序)通信的一種規(guī)范。WSGI包含了很多自有協(xié)議,其中一個(gè)是uwsgi,它用于定義傳輸信息的類型。
現(xiàn)在你清楚uWSGI, WSGI和uwsgi的區(qū)別了嗎?
- uWSGI是Python Web服務(wù)器,實(shí)現(xiàn)了WSGI通信規(guī)范和uwsgi協(xié)議;
- WSGI全名Web Server Gateway Interface,是一個(gè)Web服務(wù)器(如uWSGI服務(wù)器)與web應(yīng)用(如用Django或Flask框架寫的程序)通信的一種規(guī)范;
- uwsgi是WSGI通信規(guī)范中的一種自有協(xié)議。
uWSGI常用配置
uWSGI常用配置選項(xiàng)如下所示,稍加修改(項(xiàng)目名,項(xiàng)目根目錄)即可部署大部分Python Web項(xiàng)目。
[uwsgi] uid=www-data # Ubuntu系統(tǒng)下默認(rèn)用戶名 gid=www-data # Ubuntu系統(tǒng)下默認(rèn)用戶組 project=mysite1 # 項(xiàng)目名 base = /home/user1 # 項(xiàng)目根目錄 home = %(base)/Env/%(project) # 設(shè)置項(xiàng)目虛擬環(huán)境,Docker部署時(shí)不需要 chdir=%(base)/%(project) # 設(shè)置工作目錄 module=%(project).wsgi:application # wsgi文件位置 master=True # 主進(jìn)程 processes=2 # 同時(shí)進(jìn)行的進(jìn)程數(shù),一般 # 以下uwsgi與nginx通信手段3選一即可 # 選項(xiàng)1, 使用unix socket與nginx通信,僅限于uwsgi和nginx在同一主機(jī)上情形 # Nginx配置中uwsgi_pass應(yīng)指向同一socket文件 socket=/run/uwsgi/%(project).sock # 選項(xiàng)2,使用TCP socket與nginx通信 # Nginx配置中uwsgi_pass應(yīng)指向uWSGI服務(wù)器IP和端口 # socket=0.0.0.0:8000 或則 socket=:8000 # 選項(xiàng)3,使用http協(xié)議與nginx通信 # Nginx配置中proxy_pass應(yīng)指向uWSGI服務(wù)器一IP和端口 # http=0.0.0.0:8000 # socket權(quán)限設(shè)置 chown-socket=%(uid):www-data chmod-socket=664 # 進(jìn)程文件 pidfile=/tmp/%(project)-master.pid # 以后臺(tái)守護(hù)進(jìn)程運(yùn)行,并將log日志存于temp文件夾。 daemonize=/var/log/uwsgi/%(project).log # 服務(wù)停止時(shí),自動(dòng)移除unix socket和pid文件 vacuum=True # 為每個(gè)工作進(jìn)程設(shè)置請求數(shù)的上限。當(dāng)處理的請求總數(shù)超過這個(gè)量,進(jìn)程回收重啟。 max-requests=5000 # 當(dāng)一個(gè)請求花費(fèi)的時(shí)間超過這個(gè)時(shí)間,那么這個(gè)請求都會(huì)被丟棄。 harakiri=60 #當(dāng)一個(gè)請求被harakiri殺掉會(huì)輸出一條日志 harakiri-verbose=true # uWsgi默認(rèn)的buffersize為4096,如果請求數(shù)據(jù)超過這個(gè)量會(huì)報(bào)錯(cuò)。這里設(shè)置為64k buffer-size=65536 # 如果http請求體的大小超過指定的限制,打開http body緩沖,這里為64k post-buffering=65536 #開啟內(nèi)存使用情況報(bào)告 memory-report=true #設(shè)置平滑的重啟(直到處理完接收到的請求)的長等待時(shí)間(秒) reload-mercy=10 #設(shè)置工作進(jìn)程使用虛擬內(nèi)存超過多少M(fèi)B就回收重啟 reload-on-as=1024
注意:uWSGI和Nginx之間有3種通信方式, unix socket,TCP socket和http。Nginx的配置必須與uwsgi配置保持一致。
# 選項(xiàng)1, 使用unix socket與nginx通信 # 僅限于uwsgi和nginx在同一主機(jī)上情形 # Nginx配置中uwsgi_pass應(yīng)指向同一socket文件地址 socket=/run/uwsgi/%(project).sock # 選項(xiàng)2,使用TCP socket與nginx通信 # Nginx配置中uwsgi_pass應(yīng)指向uWSGI服務(wù)器IP和端口 socket==0.0.0.0:8000 或則 socket=:8000 # 選項(xiàng)3,使用http協(xié)議與nginx通信 # Nginx配置中proxy_pass應(yīng)指向uWSGI服務(wù)器IP和端口 http==0.0.0.0:8000
如果你的nginx與uwsgi在同一臺(tái)服務(wù)器上,優(yōu)先使用本地機(jī)器的unix socket進(jìn)行通信,這樣速度更快。此時(shí)nginx的配置文件如下所示:
location / { include /etc/nginx/uwsgi_params; uwsgi_pass unix:/run/uwsgi/project.sock; }
如果nginx與uwsgi不在同一臺(tái)服務(wù)器上,兩者使用TCP socket通信時(shí),nginx可使用如下配置:
location / { include /etc/nginx/uwsgi_params; uwsgi_pass uWSGI_SERVER_IP:8000; }
如果nginx與uwsgi不在同一臺(tái)服務(wù)器上,兩者使用http協(xié)議進(jìn)行通信,nginx配置應(yīng)修改如下:
location / { # 注意:proxy_pass后面http必不可少哦! proxy_pass http://uWSGI_SERVER_IP:8000; }