uWSGI+django+nginx部署流程及原理
在進行部署的時候不知道走了多少坑。走通過後才發現原來也就是那麼回事,說難也不難,說簡單也確實有很多坑。
部署環境
系統:Centos7
Python: python3.6.5
Django:Django2.1
web伺服器:Nginx
應用程式伺服器:uWSGI
一、原理講解
在專案開發階段用runserver執行起來的伺服器只是一個簡單的伺服器,它在處理高併發的時候回發生嚴重的丟包現象,最總要的是在Debug改為False後這個伺服器無法返回靜態檔案。所以必須改為使用web服務端進行靜態檔案的返回。Nginx又是一個高效能的反向代理伺服器。下面講解Nginx,uWSGI, WSGI等的關係。
1.WSGI
WSGI的全稱是Web Server Gateway Interface(Web伺服器閘道器介面),它不是伺服器,python模組,框架或者API。它只是一個描述Web伺服器如何與web應用程式的通訊規範
2.uWSGI
uWSGI是一個全功能的HTTP伺服器,它實現了WSGI協議、uwsgi協議、http協議等。它要做的就是把HTTP協議轉化為語言支援的網路協議。比如吧HTTP協議轉化為WSGI協議,讓python程式可以直接使用。
uwsgi與WSGI一樣是一個uWSGI伺服器的獨佔通訊協議,用於定義傳輸資訊的型別。每一個uwsgi packet前4byte為傳輸資訊型別的描述,與WSGI協議是兩種東西。
3.Nginx
Nginx是一個高效能代理伺服器,其中的HTTP伺服器功能和uWSGI功能很類似,但是Nginx還可以用作更多用途,比如最常用的反s向代理功能。
4.wsgi.py
Django專案帶的wsgi介面檔案。
5.執行流程
- 當客戶端傳送請求時,會先請求我們的web伺服器即Nginx。
- Nginx做為對外的服務介面,接受到客戶端傳送的請求後對其進行解包分析。如果是靜態檔案請求就直接返回請求的靜態檔案。
- 如果是動態的請求,Nginx就通過配置檔案,將請求傳遞給uWSGI,uWSGI將接受到的包進行處理,並轉發給wsgi
- wsgi根據請求呼叫想要的處理程式。程式處理完成後將資料返回給wsgi
- wsgi接受後將資料打包轉發給uWSGI
- uWSGI接收後轉發給nginx,nginx最終將返回值返回給客戶端
圖解如下:
二、安裝與配置
1.部署前的準備:
首先確保你的Django專案已經完成。並將其settings的DEBUG改為True,ALLOWED_HOSTS也要加入允許訪問的地址。確保已經成功安裝Nginx伺服器。Ubuntu下sudo apt-get install nginx。Centos下sudo yum install nginx。接著部署Django執行環境,我建議是執行到虛擬環境下。至於虛擬環境的安裝配置請查考virtualenv或者virtualenvwrapper。
pip install uwsgi。驗證uWSGI,新建test.py檔案
def application(env, start_response):
start_response('200 OK', [('Content-Type','text/html')])
return [b"Hello Django"]
執行:
uwsgi --http :8000 --wsgi-file test.py
瀏覽器訪問,網頁能顯示 Hello Django 說明uWSGI執行正常。
如果端口占用,檢視端口占用的程序號(lsof是一個列出當前系統開啟檔案的工具,Ubuntu自帶這個工具,Centos需要安裝yum install lsof)如果不想裝可以使用netstat -lnp | grep 8000檢視
lsof -i :8000
找PID,殺死程序
sudo kill -9 pid
2.配置uwsgi
我都放在專案的根目錄下了,在專案的根目錄下建立uwsgi.ini檔案,寫入配置
[uwsgi]
# 通過uwsgi訪問django需要配置http
# 通過Nginx請求uwsgi訪問Django需要配置成socket,這裡設定uwsgi埠號為9000
socket = :9000
# web專案根目錄
chdir = /home/hph/py/dailyfresh
# module指定專案的wsgi檔案,專案名.wsgi
module = dailyfresh.wsgi
# 允許存在主程序
master = true
# 開啟程序數量
processes = 2
# 開啟的執行緒數量
threads = 2
# 伺服器退出後自動清理環境
vacuum = true
# uWSGI日誌
daemonize = /home/hph/py/dailyfresh/uwsgi.log
啟動uwsgi
uwsgi --ini uwsgi.ini
3.配置Nginx
為了不修改預設的配置檔案我在/etc/nginx/conf.d/下新建了一個df.conf的配置檔案,寫入如下內容
server {
listen 8088;
#listen [::]:8088;
#server_name 127.0.0.1
#charset utf-8;
# 接受請求日誌
access_log /etc/nginx/conf.d/log/access.log;
# 錯誤日誌
error_log /etc/nginx/conf.d/log/error.log;
location / {
include /etc/nginx/uwsgi_params;
# 指定uwsgi執行的埠
uwsgi_pass 127.0.0.1:9000;
}
location /static/ {
alias /home/hph/py/dailyfresh/collect_static/;
}
}
其中listen是Nginx監聽的埠。uwsgi_pass是Nginx反向代理到uwsgi的埠,這個埠一定要對應,否則重啟Nginx會報錯。
然後重啟Nginx服務
systemctl restart nginx // Centos重啟
service nginx restart // Ubuntu重啟
在Nginx上可以配置負載均衡, 常用的負載均和策略有輪詢,加權輪詢,ip hash,
三、結束
到這裡就算部署完成了,可以在瀏覽器上訪問Nginx監聽的埠。如果靜態檔案沒有載入 可能是由於許可權不夠。Nginx預設的使用者是nginx,可以用chown命令將靜態檔案的訪問許可權給nginx,或者可以直接將Nginx的使用者改為root,在/etc/nginx/nginx.conf的第一行有一個user 將後面的nginx改為root就行了。我還看過一種是靜態檔案無法載入返回的狀態碼500,可以檢查settings.py裡的DEBUG是否為False。