谷明科技,專注於大數據和人工智能領域的創新者
本文主要是針對 Django 項目的生產部署操作
網絡客戶端 <-> 網站服務器(nginx) <-> the socket <-> uwsgi <-> Django
這裏,uwsgi 是與 Django 交互的一種 python 標準,而 nginx 和 uwsgi 之間的交互方式是以 socket 包的方式進行的
前提:
- 已經安裝了 python 3.7 版本
- 已經安裝了 django 版本可以在 django 2.0 - 3.0
- 已經有一個可以正常運行的 django 項目,我們這裏假設我們用的 django 教程裏的項目 mysite.
- 已經安裝了 Nginx1.6.1, 沒有安裝的可以翻看之前的教程。
說明下,我們下面會頻繁提到幾個名詞,提前備註下
- 系統環境: 以 root 用戶進入的系統環境
- 虛擬環境:是用 virtualenv 搭建並已經激活的環境
- 項目目錄:虛擬環境中有 manage.py 的目錄,是絕對路徑
- IP: 你的服務器的訪問 ip,如果是雲服務器的話,就是外網 ip
1. 在虛擬環境中安裝 uwsgi
注意,這裏強烈推薦用 pip 安裝,否則後續會遇到一些問題。
pip install uwsgi
which uwsgi
看下路徑是不是指向虛擬環境的
2. 在虛擬環境中測試並配置 uwsgi
測試:
在項目目錄下,新建一個 test.py 文件。
# test.py
def application(env, start_response):
start_response('200 OK', [('Content-Type','text/html')])
return [b"Hello World"] # python3
#return ["Hello World"] # python2
uwsgi --http :8000 --wsgi-file test.py
這裏的 8000 端口應該是可用而且空閒的,所謂可用是指 阿里雲 或者 騰訊雲 的該端口安全組是已經配置了的,具體不懂的可以百度,所謂空閒的,是指該端口沒有被佔用,具體查詢方法爲如下:
netstat -nltp | grep 8000
打開 http://IP:8000 是否能看到 “hello world” 的輸出,如果是,說明如下通信鏈路是通的
客戶端 <-> uWSGI <-> Python
如果不能看到,再看下上面的內容,是不是遺忘了一些步驟或者配置有問題
3. 虛擬環境中測試 django 項目的 uwsgi 通信
首先,看下你的 django 項目是不是可以跑通
python manage.py runserver 0.0.0.0:8000
然後打開 http://IP:8000/admin 是否可以看到你的 django 登錄界面,如果可以的話,說明項目沒問題。
然後輸入
uwsgi --http :8000 --module mysite.wsgi
這裏的 mysite 是 django 項目的名字,如果你的項目名字是其他的,這裏對應修改一下,我們本篇都會以 mysite 作爲默認的項目名
然後打開 http://IP:8000/admin 是否可以看到你的 django 登錄界面,如果可以的話,說明如下的網絡通信沒有問題
客戶端 <-> uWSGI <-> Django
4. 系統環境中測試 nginx
這裏我們默認 nginx 已經安裝完成而且安裝方式是 yum 安裝
打開 http://IP:80 是否可以看到 nginx 的歡迎界面,如果可以說明以下通信鏈路是沒問題
客戶端 <-> nginx 服務器
如果有問題,可以看下 /var/log/nginx/error.log 日誌,如果是端口被佔用,直接停掉對應的進程然後重新啓動 nginx
nginx -s reload
打開 nginx 路徑,如果不知道可以打 nginx -t 或者 whereis nginx
我這邊的 nginx 的路徑是 /etc/nginx,裏面的文件架構是
nginx
-- conf.d
fastcgi_params
nginx.conf
uwsgi_params
...
這裏的 conf.d 就是 nginx 配置文件的目錄,下一步我們會用到。
同時,因爲我們需要在項目中使用到 uwsgi_params 文件,所以把這個文件複製到項目目錄中,並且文件的擁有者是開發者而不是 root。
5. 虛擬環境中配置 nginx
在項目目錄下,新建一個 mysite_nginx.conf 文件,並填入以下信息
# mysite_nginx.conf
# the upstream component nginx needs to connect to
upstream django {
# server unix:///path/to/your/mysite/mysite.sock; # for a file socket
server 127.0.0.1:8001; # socket 的網絡端口
}
# configuration of the server
server {
# the port your site will be served on
listen 8000;
# the domain name it will serve for
server_name IP; # 服務器IP
charset utf-8;
# max upload size
client_max_body_size 75M; # 可以自己調整
# Django media
location /media {
alias 項目目錄/media; # 媒體文件路徑
}
location /static {
alias 項目目錄/static; # 靜態文件路徑
}
# Finally, send all non-media requests to the Django server.
location / {
uwsgi_pass django;
include 項目目錄/uwsgi_params; # 項目的 uwsgi_params 文件
}
}
然後做一個指向該配置文件的軟鏈接
ln -s 項目目錄/mysite_nginx.conf /etc/nginx/conf.d/
6. 虛擬環境中部署靜態文件
首先,修改一下 django 項目的配置文件(項目目錄/setting.py )
將其中的 debug = True 改爲 debug = False
然後在文件末尾添加如下一行
STATIC_ROOT = os.path.join(BASE_DIR, "static/")
STATIC_URL = '/static/'
同時需要對 mysite 文件夾下面的 urls.py 文件做一個簡單的修改
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
# ... the rest of your URLconf goes here ...
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
同時,需要對訪問的ip和域名地址做一個設置,否則會造成 connection refused 這樣的問題,這裏我的例子是這樣:
ALLOWED_HOSTS = ['127.0.0.1', '外網IP','www.guming-tech.com']
然後在你的項目目錄中添加2個子目錄
/media/
/static/
分別存放媒體文件和靜態文件,然後輸入以下命令
python manage.py collectstatic
然後放一張圖片在 media 目錄下,什麼圖片都可以,我們這裏假設圖片爲 show.png
接下來,切入到系統環境中,然後重啓 nginx
nginx -s reload
然後訪問 http://IP:8000/media/show.png, 如果圖片能夠顯示,則說明 nginx 的項目配置是沒有問題的
7. 虛擬環境中測試 nginx,uwgsi 和 python 之間的 socket 端口通信
輸入以下命令
uwsgi --socket :8001 --wsgi-file test.py
這裏的 8001 端口是基於第5步中對 nginx 項目配置文件的配置,忘記的可以重新翻看下
然後打開 http://IP:8000 是否可以看到 “hello world”,如果可以的話,說明如下的通信鏈路是沒有問題的
客戶端 <-> nginx 服務器 <-> the socket <-> uWSGI <-> Python
8. 虛擬環境中測試 nginx,uwgsi 和 python 之間的 unix socket 通信
上一步我們使用了TCP的 socket 的端口通信,這個是比較簡單的,但是在實際的網站中,更好的解決方案是 unix socket 方法,具體設置方法如下:
編輯 mysite_nginx.conf 對文件的頭部部分做一些修改
server unix://項目目錄/mysite.sock; # socket 文件,自動生成
# server 127.0.0.1:8001; # for a web port socket (we'll use this first)
切換到系統環境中,重啓 nginx
然後輸入
uwsgi --socket mysite.sock --wsgi-file test.py
然後打開 http://IP:8000 應該可以看到 “hello world”,如果有 permission error 的話,試下如下2種方法
uwsgi --socket mysite.sock --wsgi-file test.py --chmod-socket=666
uwsgi --socket mysite.sock --wsgi-file test.py --chmod-socket=664
我這邊是對第一種方法有效
9. 虛擬環境中測試 nginx,uwgsi 和 django 項目之間的完整通信
這次試下如下的命令
uwsgi --socket mysite.sock --module mysite.wsgi --chmod-socket=666
然後打開 http://IP:8000/admin 是不是可以看到 django 的登錄界面了
10. 虛擬環境中使用 ini 配置文件
在項目目錄下新建一個 mysite_uwsgi.ini 文件,並放入以下內容
# mysite_uwsgi.ini file
[uwsgi]
# Django-related settings
# the base directory (full path)
chdir = 項目目錄
# Django's wsgi file
module = mysite.wsgi
# the virtualenv (full path),這個是你使用 virtualenv 建立的項目的絕對路徑,但不是項目路徑,一般是項目目錄的上層路徑
home = 項目目錄的上層路徑
# process-related settings
# master
master = true
# maximum number of worker processes
processes = 10
# the socket (use the full path to be safe
socket = 項目路徑/mysite.sock
# ... with appropriate permissions - may be needed
chmod-socket = 666
# clear environment on exit
vacuum = false
然後輸入
uwsgi --ini mysite_uwsgi.ini
然後打開 http://IP:8000/admin 應該還是可以通信
11. 系統環境下安裝 uwsgi
依然是用 pip 安裝 uwsgi
pip install uwsgi
然後在系統環境中進入到項目目錄,輸入
uwsgi --ini mysite_uwsgi.ini
然後打開 http://IP:8000/admin 應該還是可以通信
12. Emperor 模式下的配置
uwsgi 可以在 “Emperor” 皇帝模式下工作,即可以監視所有的 uwsgi 配置文件
mkdir /etc/uwsgi
mkdir /etc/uwsgi/vassals
ln -s 項目目錄/mysite_uwsgi.ini /etc/uwsgi/vassals/
uwsgi --emperor /etc/uwsgi/vassals --uid user --gid user-group
具體的 user 和 user-group 這裏你可以自己選擇,比方說對系統用戶 django
groups django
輸出 django 的用戶組,填進去試試
13. 設置 uwsgi 系統自啓動
這裏我們選擇推薦的 /etc/rc.local 進行編輯
然後加入如下的命令
uwsgi安裝路徑/uwsgi --emperor /etc/uwsgi/vassals --uid 用戶 --gid 用戶組 --daemonize /var/log/uwsgi-emperor.log
這裏的 uwsgi安裝路徑可以通過以下的命令得到
which uwsgi
然後
source /etc/rc.local
需要提到的一點 /etc/rc.local 在centos7的版本里是隻讀的,所以我們需要給它加入一個可執行的權限,同時 /etc/rc.local 的服務名爲 rc-local,所以我們這裏將其設定爲自啓動
chmod +x /etc/rc.d/rc.local
systemctl enable rc-local
可以嘗試重啓下系統,看看服務是否自動打開
systemctl status rc-local
直接打開 http://IP:8000/admin 應該可以看到網站正常運行
部署完成
14. 項目的修改和重新加載
如果在項目中新增加了一個應用app,需要對項目進行重啓,這時候我們需要對 uwsgi 的配置文件 mysite_uwsgi.ini 做一個修改。即添加一行
touch-reload = 項目路徑/reload.ini
然後在項目目錄中,輸入以下命令
touch reload.ini
這時候不只要重新啓動 nginx 還有 uwsgi(已經在rc-local中)
nginx -s reload
killall uwsgi
source /etc/rc.local