1. 程式人生 > >uWSGI+django+nginx部署流程及原理

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.執行流程

  1. 當客戶端傳送請求時,會先請求我們的web伺服器即Nginx。
  2. Nginx做為對外的服務介面,接受到客戶端傳送的請求後對其進行解包分析。如果是靜態檔案請求就直接返回請求的靜態檔案。
  3. 如果是動態的請求,Nginx就通過配置檔案,將請求傳遞給uWSGI,uWSGI將接受到的包進行處理,並轉發給wsgi
  4. wsgi根據請求呼叫想要的處理程式。程式處理完成後將資料返回給wsgi
  5. wsgi接受後將資料打包轉發給uWSGI
  6. 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。