記錄一下在騰訊云上部署項(xiàng)目nginx + uwsgi + python-flask/django
軟件版本
- python 3.6
- flask lastest
- django 1.11.8
- uwsgi 2.0.18
- nginx lastest
- anaconda 3.5.2.0
登錄云之后先更新軟件
$ sudo apt update
$ sudo apt upgrade
配置conda環(huán)境
# 安裝conda
$ curl -O https://repo.anaconda.com/archive/Anaconda3-5.2.0-Linux-x86_64.sh
# 運(yùn)行安裝程序
$ bash Anaconda3-5.2.0-Linux-x86_64.sh # 一路yes完事
# 使用sudo conda會(huì)安裝在/root目錄下
# 不使用sudo conda就會(huì)安裝在/home目錄下
# 更新環(huán)境變量
$ source ~/.bashrc
# source .zshrc
# 新建conda環(huán)境
$ conda create --name django1.11.8 python=3.6
# 激活虛擬環(huán)境
$ source activate django1.11.8
安裝軟件
1. 配置nginx
$ sudo apt install nginx
- 存放在/etc/nginx下, 配置文件放在/etc/nginx/sites-available(sites-enabled)/default中
- 日志放在了/var/log/nginx中
- 程序文件在/usr/sbin/nginx
- 在/etc/init.d/下創(chuàng)建了啟動(dòng)腳本nginx
- nginx默認(rèn)端口號為80
# 開啟nginx服務(wù)
$ sudo /etc/init.d/nginx start
# 停止nginx服務(wù)
$ sudo /etc/init.d/nginx stop
# 重啟nginx服務(wù)
# 每次修改配置文件都需要重啟nginx
$ sudo /etc/init.d/nginx restart
2. 配置uwsgi
- 安裝
# 安裝
# 在conda環(huán)境使用pip安裝uwsgi會(huì)出現(xiàn)莫名的ModuleImportError
$ conda install uwsgi
# 安裝完畢, 測試安裝是否成功
$ uwsgi --version
# uwsgi: error while loading shared libraries: libicui18n.so.58: cannot open shared object file: No such file or directory
在安裝uwsgi過程中發(fā)生了一些錯(cuò)誤, 最后發(fā)現(xiàn)是缺少一些so文件
以下解決方法參考于 (https://blog.csdn.net/qq_26105397/article/details/79928222)
# 首先查看uwsgi的安裝位置
$ which uwsgi
# /usr/local/bin/uwsgi
# 隨后使用ldd查看可執(zhí)行模塊的dependency
$ ldd /home/ubuntu/anaconda3/bin/uwsgi
linux-vdso.so.1 (0x00007ffd043b4000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f03c3470000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f03c30d2000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f03c2ece000)
libz.so.1 => /home/ubuntu/anaconda3/bin/../lib/libz.so.1 (0x00007f03c2cb7000)
libpcre.so.1 => /home/ubuntu/anaconda3/bin/../lib/libpcre.so.1 (0x00007f03c2a72000)
libyaml-0.so.2 => /home/ubuntu/anaconda3/bin/../lib/libyaml-0.so.2 (0x00007f03c2854000)
libjansson.so.4 => /home/ubuntu/anaconda3/bin/../lib/libjansson.so.4 (0x00007f03c3da3000)
libssl.so.1.1 => /usr/lib/x86_64-linux-gnu/libssl.so.1.1 (0x00007f03c25c7000)
libcrypto.so.1.1 => /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1 (0x00007f03c20fc000)
libxml2.so.2 => /home/ubuntu/anaconda3/bin/../lib/libxml2.so.2 (0x00007f03c1d95000)
liblzma.so.5 => /home/ubuntu/anaconda3/bin/../lib/liblzma.so.5 (0x00007f03c1b6f000)
libiconv.so.2 => /home/ubuntu/anaconda3/bin/../lib/libiconv.so.2 (0x00007f03c3cbd000)
libicui18n.so.58 => not found
libicuuc.so.58 => not found
libicudata.so.58 => not found
libcrypt.so.1 => /lib/x86_64-linux-gnu/libcrypt.so.1 (0x00007f03c1937000)
libutil.so.1 => /lib/x86_64-linux-gnu/libutil.so.1 (0x00007f03c1734000)
librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f03c152c000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f03c113b000)
/lib64/ld-linux-x86-64.so.2 (0x00007f03c3b95000)
libstdc++.so.6 => /home/ubuntu/anaconda3/bin/../lib/././libstdc++.so.6 (0x00007f03bef53000)
libgcc_s.so.1 => /home/ubuntu/anaconda3/bin/../lib/././libgcc_s.so.1 (0x00007f03bed41000)
缺少libicui18n.so.58, libicuuc.so.58, libicudata.so.58這三個(gè)so庫, 將anaconda下的so庫鏈接到相應(yīng)的系統(tǒng)/lib目錄下(32位系統(tǒng)/lib, 64位系統(tǒng)則是相應(yīng)的/lib64)
$ sudo ldd -s /home/ubuntu/anaconda3/lib/libicui18n.so.58 /lib/libicui18n.so.58
$ sudo ldd -s /home/ubuntu/anaconda3/lib/libicuuc.so.58 /lib/libicuuc.so.58
$ sudo ldd -s /home/ubuntu/anaconda3/lib/libicudata.so.58 /lib/libicudata.so.58
# 測試
$ uwsgi --version
# 2.0.18
3. flask項(xiàng)目測試
- 先寫一個(gè)簡單的flask的hello_world程序
## tmp.py
from flask import Flask
app = Flask(__name__)
app.route('/')
def hello_world():
return "<h1>Hello World</h1>"
if __name__ == "__main__":
app.run(host="0.0.0.0", debug=True)
- 首先不使用nginx, 單獨(dú)使用uwsgi啟動(dòng)flask
# 無需配置ini, 直接使用shell 參數(shù)啟動(dòng)uwsgi服務(wù)
$ uwsgi --socket 0.0.0.0:5000 --protocol http -w tmp:app
可以看到使用外部瀏覽器訪問也可以成功顯示hello world, 并且再flask中會(huì)自動(dòng)識(shí)別html標(biāo)簽
- 接下來配置nginx教翩,首先修改nginx的配置文件
# 修改nginx的配置文件 /etc/nginx/sites-available (sites-enabled)/default
# 再server節(jié)點(diǎn)下添加新的location項(xiàng), 指向wsgi的IP和端口
server {
...
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
# try_files $uri $uri/ =404;
uwsgi_pass 0.0.0.0:5000;
include /etc/nginx/uwsgi_params;
}
}
重啟nginx服務(wù)
# 更改配置重啟
$ sudo /etc/init.d/nginx restart
[ ok ] Restarting nginx (via systemctl): nginx.service.
使用配置文件ini代替?zhèn)鲄?/p>
# file: mysitetest/uwsgi.ini
[uwsgi]
# 使用uwsgi接收請求
socket = 0.0.0.0:5000
# web應(yīng)用的入口模塊名稱
module = run:app
# 程序內(nèi)啟用的application變量名
callable = app
vacuum = true
# 項(xiàng)目啟動(dòng)文件的目錄
# django中對應(yīng)wsgi.py的路徑
# flask中是app文件對應(yīng)的路徑
wsgi-file = /home/ubuntu/run.py
# 是否開啟主進(jìn)程監(jiān)控子進(jìn)程
master = true
# 項(xiàng)目當(dāng)前的工作目錄
chdir = /home/ubuntu
# log文件的位置
logto = tmp.log
# uwsgi對應(yīng)啟動(dòng)時(shí)的進(jìn)程pid號, 結(jié)束服務(wù)時(shí)需要使用
pidfile = uwsgi.pid
# 設(shè)置內(nèi)存使用上限, 參照自己服務(wù)器內(nèi)存使用情況
buffer-size = 32768
# uwsgi開啟的進(jìn)程數(shù), 同樣參照自己服務(wù)器情況
# 如果開啟master, 會(huì)開啟三個(gè)進(jìn)程, 其中一個(gè)進(jìn)程只負(fù)責(zé)調(diào)度子進(jìn)程
processes = 2
# 每個(gè)進(jìn)程的線程數(shù)
threads = 2
開啟服務(wù)
$ uwsgi --ini uwsgi.ini
[uWSGI] getting INI configuration from uwsgi.ini
這里nginx默認(rèn)監(jiān)聽端口是80, 接到請求后會(huì)重定向到5000端口
4. django項(xiàng)目測試
- 創(chuàng)建新的django項(xiàng)目
$ django-admin startproject mysitetest
# django項(xiàng)目結(jié)構(gòu)
$ cd mysitetest
$ tree .
- 新建uwsgi配置文件uwsgi.ini
$ nano uwsgi.ini
[uwsgi]
socket = 0.0.0.0:8000
processes = 3 # 進(jìn)程數(shù), 自定
threads = 2 # 線程數(shù), 自定
pidfile = uwsgi.pid
daemonize = uwsgi.log
chdir = /home/ubuntu/mysite_test/mysitetest # 當(dāng)前工作目錄
wsgi-file = mysitetest/wsgi.py # django的wsgi.py的相對路徑
master = true # 開啟父進(jìn)程
# 查看目錄結(jié)構(gòu)
$ tree .
- 配置nginx
$ sudo nano /etc/nginx/sites-enabled/default
# 添加下面兩行
server {
...
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
# try_files $uri $uri/ =404;
uwsgi_pass 0.0.0.0:8000;
include /etc/nginx/uwsgi_params;
}
}
- 開啟服務(wù)
$ uwsgi --ini uwsgi.ini
[uWSGI] getting INI configuration from uwsgi.ini
# 查看當(dāng)前后臺(tái)運(yùn)行的uwsgi進(jìn)程
$ ps aux | grep "uwsgi"
我們可以看到有四個(gè)進(jìn)程在后臺(tái)運(yùn)行, 因?yàn)槲覀冊谂渲梦募虚_啟了父進(jìn)程
master=true
, 父進(jìn)程負(fù)責(zé)調(diào)度子進(jìn)程
# 查看目錄結(jié)構(gòu)
$ tree .
首先項(xiàng)目目錄中新增了pycache
文件夾, 這是py文件運(yùn)行后, python解釋器保存的字節(jié)碼, 而另外的uwsgi.pid
和uwsgi.log
就是我們在配置文件中設(shè)置的pidfile
和daemonize
, 分別保存uwsgi后臺(tái)運(yùn)行的進(jìn)程pid號以及uwsgi運(yùn)行的log日志
$ cat uwsgi.pid
11435
這個(gè)pid文件中保存著父進(jìn)程的pid號, 當(dāng)我們想要停止uwsgi服務(wù)時(shí), 只需要使用uwsgi --stop uwsgi.pid
這樣系統(tǒng)就會(huì)殺死父進(jìn)程, 由于父進(jìn)程負(fù)責(zé)調(diào)度另外的進(jìn)程, 其他進(jìn)程也會(huì)結(jié)束
$ cat uwsgi.log
*** Starting uWSGI 2.0.18 (64bit) on [Thu Jan 7 00:07:36 2021] ***
compiled with version: 7.3.0 on 09 February 2019 23:40:56
os: Linux-4.15.0-118-generic #119-Ubuntu SMP Tue Sep 8 12:30:01 UTC 2020
nodename: VM-0-17-ubuntu
machine: x86_64
clock source: unix
pcre jit disabled
detected number of CPU cores: 1
current working directory: /home/ubuntu/mysite_test/mysitetest
writing pidfile to uwsgi.pid
detected binary path: /home/ubuntu/anaconda3/envs/django1.11.8/bin/uwsgi
chdir() to ~/mysite_test/mysitetest
chdir(): No such file or directory [core/uwsgi.c line 2623]
*** Starting uWSGI 2.0.18 (64bit) on [Thu Jan 7 00:11:26 2021] ***
compiled with version: 7.3.0 on 09 February 2019 23:40:56
os: Linux-4.15.0-118-generic #119-Ubuntu SMP Tue Sep 8 12:30:01 UTC 2020
nodename: VM-0-17-ubuntu
machine: x86_64
clock source: unix
pcre jit disabled
detected number of CPU cores: 1
current working directory: /home/ubuntu/mysite_test/mysitetest
writing pidfile to uwsgi.pid
detected binary path: /home/ubuntu/anaconda3/envs/django1.11.8/bin/uwsgi
chdir() to /home/ubuntu/mysite_test/mysitetest
your processes number limit is 7075
your memory page size is 4096 bytes
detected max file descriptor number: 1024
lock engine: pthread robust mutexes
thunder lock: disabled (you can enable it with --thunder-lock)
uwsgi socket 0 bound to TCP address 0.0.0.0:8000 fd 3
Python version: 3.6.7 | packaged by conda-forge | (default, Nov 21 2018, 03:09:43) [GCC 7.3.0]
Python main interpreter initialized at 0x555a259b36d0
python threads support enabled
your server socket listen backlog is limited to 100 connections
your mercy for graceful operations on workers is 60 seconds
mapped 166752 bytes (162 KB) for 2 cores
*** Operational MODE: threaded ***
WSGI app 0 (mountpoint='') ready in 1 seconds on interpreter 0x555a259b36d0 pid: 10878 (default app)
*** uWSGI is running in multiple interpreter mode ***
spawned uWSGI master process (pid: 10878)
spawned uWSGI worker 1 (pid: 10891, cores: 2)
[pid: 10891|app: 0|req: 1/1] 111.56.143.81 () {42 vars in 753 bytes} [Wed Jan 6 16:11:32 2021] GET / => generated 1716 bytes in 8 msecs (HTTP/1.1 200) 3 headers in 95 bytes (1 switches on core 0)
SIGINT/SIGQUIT received...killing workers...
worker 1 buried after 1 seconds
goodbye to uWSGI.
*** Starting uWSGI 2.0.18 (64bit) on [Thu Jan 7 00:14:21 2021] ***
compiled with version: 7.3.0 on 09 February 2019 23:40:56
os: Linux-4.15.0-118-generic #119-Ubuntu SMP Tue Sep 8 12:30:01 UTC 2020
nodename: VM-0-17-ubuntu
machine: x86_64
clock source: unix
pcre jit disabled
detected number of CPU cores: 1
current working directory: /home/ubuntu/mysite_test/mysitetest
writing pidfile to uwsgi.pid
detected binary path: /home/ubuntu/anaconda3/envs/django1.11.8/bin/uwsgi
chdir() to /home/ubuntu/mysite_test/mysitetest
your processes number limit is 7075
your memory page size is 4096 bytes
detected max file descriptor number: 1024
lock engine: pthread robust mutexes
thunder lock: disabled (you can enable it with --thunder-lock)
uwsgi socket 0 bound to TCP address 0.0.0.0:8000 fd 3
Python version: 3.6.7 | packaged by conda-forge | (default, Nov 21 2018, 03:09:43) [GCC 7.3.0]
Python main interpreter initialized at 0x5635857876d0
python threads support enabled
your server socket listen backlog is limited to 100 connections
your mercy for graceful operations on workers is 60 seconds
mapped 333504 bytes (325 KB) for 6 cores
*** Operational MODE: preforking+threaded ***
WSGI app 0 (mountpoint='') ready in 1 seconds on interpreter 0x5635857876d0 pid: 11435 (default app)
*** uWSGI is running in multiple interpreter mode ***
spawned uWSGI master process (pid: 11435)
spawned uWSGI worker 1 (pid: 11448, cores: 2)
spawned uWSGI worker 2 (pid: 11449, cores: 2)
spawned uWSGI worker 3 (pid: 11450, cores: 2)
這里保留著uwsgi運(yùn)行輸出的日志, 我們可以看到當(dāng)前系統(tǒng)的版本, python版本以及uwsig版本等等
6. 配置nginx靜態(tài)文件路徑
- 配置nginx
# file: /etc/nginx/sites-available(sites-enabled)/default
# 新添加location /static 路由配置, 重定向到指定的絕對路徑
server{
location /static {
# root static 文件夾所在的絕對路徑
root /home/path/to/mysite;
}
}
- 配置django
# file: /mysitetest/settings.py
# 在django配置文件中新增靜態(tài)文件的地址
STATICFILES_DIRS = (os.path.join(BASE_DIR, "static"), )
但是在測試時(shí)發(fā)現(xiàn)靜態(tài)文件訪問報(bào)403, 去查了一下發(fā)現(xiàn)需要將nginx的user改為root
# file: /etc/nginx/nginx.conf
# 更改user為root
# user www-data;
user root;
# 重啟nginx服務(wù)
$ sudo /etc/init.d/nginx restart