WSGI(the Python Web Server Gateway Interface)指Python的Web服務(wù)的網(wǎng)關(guān)接口。從名稱上看,WSGI是一個(gè)網(wǎng)關(guān),網(wǎng)關(guān)的作用是在協(xié)議之間進(jìn)行轉(zhuǎn)換。因此,WSGI是一個(gè)Web服務(wù)器與Django等程序進(jìn)行通信的規(guī)范或者協(xié)議。WSGI 是作為 Web 服務(wù)器與 Web 應(yīng)用程序或應(yīng)用框架之間的一種低級別的接口,以提升可移植 Web 應(yīng)用開發(fā)的共同點(diǎn)。WSGI 是基于現(xiàn)存的 CGI 標(biāo)準(zhǔn)而設(shè)計(jì)的。簡單來說,WSGI就是一種協(xié)議規(guī)范,起到規(guī)范參數(shù)的作用,類似于高速公路上的限速一樣,規(guī)定你此路段不能超過100km/h,同時(shí)一條高速公路有兩個(gè)地點(diǎn),如京滬高速,北京跟上海各占一端,那么他們之間的行車規(guī)范就按照WSGI規(guī)則進(jìn)行。即WSGI溝通的雙方是wsgi server(uWSGI)和 wsgi application(django)。
wsgi server (uWSGI)實(shí)現(xiàn)wsgi協(xié)議規(guī)范的服務(wù)器叫做wsgi服務(wù)器,也就是uWSGI服務(wù)器。
wsgi application (Django) 用以實(shí)現(xiàn)wsgi協(xié)議的應(yīng)用,叫做wsgi應(yīng)用,如Django,F(xiàn)alsk等。
uWSGI是一個(gè)快速的、純C語言開發(fā)的、自維護(hù)的等WSGI服務(wù)器,旨在實(shí)現(xiàn)專業(yè)的Python Web應(yīng)用開發(fā)和發(fā)布,它實(shí)現(xiàn)了WSGI、uwsgi、HTTP等協(xié)議。Nginx中HttpUwsgiModule的作用是與uWSGI服務(wù)器進(jìn)行交換。
uWSGI是一個(gè)web服務(wù)器,或者是是wsgi server 服務(wù)器。其作用就是接收用戶請求,用戶請求是通過網(wǎng)絡(luò)使用http協(xié)議發(fā)來的,因此服務(wù)器要想正確解析http協(xié)議就需要uWSGI實(shí)現(xiàn)解析 。當(dāng)uWSGI解析成功后就需要把解析出來的信息發(fā)給Django,此時(shí)就需要WSGI協(xié)議了。uWSGI實(shí)現(xiàn)了WSGI協(xié)議,所以uWSGI將用戶請求的信息做一下簡單的封裝處理通過WSGI協(xié)議發(fā)送給后端的Django,Django接受的請求后先通過一層層中間件,并根據(jù)其請求的url發(fā)送給不同的視圖函數(shù)(View),視圖函數(shù)通過處理在依次返回Django,Django通過WSGI協(xié)議返回給uWSGI服務(wù)器。uWSGI服務(wù)器最后返回給請求的用戶。受Django自帶的web服務(wù)器性能原因(單進(jìn)程單線程,處理請求慢等),因此在開發(fā)過程中,使用uWSGI來代替Django自帶的服務(wù)器。
上面的這個(gè)流程似乎并沒有涉及uwsgi,不急,慢慢看下文:
uWSGI雖然也能處理靜態(tài)資源,但能力遠(yuǎn)不如高效的Nginx,并且生產(chǎn)環(huán)境下需要為集群實(shí)現(xiàn)負(fù)載均衡的功能,那么就會(huì)使用Nginx作為上游服務(wù)器用做處理靜態(tài)資源以實(shí)現(xiàn)負(fù)載均衡。而使用nginx的proxy_pass功能向uWSGI轉(zhuǎn)發(fā)http包,因他們之間使用的是http協(xié)議,所以需要用--http-socket
模式啟動(dòng),nginx就能向uWSGI發(fā)送請求了。但是使用proxy_pass代理發(fā)送請求給uWSGI的架構(gòu),有個(gè)缺點(diǎn),即http協(xié)議解析了兩次,nginx和uWSGI各自解析了一次,因此效率會(huì)慢點(diǎn)。因此uWSGI就開發(fā)出了uwsgi協(xié)議,該協(xié)議解析比http解析快,如果上游服務(wù)(Nginx)能夠兼容uwsgi協(xié)議,那么上游Nginx與uWSGI之間就能通過uwsgi進(jìn)行溝通并傳輸數(shù)據(jù),該情況下,http只在上游解析了一次,效率更高。因此uwsgi應(yīng)運(yùn)而生。常用的Nginx、Apache都兼容uwsgi協(xié)議,若使用uwsgi協(xié)議,則需要用--http-socket
,上游服務(wù)器Nginx使用uwsgi_pass
代替proxy_pass
uwsgi是一個(gè)具體的線路協(xié)議,用來實(shí)現(xiàn)uWSGI服務(wù)器與其他服務(wù)軟件(例如:Nginx)的數(shù)據(jù)通信。uwsgi官方文檔
整體流程如下:
在django帶有manange.py的同一級目錄下常見一個(gè)uwsgi.ini文件,文件內(nèi)容如下:
[uwsgi]
# 指定項(xiàng)目的路徑,及帶有manage.py的上一級目錄
chdir = /home/user/maproject/backma
# wsgi文件路徑,即帶有wsgi.py 的文件
module = config.wsgi
# the virtualenv path 虛擬環(huán)境安裝目錄,我的虛擬環(huán)境名為django,不知道可以使用which django查看一下,直接復(fù)制粘貼過來。
virtualenv = /root/.virtualenvs/django
# 是否開啟master進(jìn)程,啟動(dòng)主進(jìn)程,來管理其他進(jìn)程,其它的uwsgi進(jìn)程都是這個(gè)master進(jìn)程的子進(jìn)程,如果kill這個(gè)master進(jìn)程,相當(dāng)于重啟所有的uwsgi進(jìn)程。
master= true
# process-related settings
master = /home/user/maproject/logs/uwsgi88.pid
# 工作進(jìn)程的大數(shù)目,指定uwsgi啟動(dòng)的進(jìn)程數(shù)
processes = 4
#啟動(dòng)2兩個(gè)線程數(shù)
threads = 2
# 使用nginx時(shí)使用socket參數(shù),一定要跟nginx的配置的轉(zhuǎn)發(fā)接口一致。
socket = 127.0.0.1:8080
# 當(dāng)服務(wù)器退出時(shí)自動(dòng)刪除unix socket文件和pid文件,結(jié)束后是否清理文件
vacuum = true
# 后臺啟動(dòng),使進(jìn)程在后臺運(yùn)行,并將日志打到指定的日志文件或者udp服務(wù)器
daemonize = /home/user/maproject/logs/django_logs.log
#指定pid文件
pidfile = /var/run/uwsgi.pid
# 設(shè)置用于uwsgi包解析的內(nèi)部緩存區(qū)大小為64k,默認(rèn)是4k。
buffer-size = 65535
#為每個(gè)工作進(jìn)程設(shè)置請求數(shù)的上限。當(dāng)一個(gè)工作進(jìn)程處理的請求數(shù)達(dá)到這個(gè)值,那么該工作進(jìn)程就會(huì)被回收重用(重啟)。你可以使用這個(gè)選項(xiàng)來默默地對抗內(nèi)存泄漏。
max-requests = 5000
#通過使用POSIX/UNIX的setrlimit()函數(shù)來限制每個(gè)uWSGI進(jìn)程的虛擬內(nèi)存使用數(shù)。這個(gè)配置會(huì)限制uWSGI的進(jìn)程占用虛擬內(nèi)存不超過256M。如果虛擬內(nèi)存已經(jīng)達(dá)到256M,并繼續(xù)申請?zhí)摂M內(nèi)存則會(huì)使程序報(bào)內(nèi)存錯(cuò)誤,本次的http請求將返回500錯(cuò)誤。
limit-as = 256
#一個(gè)請求花費(fèi)的時(shí)間超過了這個(gè)harakiri超時(shí)時(shí)間,那么這個(gè)請求都會(huì)被丟棄,并且當(dāng)前處理這個(gè)請求的工作進(jìn)程會(huì)被回收再利用(即重啟)
harakiri = 60
在uwsgi.ini當(dāng)前目錄下啟動(dòng)uwsgi,啟動(dòng)命令如下:
uwsgi --ini uwsgi.ini
關(guān)閉uwsgi服務(wù),命令如下:
pkill -f uwsgi -9
四、WSGI、uWSGI與uwsgi三者關(guān)系即歸納WSGI:網(wǎng)關(guān)、接口。
uwsgi:線路協(xié)議。
uWSGI:一種服務(wù)的具體實(shí)現(xiàn)。
為什么使用了uWSGI還需要使用Nginx?
前面說過,uWSGI雖然能處理靜態(tài)資源,但遠(yuǎn)不能如Nginx處理的高效,并且考慮為集群實(shí)現(xiàn)負(fù)載均衡,所以,在一般的生產(chǎn)環(huán)境下,使用Nginx+uWSGI(或者Gunicorn)來對網(wǎng)站進(jìn)行部署。
使用了uWSGI還使用Nginx的好處如下:
Nginx處理靜態(tài)文件更有優(yōu)勢,性能更好。
Nginx更安全。
Nginx可以進(jìn)行多臺機(jī)器的負(fù)載均衡。
nginx是一個(gè)高性能的http和反向代理服務(wù)器,也是IMAP/POP3/SMTP代理服務(wù)器,其以事件驅(qū)動(dòng)的方式編寫。
在性能上,Nginx占用很少的系統(tǒng)資源,支持更多的并發(fā)連接,可達(dá)到更高的訪問效率。
在功能上,Nginx是優(yōu)秀的代理服務(wù)器和負(fù)載均衡服務(wù)器。
在安裝配置上,Nginx安裝簡單、配置靈活。
Nginx支持熱部署,啟動(dòng)速度快,可以在不間斷的情況下對軟件版本或配置進(jìn)行升級,且運(yùn)行數(shù)個(gè)月也無需重啟。
簡單說一下Nginx的正向代理和反向代理:
正向代理:
正向代理,代理的是客戶端,用戶的一切請求都交給代理服務(wù)器去完成,至于代理服務(wù)器如何完成,用戶可以不用關(guān)心。其大的特點(diǎn)是客戶端非常明確要訪問的服務(wù)器地址,服務(wù)器只清楚來自哪個(gè)代理服務(wù)器,而不清楚來自哪個(gè)具體的客戶端正向代理模式屏蔽或隱藏了真實(shí)客戶端信息。
反向代理:
反向代理,代理的是服務(wù)器,隱藏了服務(wù)器的信息。如,當(dāng)打開購物商城網(wǎng)站時(shí),(現(xiàn)在網(wǎng)站都是分布式部署),瀏覽的某一頁信息或者發(fā)送某個(gè)請求給反向代理服務(wù)器,該請求由反向代理具體分發(fā)到某一臺服務(wù)器上去完成相關(guān)的請求處理,對用戶而言,是感受不到反向代理的存在的。其大特點(diǎn)是:客戶端是無感知代理的存在的,反向代理對外是透明的,訪問者并不知道自己訪問的是一個(gè)代理,因?yàn)榭蛻舳瞬恍枰渲镁涂梢栽L問。反向代理,”它代理的是服務(wù)端,代理服務(wù)端接受請求“,且反向代理隱藏了服務(wù)器的信息。
#查看版本號
nginx -v
#啟動(dòng)nginx
service nginx start
#重啟
service nginx restart
#重載
nginx -s reload
#停止nginx
nginx -s stop #直接停止
nginx -s quit #完成已經(jīng)接收的連接請求后再退出
#查看nginx進(jìn)程
ps -ef | grep nginx
Nginx文件保存位置:/usr/sbin/nginx:主程序
/etc/nginx:存放配置文件
/usr/share/nginx:存放靜態(tài)文件
/var/log/nginx:存放日志
Nginx配置文件詳解:利用vi 命令打開/etc/nginx/nginx.conf
nginx配置文件大致分為三部分:全局部分、event部分、http部分。
1. 全局部分:
#指定nginx運(yùn)行的用戶及用戶組,默認(rèn)為nobody,可以使用linux的user用戶運(yùn)行ngixn,不要使用root,有風(fēng)險(xiǎn)存在。
user nobody;
#開啟的進(jìn)程數(shù),一般小于或等于CPU數(shù)
worker_processes 1;
#定位全局錯(cuò)誤日志文件,級別以notice顯示,還有debug,info,warn,error,crit模式,
#debug輸出最多,crir輸出最少,根據(jù)實(shí)際環(huán)境而定
error_log logs/error.log;
error_log logs/error.log notice;
error_log logs/error.log info;
#指定進(jìn)程號的保存位置
pid logs/nginx.pid;
2. events部分:
events { #設(shè)置工作模式為epoll,除此之外還有select,poll,kqueue,rtsig和/dev/poll模式
use epoll;
#定義每個(gè)進(jìn)程的大連接數(shù),受系統(tǒng)進(jìn)程的大打開文件數(shù)量限制,默認(rèn)為1024.
worker_connections 1024;
}
3. http部分:
http部分包括的參數(shù)有文件引入、日志格式定義、連接數(shù)等,其中server塊相當(dāng)于一個(gè)站點(diǎn)、一個(gè)http塊可以有多個(gè)server塊。
2 http { #文件擴(kuò)展名與文件類型的映射。主模塊指令,實(shí)現(xiàn)對配置文件所包含的文件的設(shè)定,可以減少主配置文件的復(fù)雜度。
include mime.types;
#默認(rèn)文件類型。核心模塊指令,智力默認(rèn)設(shè)置為二進(jìn)制流,也就是當(dāng)文件類型未定義時(shí)使用這種方式
default_type application/octet-stream;
#日志文件的輸出格式,main為日志格式的名稱,可自行設(shè)置,后面引用
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
#引用日志main,
access_log logs/access.log main;
#設(shè)置允許客戶端請求的大的單個(gè)文件字節(jié)數(shù)
#client_max_body_size 20M;
#指定來自客戶端請求頭的headebuffer大小
#client_header_buffer_size 32k;
#指定連接請求試圖寫入緩存文件的目錄路徑
#client_body_temp_path /dev/shm/client_body_temp;
#指定客戶端請求中較大的消息頭的緩存大數(shù)量和大小,目前設(shè)置為4個(gè)32KB
#large client_header_buffers 4 32k;
#設(shè)置客戶端連接保存活動(dòng)的超時(shí)時(shí)間
keepalive_timeout 65;
#開啟高效文件傳輸模式
#sendfile on;
#開啟防止網(wǎng)絡(luò)阻塞
#tcp_nopush on;
#開啟防止網(wǎng)絡(luò)阻塞
#tcp_nodelay on;
#設(shè)置客戶端請求讀取超時(shí)時(shí)間
#client_header_timeout 10;
#設(shè)置客戶端請求主體讀取超時(shí)時(shí)間
#client_body_timeout 10;
#用于設(shè)置相應(yīng)客戶端的超時(shí)時(shí)間
#send_timeout
#server配置
server { #監(jiān)聽端口為 80
listen 80 default_server;
#設(shè)置主機(jī)域名或Ip
server_name 192.168.2.101;
#設(shè)置訪問的語言編碼
#charset koi8-r;
#設(shè)置虛擬主機(jī)訪問日志的存放路徑及日志的格式為main
#access_log logs/host.access.log main;
#設(shè)置虛擬主機(jī)的基本信息
location / { #設(shè)置虛擬主機(jī)的網(wǎng)站根目錄,前端vue開發(fā)的靜態(tài)資源
root /home/user/maproject/dist;
#設(shè)置虛擬主機(jī)默認(rèn)訪問的網(wǎng)頁
index index.html index.htm;
# 主要參數(shù)
try_files $uri $uri/ /index.html;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
error_page 500 502 503 504 /50x.html;
location = /50x.html { root html;
}
server { #前端訪問后端的端口
listen 8000;
#監(jiān)聽前端的ip
server_name 192.168.2.101;
#設(shè)置django后端訪問超管界面,轉(zhuǎn)發(fā)給uWSGI處理
location ^~/admin/ { include uwsgi_params;
uwsgi_pass 127.0.0.1:8080;
}
#訪問后端的靜態(tài)資源
location /static/ { #static文件夾所在的絕對路徑
root /home/user/maproject/django_static; # 重定向,自動(dòng)找到static
}
#訪問后端的api請求,前段訪問的后端api請求都以api開頭
location /api { include uwsgi_params;
uwsgi_pass 127.0.0.1:8080;
}
}
啟動(dòng)部署的項(xiàng)目時(shí),先啟動(dòng)nginx,在啟動(dòng)uwsgi服務(wù)。
我的項(xiàng)目整體結(jié)構(gòu)如下所示:
好了,基于Django開發(fā)的應(yīng)用網(wǎng)站部署就到此結(jié)束了,從ubuntu server搭建到nginx與uwsgi的部署。鄙人也是初學(xué)者,在學(xué)習(xí)的路上一直在慢慢的積累,歡迎各位大佬的及時(shí)指正,如有紕漏,懇請及時(shí)糾正。
你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級服務(wù)器適合批量采購,新人活動(dòng)首月15元起,快前往官網(wǎng)查看詳情吧