使用 uWSGI 和 Nginx 部署 Django 專案

迪斯馬斯克發表於2019-04-19

前言

本文只介紹部署
首先需要有一個已經可用的 Django 專案。

操作環境 Ubuntu。

uWSGI 的安裝配置

安裝

pip install uwsgi
複製程式碼

Debian 及衍生系統,如 Ubuntu,需要先安裝 python-devpython3-dev。否則不能正常安裝 uwsgi。

使用 uWSGI 在 8000 埠執行 Django 專案:

uwsgi --http 127.0.0.1:8000 --chdir /path/to/project/ --wsgi-file /path/to/wsgi.py
複製程式碼

根據 uWSGI 文件,為了正確載入模組,必須新增 chdir 選項。

而實際上,chdir 選項的作用是切換到該目錄,見《uwsgi 常用引數說明》
所以如果所有的配置都使用完整路徑的話,就不需要 chdir 了。

配置項

  • --processes 啟用的程式數,預設1
  • --threads 每個程式的執行緒數,預設1
  • --stats 設定一個地址,可以通過該地址監控執行狀態,輸出 JSON 格式的資料

關於 --stats

  • 因為是一個地址,所以可以使用 telnetcurl 檢視。或者使用官方提供的工具 uwsgitop,最後一部分會簡單介紹一下。

示例:

uwsgi --http 127.0.0.1:8000 --chdir /path/to/project/ --wsgi-file /path/to/wsgi.py --processes 4 --threads 2 --stats 127.0.0.1:8080
複製程式碼

上面的命令在 8000 埠啟動了一個 uWSGI 例項,產生4個程式,每個程式2個執行緒,並可以在 127.0.0.1:8080 檢視執行狀態。

命令列引數寫為配置檔案

顯然上面的命令有點長了。可以把配置寫在配置檔案裡,執行時只需要一個配置檔案做引數:

# conf.ini
[uwsgi]
http = 127.0.0.1:8000
chdir = /path/to/project/
wsgi-file = /path/to/wsgi.py
processes = 4
threads = 2
stats = 127.0.0.1:8080
複製程式碼

考慮到安全性,uWSGI 文件中提到,不要使用 root 許可權來執行 uWSGI,新增 uidgid 選項指定使用者和組。

使用配置檔案執行:

uwsgi conf.ini
複製程式碼

現在專案已經通過 uWSGI 執行在 8000 埠了。

注意:
http 選項的引數可以只是一個埠,比如 :8000,不過效果等於 0.0.0.0:8000
所以最好完整地寫為 127.0.0.1:8000,讓專案只執行在本地,然後反向代理出去。

停止和重啟

一般會設定多個程式,那麼可以在配置檔案中新增 master 選項:

master = true
複製程式碼

這樣一來,除了配置中設定的程式數,還將另外啟動一個 master 程式,用來管理其他程式。

這時,

  • kill master 程式的 pid,master 將自動重啟
  • kill uWSGI 的其他程式,master 將自動重新啟動一個程式

可以使用 killall 退出 uWSGI,參考 StackOverflow 上的這個問題
可以,但是沒有必要。

為了更優雅地操作 uWSGI,再新增 safe-pidfile 選項,使用 pidfile 來操作 uWSGI:

safe-pidfile = /path/to/uwsgi-master.pid
複製程式碼

safe-pidfile 會在指定的位置生成一個 pid 檔案。

這時,

  • 停止 uWSGI:uwsgi --stop /path/to/uwsgi-master.pid
  • 重啟 uWSGI:uwsgi --reload /path/to/uwsgi-master.pid

詳細內容見管理 uWSGI 伺服器 - uWSGI 文件

個人感覺 --reload 經常沒效果,很多時候 --stop 後再啟動才行。

配置 Nginx

這裡只給出一個最簡單的配置:

server{
  listen 80;
  # 如果有域名
  server_name example.com;

  location / {
    proxy_pass http://127.0.0.1:8000;
    include uwsgi_params;
  }
  ...
}
複製程式碼

uwsgi_params 檔案在 /etc/nginx/ 目錄中。如果沒有,可以從 GitHub 獲取。

使用 Unix Sockets

簡介

應該叫 Unix Domain Socket,不過 uWSGI 官方文件寫的就是 Unix Sockets。

