本文由雲+社群發表
本文主要講述瞭如何一步步在生產環境上部署django和vue,作業系統預設為centos
說明:後文中出現的以下字串均表示具體的路徑或者名稱,含義如下:
- DJANGO_DIR—-表示django的工程根目錄
- DJANGO_NAME—-表示django的工程名稱
- VUE_HTML_DIR—-表示vue編譯好的index.html路徑
- VUE_STATIC_DIR—-表示vue編譯好的靜態資料夾static的路徑
整體框架
一個常用的web框架圖如下圖所示
框架選用.jpg
我們使用nginx + uwsgi來驅動django,因為uwsgi效能非常高
720333-20170312154455592-1425120615.png
一、安裝和配置nginx
安裝
使用yum安裝即可
yum -y install nginx
啟動
service nginx start
此時到瀏覽器輸入對應的ip地址,出現下面頁面即表示安裝成功
1324702136-57fb16aa00d21_articlex.png
修改配置檔案
nginx可以新建一個配置,放在專案目錄,暫時不修改nginx的預設配置,埠號可以換一個,然後在/etc/nginx/conf.d/內新建一個軟連結指向該配置檔案,這樣nginx在讀取配置時會將該配置一起讀進去。這樣,訪問埠號8080的請求便會指向我們自己的這個配置。
server {
listen 8080;
server_name 132.232.50.225;
root /data/;
charset utf-8;
access_log /data/access_narwhals.log;
error_log /data/error_narwhals.log;
client_max_body_size 75M;
location / {
uwsgi_pass 127.0.0.1:9090;
include /etc/nginx/uwsgi_params;
}
location ^~ /admin/ {
uwsgi_pass 127.0.0.1:9090;
include /etc/nginx/uwsgi_params;
}
}
該配置中uwsgi_pass要指向uwsgi繫結的介面。(我們先假設uwsgi配置的是9090埠)
二、安裝和配置uwsgi
安裝
使用yum或者pip均可安裝
yum install uwsgi
# 或者
pip install uwsgi
不過這裡需要注意,如果執行uwsgi出現下面錯誤
uwsgi: option `--http` is ambiguous; possibilities: `--http-socket` `--https-socket-modifier2` `--https-socket-modifier1` `--https-socket` `--http11-socket` `--http-socket-modifier2` `--http-socket-modifier1`
getopt_long() error
主要是用yum安裝的uwsgi,缺少python的plugin,可以安裝對應的外掛
yum install uwsgi-plugin-python
plugins = python (加在ini配置檔案中)
配置
uwsgi可以使用命令列啟動,也可以使用配置檔案來啟動,推薦使用配置檔案來啟動守護程式,配置檔案內容如下
[uwsgi]
socket = 127.0.0.1:9090
stats = 127.0.0.1:9293
workers = 4
# 專案根目錄
chdir = DJANGO_DIR
touch-reload = DJANGO_DIR
py-auto-reload = 1
# 在專案跟目錄和專案同名的資料夾裡面的一個檔案
module= DJANGO_NAME.wsgi
pidfile = /var/run/inner_manager.pid
daemonize = /data/uwsgi9090.log
# If you plan to receive big requests with lots of headers you can increase this value up to 64k (65535).
buffer-size=65535
這裡以socket形式執行uwsgi,繫結了本地的9090埠,也就是上文nginx配置中uwsgi_pass指定的埠。
大概解釋下幾個配置的含義:
- chdir—-應用載入前chdir到指定目錄,一般設定為django的工程根目錄
- touch-reload—-如果修改/碰了指定的檔案,那麼過載uWSGI
- module—-載入一個WSGI模組的路徑,如果django的話就指向對應的wsgi檔案模組
- buffer-size—-設定請求的最大大小 (排除request-body),這一般對映到請求頭的大小。預設情況下,它是4k。如果你接收到了一個更大的請求 (例如,帶有大cookies或者查詢字串),那麼你也許需要增加它。它也是一個安全度量,所以調整為你的應用需要,而不是最大輸出。該值如果太小會報錯
具體引數含義可以到官方文件查詢
然後使用命令啟動uwsgi程式,其中uwsgi.ini為上面內容的配置檔案
uwsgi -i uwsgi.ini
可以看下日誌檔案有沒有報錯,或者看下ps -ef|grep uwsgi
程式有沒有跑起來。一定要確保程式正常run起來才行
至此,DJANGO已經通過nginx+uwsgi可以訪問了
三、配置訪問vue
其實這裡訪問編譯好的vue靜態檔案有很多方式,本文主要講述通過nginx直接訪問和通過django路由訪問
通過django路由訪問
其實我們也可以直接通過http://ip:8080/ 來經由django的路由來訪問vue的頁面。當然要做到這樣要確保以下配置的正確
找到DJANGO_DIR根目錄下DJANGO_NAME同名資料夾下urls.py,使用通用檢視建立最簡單的模板控制器,增加一行路由
url(r`^$`, TemplateView.as_view(template_name="index.html")),
這樣訪問http://ip:8080/
時會直接返回 index.html。
上一步使用了Django的模板系統,所以需要配置一下模板使Django知道從哪裡找到index.html。在project目錄的settings.py下:
TEMPLATES = [
{
`BACKEND`: `django.template.backends.django.DjangoTemplates`,
`DIRS`: [VUE_HTML_DIR],
`APP_DIRS`: True,
`OPTIONS`: {
`context_processors`: [
`django.template.context_processors.debug`,
`django.template.context_processors.request`,
`django.contrib.auth.context_processors.auth`,
`django.contrib.messages.context_processors.messages`,
],
},
},
]
按照上述配置完成後,結合前面配置好的nginx和uwsgi,你已經可以通過http://ip:8080/ 來訪問到對應的vue編譯好的VUE_HTML_DIR目錄下的index.html了,但是這時候你可能會有其他困擾,比如找不到css樣式檔案的問,這經常是靜態配置有誤導致找不到靜態檔案的問題。
Django通過django.contrib.staticfiles來管理靜態檔案,首先確保django.contrib.staticfiles已經新增到INSTALLED_APPS。
然後可以在DJANGO的配置檔案settings.py中增加以下幾個配置:
STATIC_URL = `/static/`
STATIC_ROOT = os.path.join(BASE_DIR, "static")
# Add for vuejs
STATICFILES_DIRS = [
VUE_STATIC_DIR,
# other static folders
]
-
STATIC_URL
對外提供WEB訪問時static的URL地址 -
STATIC_ROOT
設定絕對路徑, 用來儲存收集到的靜態檔案,伺服器最終也將從該路徑中獲取檔案進行轉發。在collectstatic執行的時候會把STATICFILES_DIRS
中的靜態檔案拷貝到這個目錄中,達到從開發環境到生產環節過程中移植靜態檔案的作用。 -
STATICFILES_DIRS
用來配置一些開發環境下生成的靜態檔案的地址,即編譯好的VUE_STATIC_DIR
在url.py中新增路由
url(r`^static/(?P<path>.*)$`, static.serve,
{`document_root`: settings.STATIC_ROOT}, name=`static`),
配置好以上配置後,編譯好的靜態檔案還在VUE_STATIC_DIR
目錄下,我們最終要執行下面命令才能把STATICFILES_DIRS
中的靜態檔案拷貝到STATIC_ROOT
這個目錄中,也就是最終生產環境指定的static的存放目錄
python manage.py collectstatic
那麼為什麼不直接手動把構建好的VUE_STATIC_DIR中的檔案拷過來呢,因為Django自帶的App:admin 也有一些靜態檔案(css,js等),它會一併collect過來,畢竟nginx只認專案跟目錄的靜態檔案,它不知道django把它自己的需求檔案放到哪了
這樣你訪問django的admin網址http://ip:8080/admin 時,也不會出現找不到css的問題了
當然這種方式其實是通過django的路由來訪問靜態檔案的,一般的,生產環境不會通過django來轉發靜態檔案,而是通過其他伺服器進行轉發,比如nginx,apache等,所以這裡我們需要再配置下nginx的配置檔案,在8080的server中增加如下路徑的配置
location /static/ {
expires 30d;
autoindex on;
add_header Cache-Control private;
alias VUE_STATIC_DIR;
access_log off;
}
這樣訪問靜態檔案便會直接通過nginx來訪問了,不用擔心靜態檔案訪問導致Django的處理速度變慢了。
通過nginx直接訪問
如果你想直接通過nginx訪問對應的前端vue檔案,可以重新配置一個server來訪問對應的html檔案,比如上面已經使用了8080埠,我們可以用預設的80埠來配置個server,其中root可以指向存放index.html檔案的路徑,/static/
路徑下的root路徑可以指向html對應的存放css和js的static資料夾,如果static就在index.html路徑下,不指認也可以。直接修改/etc/nginx.conf即可,裡面已經有配置好的80埠的server
配置如下所示
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
root VUE_HTML_DIR;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
location / {
}
location /static/ {
root VUE_STATIC_DIR;
access_log off;
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
這樣我們可以通過http://ip:80/ 來訪問vue編譯好的頁面,使用http://ip:8080/ 訪問django配置的cgi請求
四、通過supervisor管理程式
上面我們已經用到了uwsgi,後面可能還會用到redis、celery,都需要開啟守護程式,其中celery自身還不支援守護程式。那麼如何管理這麼多程式呢,這時候可以考慮下supervisor
安裝
使用pip安裝即可
pip install supervisor
配置
我們可以配置redis,celery,uwsgi進去,比如向下面一樣
[program:redis]
;指定執行目錄
directory=%(here)s/
;執行命令(redis-server redis配置檔案路徑)
command=redis-server /etc/redis.conf
;啟動設定
numprocs=1 ;程式數
autostart=true ;當supervisor啟動時,程式將會自動啟動
autorestart=true ;自動重啟
;停止訊號
stopsignal=INT
[program:celery.worker.default]
;指定執行目錄
directory=%(here)s/
;執行目錄下執行命令
command=celery -A DjangoProject worker --loglevel info --logfile log/celery_worker.log -Q default -n %%h-%(program_name)s-%(process_num)02d
process_name=%(process_num)02d
;啟動設定
numprocs=2 ;程式數
autostart=true ;當supervisor啟動時,程式將會自動啟動
autorestart=true ;自動重啟
;停止訊號,預設TERM
;中斷:INT (類似於Ctrl+C)(kill -INT pid),退出後會將寫檔案或日誌(推薦)
;終止:TERM (kill -TERM pid)
;掛起:HUP (kill -HUP pid),注意與Ctrl+Z/kill -stop pid不同
;從容停止:QUIT (kill -QUIT pid)
stopsignal=INT
[program:uwsgi]
;指定執行目錄
directory=%(here)s/
;執行目錄下執行命令
command=uwsgi -i conf/uwsgi/uwsgi9090.ini
;啟動設定
numprocs=1 ;程式數
autostart=true ;當supervisor啟動時,程式將會自動啟動
autorestart=true ;自動重啟
;停止訊號,預設TERM
;中斷:INT (類似於Ctrl+C)(kill -INT pid),退出後會將寫檔案或日誌(推薦)
;終止:TERM (kill -TERM pid)
;掛起:HUP (kill -HUP pid),注意與Ctrl+Z/kill -stop pid不同
;從容停止:QUIT (kill -QUIT pid)
stopsignal=INT
使用
啟動supervisor輸入如下命令,使用具體的配置檔案執行:
supervisord -c supervisord.conf
關閉supervisord需要通過supervisor的控制器:
supervisorctl -c supervisord.conf shutdown
重啟supervisord也是通過supervisor的控制器:
supervisorctl -c supervisord.conf reload
一些特殊的變數
%(here)s 配置檔案所在路徑
(program_name)s program的名字
%(process_num)02d 多程式時的程式號
注意:command中如果含有%,需要進行轉義%%
多程式時如果不指定process_name會遇到如下錯誤
Error: Format string `celery -A INTProject worker --loglevel info --logfile log/celery_worker.log -Q diff_task,caller_task -n %h` for `program:celery.worker.mac.command` is badly formatted: incomplete format in section `program:celery.worker.mac` (file: `supervisord.conf`)
中間可能遇到的坑
*8107 recv() failed (104: Connection reset by peer) while reading response header from upstream, client 錯誤
使用django+uwsgi+nginx,發現如下報錯
2018/10/08 14:34:33 [error] 12283#0: *8107 recv() failed (104: Connection reset by peer) while reading response header from upstream, client: 9.19.161.66, server: 132.232.50.225, request: "GET /auth/info?token=ZXlKaGJHY2lPaUprWldaaGRXeDBJaXdpZEhsd0lqb2lTbGRRSW4wOjFnOVA3aDp0bVZYcmg3XzJPR3RXSHJrbXFLRVdCZEpUdXc_ZXlKMWMyVnlibUZ0WlNJNkltVjBhR0Z1Wm1GdUlpd2lhV0YwSWpveE5UTTRPVGd3TkRjekxqZzVNekk1TVgwOjFnOVA3aDpMVXRHZkFiQkhrRTNaenFnS3NuS1RvOHBOMGM_3bdf34e6de16096f9982015a2382d3c8 HTTP/1.1", upstream: "uwsgi://127.0.0.1:9090", host: "int.oa.com", referrer: "http://int.oa.com/"
I finally found a reference to fastcgi and a 502 bad gateway error (https://support.plesk.com/hc/…). That lead me to look for a buffer size limit in the uwsgi configuration which exists as buffer-size. The default value is 4096. From the documentation, it says: If you plan to receive big requests with lots of headers you can increase this value up to 64k (65535).
意思是uwsgi中有一項配置是buffer-size,表明收到的最大請求size,預設是4096,可以將其改成65535
buffer-size=65535
此文已由作者授權騰訊雲+社群釋出