寫在部署前
線上上部署django項目時,比較成熟的方案是:nginx + uWSGI + Django。 nginx和Django 都比較熟悉了,uWSGI是什麼呢?WSGI是一個協定,python用于web開發的協定,uWSGI則是一個程式,充當WEB伺服器或者中間件。當Nginsx+uWSGI+Django一起使用時,uWSGI就是個中間件,如果直接用django+uWSGI時,uWSGI就是個WEB伺服器。
說下WEB協定出現的順序: CGI --> FCGI --> WSGI --> uwsgi。
CGI是最早的協定,然後FCGI顧名思義就是比CGI更快,WSGI是Python專用的協定,uwsgi比FCGI和WSGI都快,是uWSGI項目的自有協定,主要特征是采用二進制來存儲資料,
之前的協定都是存儲字元串,是以在存儲空間和解析速度上,都會優于字元串協定。附官方資料位址:http://uwsgi-docs.readthedocs.io/en/latest/FAQ.html

CGI = Common Gateway Interface,通用網關接口
顧名思義,它是一種接口規範。該規範詳細定義了Web伺服器中運作的伺服器代理程式,怎樣擷取及傳回網頁生成過程中,伺服器環境上下文和HTTP協定中的參數名稱,
如大家所熟知的:REQUEST_METHOD,QUERY_STRING,CONTENT_TYPE等等。絕大部分的Web伺服器程式,是以腳本的形式代理接受并處理HTTP請求,傳回HTTP頁面或響應。
這些腳本程式,就是大家所熟知的PHP、ASP、JSP等等。
FCGI = Fast CGI
它其實是CGI在具體實作中的的一個變種。其設計思路是,通過減少CGI代理程式和Web宿主服務程式的通信開銷,進而達到提高Web服務性能的最終目的。
由此可見,FCGI在規範上跟CGI并沒有不同,
隻是具體實作方式上有所改進:
CGI的做法是,對于每個HTTP請求,Web宿主服務程式都建立新的程序以調用伺服器腳本,響應該請求;大量HTTP請求時,伺服器頻繁建立程序會影響伺服器性能。
FCGI的做法是,建立一個獨立的FCGI服務程式程序,和Web宿主服務程式程序通信,FCGI服務程序被一旦啟動後,自己配置設定資源、建立線程響應HTTP請求、并決定自身生命周期,
進而大大降低了系統為了建立程序而做出的資源開銷。FCGI還支援分布式,也就是WEB伺服器和應用程式可以再不通的機器上。
現代流行的Web伺服器程式,如PHP、ASP.Net,基本都是FCGI的實作。
SCGI = Simple CGI
它是FCGI在精簡資料協定和響應過程後的産物。其設計目的是為了适應越來越多基于AJAX或REST的HTTP請求,而做出更快更簡潔的應答。
并且SCGI約定,當伺服器傳回對一個HTTP協定請求響應後,立刻關閉該HTTP連接配接。是以不難看出,SCGI更加适合于普遍意義上SOA所提倡的“請求-忘記”這種通信模式。
WSGI = Web Server Gateway Interface
此協定是Python語言的專利,它定義了一組在Web服務宿主程式和HTTP響應代理程式之間通信的普遍适用的接口。
它的産生是因為Python程式員注意到,對于Web架構和Web宿主伺服器程式間,有嚴重的耦合性,比如說,某些架構是針對Apache的mod_python設計的。
于是,WSGI就定義了一套非常低級别的接口。常見的Python Web架構都實作了這個協定:如 CherryPy, Django, web.py, web2py, TurboGears, Tornado,
Pylons, BlueBream, Google App Engine[dubious – discuss], Trac, Flask, Pyramid,等等.
各類CGI簡介
浏覽器請求一個頁面的流程
- 浏覽器發送請求給伺服器,包含請求頭和請求體
- 伺服器解析請求頭和請求體
- 伺服器根據請求資訊來處理請求,生成傳回内容
- 伺服器生成響應頭和響應體
- 伺服器傳回響應給浏覽器,浏覽器顯示給使用者
步驟1,2,4,5在所有網站的請求中都是一樣的,隻有步驟3是不固定的。是以把固定的4個步驟抽象出來,讓開發者隻關注步驟3,可以提高開發效率。
WSGI,全稱 Web Server Gateway Interface, 是python專用的協定,其他語言沒有。用于處理WEB伺服器和應用程式APP的互動資訊。很多WEB架構
都有自帶的WSGI伺服器,不過性能并不理想,隻能用于測試用途。