上面 uWSGI 通過 http 配置項使 Django 專案執行在 http://127.0.0.1:8000,因此 Nginx 中需要使用 proxy_pass 對這個地址進行反向代理。這是使用 TCP Socket 的執行方式。

下面將修改為使用 Unix Sockets 的方式,好處是開銷低,效率高。

關於 TCP Socket 和 Unix Sockets 更具體一些的區別,可以看一下這篇文章:《Node.js HTTP Server 監聽 Unix Socket 套接字》

一個比較直觀的表現是:

  • 使用 http 選項執行 uWSGI 時,如果使用 uWSGI 的 pid 來檢視它所佔用的埠,是可以查到的
  • 使用 socket 選項執行,並且值設定為 sock 檔案時(見下文),使用 uWSGI 的 pid 來檢視它所佔用的埠,是查不到的,因為不走 TCP

下面看一下怎麼改。

修改 uWSGI 配置

刪除 http選項,新增 socket 選項,並設定一個 sock 檔案的路徑,執行 uWSGI 後會生成該 sock 檔案。
生成的 sock 檔案可能會缺少執行許可權,可以通過設定 chmod-socket = 666 解決。

關於 Linux 中的許可權,可以看這篇文章:《檔案許可權》

socket 選項可以設定兩種型別的值:

  • sock 檔案
  • IP 地址,即原來 http 選項的值

例如下面的配置:

[uwsgi]
socket = /path/to/sock.sock
chmod-socket = 666
...
複製程式碼

修改 Nginx 配置

uWSGI 改為使用 socket 後:
socket 設定為 IP 時,只要把原 Nginx 配置中的 proxy_pass 改成 uwsgi_pass 即可。
socket 設定為 sock 檔案時,需要把 proxy_pass 改為:

location / {
  uwsgi_pass unix:///path/to/sock.sock;
  ...
}
...
複製程式碼

注意,有三條斜線,由 unix:///path/to/sock.sock 兩部分組成

使用 upstream

uWSGI 文件中,Nginx 配置中使用了 uwsgi_passupstream

upstream django{
  server ...;
}
server{
  location /{
    uwsgi_pass django;
  }
  ...
}
複製程式碼

相當於本來直接設定 uwsgi_pass 的值,現在改成了先把值賦給變數 django,再把變數 django 設定到 uwsgi_pass 上。

使用 IP 地址時,下面兩個例子效果是一樣的:

# 使用upstream
upstream django{
  server 127.0.0.1:8000;
}
server {
  location / {
    uwsgi_pass django;
    ...
  }
}

# 不使用upstream
server {
  location / {
    uwsgi_pass 127.0.0.1:8000;
    ...
  }
}
複製程式碼

使用 sock 檔案時,下面兩個例子效果也是一樣的:

# 使用upstream
upstream django{
  server unix:///path/to/sock.sock;
}
server {
  location / {
    uwsgi_pass django;
    ...
  }
}

# 不使用upstream
server {
  location / {
    uwsgi_pass unix:///path/to/sock.sock;
    ...
  }
}
複製程式碼

upstream 常用於需要做負載均衡的場景,一個 upstream 裡可以配置多個 server。
就不再詳細介紹了。

配置 SSL 證照

如果要配置 SSL 證照,只要修改 Nginx 的配置即可:

server{
  ssl_certificate      crt;
  ssl_certificate_key  key;
  ...
}
複製程式碼

更詳細的配置可以參考 StackOverflow 上的這個問題

可以使用 Let's Encrypt 生成免費的 SSL 證照
欲知使用方法,請瘋狂點選這篇文章:《你的網站還沒用上 HTTPS 嗎》

其他

使用域名時

如果使用域名,記得把域名新增到 settings.pyALLOWED_HOSTS 中。

uWSGI 監控工具 uwsgitop

安裝:

pip install uwsgi
複製程式碼

啟動:

uwsgi :port
複製程式碼

退出:

  • Ctrl + C 主動退出
  • 當 uWSGI 程式結束時自動退出

參考連結

參考連結較多,不再一一列出。

打個廣告

我的其他文章:

《你的網站還沒用上 HTTPS 嗎》
《polipo/privoxy 實現 Linux 系統全域性/自動代理》

相關文章