# nginx 相關
(1)正向代理:浏覽器主動請求代理伺服器,代理伺服器轉發請求到對應的目标伺服器。
(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相關簡介
正式安裝
#系統環境:
CentOS 7
nginx
Django1.9
python3.6
uwsgi
# 安裝依賴包
yum install zlib-devel bzip2-devel pcre-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel python-pip -y
# 安裝uwsgi
pip install uwsgi
# 檢視版本
uwsgi --version
# 測試uwsgi是否正常,實作一個最簡單的伺服器
# vim test.py
#!/usr/bin/python env
# coding: utf-8
def application(env, start_response):
start_response('200 OK', [{'Contetn-Type', 'text/html'}])
return "hello world"
# 解釋:
# env參數是一個字典對象,儲存HTTP請求的資訊,如URL路徑,域名,請求頭,請求參數等
# start_response 參數是一個函數,用于向wsgiref提供響應頭的設定,隻能調用一次。
# 在終端運作
uwsgi --http :8080 --wsgi-file test.py
# 浏覽器輸入 http://127.0.0.1:8080 , 如果傳回hello world 則正确,不是的話,請檢查上面步驟。
# 安裝django 和 nginx
pip install Django==1.9
yum install nginx -y
# 配置uwsgi
vim /etc/uwsgi.ini
[uwsgi]
socket = 127.0.0.1:10000 // 運作端口号
chdir = /data/OPS/superops/ // django項目絕對路徑
wsgi-file = superops/wsgi.py // django的wsgi檔案
master = true // 主程序
vhost = true // 多站模式
no-stie = true // 多站模式時不設定入口子產品和檔案
workers = 2 // 子程序數
reload-mercy = 10
vacuum = true // 退出,重新開機時清理檔案
max-requests = 1000
limit-as = 512
buffer-sizi = 30000
pidfile = /var/run/uwsgi.pid // pid檔案,用于下面的腳本啟動,停止該程序
daemonize = /var/log/uwsgi.log // 日志檔案,這個日志會記錄django運作日志
# 附:uWSGI參考資料:http://www.cnblogs.com/zhouej/archive/2012/03/25/2379646.html
# 啟動uwsgi
uwsgi /etc/uwsgi.ini

# cat /etc/init.d/uwsgi
DESC="uwsgi daemon"
NAME=uwsgi
DAEMON=/usr/bin/uwsgi
CONFIGFILE=/etc/$NAME.ini
PIDFILE=/var/run/$NAME.pid
SCRIPTNAME=/etc/init.d/$NAME
set -e
[ -x "$DAEMON" ] || exit 0
do_start() {
$DAEMON $CONFIGFILE || echo -n "uwsgi running"
}
do_stop() {
$DAEMON --stop $PIDFILE || echo -n "uwsgi not running"
rm -f $PIDFILE
echo "$DAEMON STOPED."
}
do_reload() {
$DAEMON --reload $PIDFILE || echo -n "uwsgi can't reload"
}
do_status() {
ps aux|grep $DAEMON
}
case "$1" in
status)
echo -en "Status $NAME: \n"
do_status
;;
start)
echo -en "Starting $NAME: \n"
do_start
;;
stop)
echo -en "Stopping $NAME: \n"
do_stop
;;
reload|graceful)
echo -en "Reloading $NAME: \n"
do_reload
;;
*)
echo "Usage: $SCRIPTNAME {start|stop|reload}" >&2
exit 3
;;
esac
exit 0
建立uwsgi的啟動腳本
# 配置nginx
server {
listen 8888; // 外網通路端口
listen [::]:8888;
server_name _;
root /usr/share/nginx/html;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
location / {
include uwsgi_params;
uwsgi_pass 127.0.0.1:10000; // 必須和uwsgi.ini配置的端口一緻
uwsgi_param UWSGI_SCRIPT superops.wsgi; // 入口檔案, superops是項目名稱
uwsgi_param UWSGI_CHDIR /data/OPS/superops; // 項目根目錄,這個路徑是有manage.py的那一層
index index.html index.htm;
client_max_body_size 35m;
}
location /static/ {
alias /data/OPS/superops/static/; // 有時候會發現通路網站的時候加載不到資源(404)在這裡聲明下。
}
# 測試整體
/etc/init.d/uwsgi start
systemctl start nginx
在浏覽器中輸入http://127.0.0.1:8888 就可以正常通路django 項目了
# 多站配置
# uwsgi:也就是使用多個uwsgi服務的方法來實作多個站點,建立多個/etc/uwsgi01.ini并修改檔案對應的端口号
# nginx: 在配置檔案中再配置一個server,設定不同的端口,并指向uwsgi