項目部署
項目部署流程:
-
買服務器, 服務器租用
-
選擇操作系統的版本,安裝系統
-
在開發環境中把項目需要的pip包寫到一個文件 pip freeze . requirements
.txt
-
把項目上傳到服務器
-
部署項目, 安裝需要的環境
- pyhton3解釋器
- 虛擬環境
- 數據庫
- nginx, uwsgi
服務器
nginx
mysql
redis
uwsgi
celery
docker
網站流量參考

網站流量度量
pv:獨立訪客
ip:獨立ip
uv:獨立訪客
並發:
每秒響應的最大連接數
web服務器每秒能夠接受的用戶連接數
web服務器每秒能接受最大用戶連接數
web服務器單位時間能夠處理的最大連接數
Django前后端分離項目部署
介紹
技術棧 Nginx+uwsgi+celery+supervisor
本教程 實現了負載均衡、反向代理、動靜分離,還實現了根據客戶端設備user-agent進行轉發,也就是移動端和PC端訪問的頁面不一樣。
前期准備
1. 項目部署邏輯圖

2. 環境准備
服務器:6台VM
操作系統:CentOS7
LB、www、wap:安裝Nginx
uwsgi1、uwsgi2:安裝nfs-utils、Python3解釋器、virtualenv
NFS:安裝NFS
MRCS:安裝MySQL、Redis、virtualenv
CentOS安裝Nginx
鏡像下載地址 http://isoredirect.centos.org/centos/7/isos/x86_64/CentOS-7-x86_64-DVD-1804.iso
CentOS 服務器部署遇到的常見問題
CentOS不能聯網
進入目錄
cd /etc/sysconfig/network-scripts/
輸入ls查看文件列表, 找到網卡配置文件,如下圖,我虛擬機的網卡名稱為ens33

編輯
vi
按i進入編輯模式, 編輯ifcfg-ens33文件的最后一行,將ONBOOT=no改為ONBOOT=yes,
按esc退出編輯模式, 輸入:wq保存退出

重啟network:
$ server network restart
pingi下百度能不能ping通
$ ping www.baidu.com
如果能ping通, 說明網絡已經可以連接了

CentOS沒有ifconfig命令的解決辦法
全新安裝centos的時候,運行ifconfig准備查看服務器IP的時候, 發現會報錯
-bash:command not found
網上搜了下, 原因可能是最小化安裝centos等Linux發行版的時候會默認不安裝ifconfig等命令
解決的辦法: yum安裝ifconfig這個包
首先搜索下
$ yum search ifconfig
發現ifconfig所屬的命令包是net-tools.x86_64

安裝
$ yum install net-tools.x86_64
中途會詢問“Is this os [y/d/n]”,按y回車,Complete完成安裝。
安裝完之后就可以輸入ifconfig查看網卡信息了

CentOS修改終端輸出語言
遠程連接centos服務器的時候, 發現有些字符會亂碼

在網上搜了下, 發現是默認語言設置的問題. 輸入echo $LANG和locale查詢, 結果如下

修改默認語言, 編輯配置文件
$ vi /etc/locale.conf
添加下面字段, wq保存
LANG=”zh_CN.UTF-8”
應用配置文件, 使其生效
$ source /etc/locale.conf
問題解決


CentOS編譯安裝Nginx
1. 環境准備
# 更換YUM源,centos默認源是國外的網站,下載會比較慢
curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
yum makecache
# 安裝編譯環境,如果安裝過了,就不需要再安裝了
yum -y install gcc*
2. 安裝pcre庫,如果不安裝pcre庫,Nginx無法使用rewrite模塊,在編譯安裝過程也會報錯
# 查詢pcre庫是否安裝
rpm -qa|grep pcre
yum -y install pcre pcre-devel
# 安裝完之后查詢一下是否安裝成功,如果能夠看到pcre和pcre-devel包就可以了
rpm -qa|grep pcre
3. 安裝nginx
# 創建一個software/目錄用來放軟件包
mkdir -p /opt/software
# 創建安裝目錄
mkdir -p /application/nginx-1.14.0
# 下載nginx安裝包
cd /opt/software
wget -q http://nginx.org/download/nginx-1.14.0.tar.gz
# 創建一個nginx用戶
useradd nginx -s /sbin/nologin -M //創建一個nginx用戶
# 解壓
tar xvf nginx-1.14.0.tar.gz
cd nginx-1.14.0
# 安裝
./configure --user=nginx --group=nginx --prefix=/application/nginx-1.14.0 --with-http_stub_status_module --with-http_ssl_module
# 如果安裝報./configure: error: SSL modules require the OpenSSL library 需要安裝openssl-devel,安裝完之后再執行一下上一條命令
yum -y install openssl-devel
make && make install
# 創建軟鏈接是為了以后如果要升級,應用程序中如果有引用Nginx路徑,不需要做任何更改,訪問的還是原來的路徑/application/nginx
ln -s /application/nginx-1.14.0/ /application/nginx
# 查看鏈接狀態
ls -l /application/nginx
注意:編譯安裝Nginx軟件時,還可以使用./configure --help查看相關參數幫助
4. 檢查安裝結果
# 啟動nginx服務
/application/nginx/sbin/nginx
netstat -lntup|grep 80
5. 在瀏覽器里面輸入nginx服務器IP地址

發現並沒有成功,原因是被centos防火牆攔截了, 這個時候, 我們需要關閉防火牆
6. 關閉防火牆
CentOS7版本后防火牆默認使用firewalld,因此在CentOS7中關閉防火牆使用以下命令,
# 臨時關閉
$ systemctl stop firewalld
# 禁止開機啟動
$ systemctl disable firewalld
Removed symlink /etc/systemd/system/multi-user.target.wants/firewalld.service.
Removed symlink /etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service.123456
當然,如果安裝了iptables-service,也可以使用下面的命令,
$ yum install -y iptables-services
# 關閉防火牆
$ service iptables stop
Redirecting to /bin/systemctl stop iptables.service
# 檢查防火牆狀態
$ service iptables status
Redirecting to /bin/systemctl status iptables.service
iptables.service - IPv4 firewall with iptables
Loaded: loaded (/usr/lib/systemd/system/iptables.service; disabled; vendor preset: disabled)
Active: inactive (dead)
重新訪問就能成功訪問了

CentOS 安裝NFS服務
0.准備工作
在之前安裝好的服務器克隆一個副本
先把CentOS關機, 然后如圖所示, 創建完整的克隆, 克隆一個副本

安裝NFS服務,需要安裝nfs-utils和rpcbind,NFS的RPC服務,在Centos5.X下名稱為portmap,在Centos6.X下名稱為rcpbind。
1.查詢nfs服務和rpc服務是否安裝
[root@localhost ~]# rpm -qa|grep nfs
[root@localhost ~]# rpm -qa|grep rpcbind
2.使用YUM安裝nfs和rpcbind
[root@localhost ~]# yum install -y nfs-utils
3.啟動nfs服務,在啟動nfs服務之前,一定要先啟動rpcbind,然后再啟動nfs
[root@localhost ~]# service rpcbind start
Redirecting to /bin/systemctl start rpcbind.service
查看rpc信息
[root@localhost ~]# rpcinfo -p localhost
program vers proto port service
100000 4 tcp 111 portmapper
100000 3 tcp 111 portmapper
100000 2 tcp 111 portmapper
100000 4 udp 111 portmapper
100000 3 udp 111 portmapper
100000 2 udp 111 portmapper
[root@localhost ~]# service nfs start
Starting NFS services: [ OK ]
Starting NFS quotas: [ OK ]
Starting NFS mountd: [ OK ]
Starting NFS daemon: [ OK ]
Starting RPC idmapd: [ OK ]
啟動nfs服務以后,再查看rpcinfo信息。
[root@localhost ~]# rpcinfo -p
program vers proto port service
100000 4 tcp 111 portmapper
100000 3 tcp 111 portmapper
100000 2 tcp 111 portmapper
100000 4 udp 111 portmapper
100000 3 udp 111 portmapper
100000 2 udp 111 portmapper
100011 1 udp 875 rquotad
100011 2 udp 875 rquotad
100011 1 tcp 875 rquotad
100011 2 tcp 875 rquotad
100005 1 udp 35606 mountd
100005 1 tcp 38238 mountd
100005 2 udp 33761 mountd
100005 2 tcp 41083 mountd
100005 3 udp 47608 mountd
100005 3 tcp 35056 mountd
100003 2 tcp 2049 nfs
100003 3 tcp 2049 nfs
100003 4 tcp 2049 nfs
100227 2 tcp 2049 nfs_acl
100227 3 tcp 2049 nfs_acl
100003 2 udp 2049 nfs
100003 3 udp 2049 nfs
100003 4 udp 2049 nfs
100227 2 udp 2049 nfs_acl
100227 3 udp 2049 nfs_acl
100021 1 udp 34627 nlockmgr
100021 3 udp 34627 nlockmgr
100021 4 udp 34627 nlockmgr
100021 1 tcp 46375 nlockmgr
100021 3 tcp 46375 nlockmgr
100021 4 tcp 46375 nlockmgr
4.配置共享目錄/share,允許192.168.25.*訪問
[root@localhost ~]# mkdir /share //創建共享目錄
[root@localhost ~]# ll -d /share/ //查看目錄信息
drwxr-xr-x. 2 root root 4096 Dec 30 13:55 /share/
[root@localhost ~]# chown -R nfsnobody:nfsnobody /share/ //更改目錄所屬用戶和所屬組
[root@localhost ~]# ll -d /share/
drwxr-xr-x. 2 nfsnobody nfsnobody 4096 Dec 30 13:55 /share/
[root@localhost ~]# vi /etc/exports
/share 192.168.25.*(rw,sync) # 添加此字段 wq保存 ///share 192.168.25.* 本機IP網段
5.查看NFS共享目錄信息
[root@localhost ~]# showmount -e 192.168.25.231 //本機IP
Export list for 192.168.25.231:
/share 192.168.25.*
6.NFS客戶端掛載共享目錄/share
[root@localhost ~]# mount -t nfs 192.168.25.231:/share /mnt
[root@localhost ~]# df -h
文件系統 容量 已用 可用 已用% 掛載點
/dev/mapper/centos-root 17G 1.8G 16G 11% /
devtmpfs 476M 0 476M 0% /dev
tmpfs 488M 0 488M 0% /dev/shm
tmpfs 488M 7.9M 480M 2% /run
tmpfs 488M 0 488M 0% /sys/fs/cgroup
/dev/sda1 1014M 130M 885M 13% /boot
tmpfs 98M 0 98M 0% /run/user/0
192.168.25.231:/share 17G 1.8G 16G 11% /mnt
7.NFS客戶端排錯思路
試客戶端與服務端網絡是否可否,如在客戶端使用ping IP地址
在服務端自己掛載看看是否能夠正常掛載
檢查服務端防火牆規則,初學者可以選擇直接關閉防火牆
8.管理NFS共享目錄
exportfs命令可以導出NFS服務器上的共享目錄、顯示共享目錄,或者不導出共享目錄。
命令語法:
exportfs [選項][目錄]
| 選項 | 含義 |
|---|---|
| -a | 導出或不導出所有的目錄 |
| -v | 顯示導出列表的同時,也顯示導出選項的列表 |
| -u | 不導出指定的目錄。當和-a選項一起時,不導出所有的目錄 |
| -f | 指定一個新的導出文件,而不是/etc/exports文件 |
| -r | 重新導出所有的目錄 |
| -o<選項> | 指定導出選項列表 |
查看NFS共享目錄信息
showmount [選項][NFS服務器]
| 選項 | 含義 |
|---|---|
| -a | 同時顯示客戶端的主機名或IP地址以及所掛載的目錄 |
| -e | 顯示NFS服務器的導出列表 |
| -d | 只顯示已經被掛載的NFS共享目錄信息 |
9.NFS配置文件權限參數說明
| 參數名稱 | 參數用途 |
|---|---|
| rw | 共享目錄具有讀寫權限 |
| ro | 共享目錄具有只讀權限 |
| sync | 請求或寫入數據時,數據同步寫入到NFS Server硬盤中。數據安全不會丟,缺點,性能比不啟用該參數要差。 |
| async | 請求或寫入數據時,先返回請求,再將數據寫入到內存緩存和硬盤中,即異步寫入數據。此參數可以提升NFS性能,但是會降低數據的安全。因此,一般情況下建議不用,如果NFS處於瓶頸狀態,並且允許數據丟失的話可以打開此參數提升NFS性能。寫入時數據會先到內存緩沖區,等硬盤有空檔再寫入磁盤,這樣可以提升寫入效率!風險為若服務器宕機或不正常關機,會損失緩沖區未寫入硬盤的數據(解決辦法:服務器主板電池或加UPS不間斷電源)! |
| root_squash | root用戶的所有請求映射成如nfsnobody(匿名)用戶一樣的權限 |
| no_root_squash | 關閉root_squash |
| all_squash | 映射所有的UID和GID為匿名用戶 |
| no_all_squash | 保留共享文件的UID和GID(默認) |
| anonuid | 指定NFS服務器/etc/passwd文件中匿名用戶的UID |
| anongid | 指定NFS服務器/etc/passwd文件中匿名用戶的GID |
| secure | NFS通過1024以下的安全TCP/IP端口發送 |
| insecure | NFS通過1024以上的端口發送 |
| wdelay | 如果多個用戶要寫入NFS目錄,則歸組寫入(默認) |
| no_wdelay | 如果多個用戶要寫入NFS目錄,則立即寫入,當使用async時,不需要設置 |
| subtree_check | 如果共享/usr/bin之類的子目錄時,強制NFS檢查父目錄的權限 |
| no_subtree_check | 和subtree_check相對,不檢查父目錄權限 |
| hide | 在NFS共享目錄中不共享其子目錄 |
| nohide | 共享NFS目錄的子目錄 |
| mp | 如果它已經成功掛載,那么使得它只導出一個目錄 |
| fsid | NFS需要能夠識別每個它導出的文件系統。通常情況下它會為文件系統使用一個UUID,或者該設備保持文件系統的設備號 |
負載均衡和反向代理服務器配置
在LB(負載均衡)服務器上面配置
(就是第一個創建的那個服務器)
編輯nginx.conf
vi /application/nginx/conf/nginx.conf
文件更改為
如果要寫注釋, 中文亂碼的話, 可以臨時配為utf8編碼. 在vim的命令模式下輸入
:set encoding=utf8, 就可以輸入中文了建議下載下來使用vscode裝nginx插件進行編輯會比較方便
# 配置文件內容
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
# 靜態請求服務器池
upstream static_pools {
server 192.168.25.150:80 weight=1;
}
# 動態請求服務器池
upstream dynamic_pool {
server 192.168.25.151:8001 weight=1;
server 192.168.25.152:8001 weight=1;
}
# 移動端服務器池
upstream mobile_pools {
server 192.168.25.160:80 weight=1;
}
# 后端api服務器
server {
listen 8080;
server_name api.meiduo.site;
location / {
include uwsgi_params;
uwsgi_pass dynamic_pool;
}
access_log off;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
# 提供前端頁面訪問
server {
listen 80;
server_name www.meiduo.site;
# 如果訪問url為:http://www.meiduo.site/xadmin就交給meiduo池
location /xadmin{
include uwsgi_params;
uwsgi_pass dynamic_pool;
}
# 如果請求url為:http://www.meiduo.site/cheditor就交給meiduo池
location /cheditor{
include uwsgi_params;
uwsgi_pass dynamic_pool;
}
# 請求uri以/開頭就交給這個location區塊進行處理,例如:/static
location / {
# 如果客戶端設備user_agent為iphone,就交給iphone_pools池
if ($http_user_agent ~* "iphone")
{
proxy_pass http://mobile_pools;
}
# PC端訪問就交給static_pools池處理
proxy_pass http://static_pools;
}
access_log off;
}
}
啟動nginx服務
/application/nginx/sbin/nginx
NFS 服務器配置
mkdir /project
# 配置掛載目錄
cat /etc/exports
# 配置內容
/share 192.168.25.*(rw,sync)
# 重啟NFS服務
systemctl restart rpcbind
systemctl restart nfs
配置完成之后把項目上傳到/project目錄里面
配置uwsgi和uwsgi2服務器
在uwsgi1和uwsig2服務器上操作:
# 創建虛擬環境
mkvirtualenv -p python3 meiduo
# 切換到meiduo虛擬環境
workon mediuo
# 安裝uwsgi包
pip install uwsgi
mkdir /project
# 掛載NFS服務器/project目錄到uwsgi服務器的/project
mount -t nfs 172.16.1.14:/project /project
# 查看當前服務器掛載情況
df -h
# 輸出
文件系統 容量 已用 可用 已用% 掛載點
/dev/mapper/centos-root 36G 2.4G 33G 7% /
devtmpfs 226M 0 226M 0% /dev
tmpfs 237M 0 237M 0% /dev/shm
tmpfs 237M 8.8M 228M 4% /run
tmpfs 237M 0 237M 0% /sys/fs/cgroup
/dev/sda1 1014M 143M 872M 15% /boot
tmpfs 48M 0 48M 0% /run/user/0
172.16.1.14:/project 17G 1.8G 16G 11% /project
# 安裝項目中用到的pip包
cd /project/meiduo/meiduo_mall
pip install -r requirements.txt # 這個文件是在開發環境中通過pip freeze >requirements.txt生成的
cd /root
# 創建uwsgi.ini文件
touch uwsgi.ini
uwsgi1配置
[uwsgi]
#使用nginx連接時使用,Django程序所在服務器地址
socket=172.16.1.11:8001
#直接做web服務器使用,Django程序所在服務器地址
#http=172.16.1.11:8000
#項目目錄
chdir=/project/meiduo/meiduo_mall
#項目中wsgi.py文件的目錄,相對於項目目錄
wsgi-file=meiduo_mall/wsgi.py
# 進程數
processes=4
# 線程數
threads=2
# uwsgi服務器的角色
master=True
# 存放進程編號的文件
pidfile=uwsgi.pid
# 日志文件,因為uwsgi可以脫離終端在后台運行,日志看不見。我們以前的runserver是依賴終端的
daemonize=uwsgi.log
# 指定依賴的虛擬環境
virtualenv=/root/.virtualenvs/meiduo
uwsgi2配置
[uwsgi]
#使用nginx連接時使用,Django程序所在服務器地址
socket=172.16.1.12:8001
#直接做web服務器使用,Django程序所在服務器地址
#http=172.16.1.12:8000
#項目目錄
chdir=/project/meiduo/meiduo_mall
#項目中wsgi.py文件的目錄,相對於項目目錄
wsgi-file=meiduo_mall/wsgi.py
# 進程數
processes=4
# 線程數
threads=2
# uwsgi服務器的角色
master=True
# 存放進程編號的文件
pidfile=uwsgi.pid
# 日志文件,因為uwsgi可以脫離終端在后台運行,日志看不見。我們以前的runserver是依賴終端的
daemonize=uwsgi.log
# 指定依賴的虛擬環境
virtualenv=/root/.virtualenvs/meiduo
uwsgi啟動命令
# 啟動uwsgi服務器
uwsgi --ini uwsgi.ini
# 停止uwsgi服務器
uwsgi stop uwsgi.ini
5. www服務器
處理PC端靜態文件請求
cat nginx.conf
# 配置文件
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name www.meiduo.site;
location / {
root html/front_end_pc;
# 相對路徑,把前端文件夾放到Nginx安裝路徑下html目錄下,我這里的路徑是/application/nginx/html
index index.html index.htm;
}
access_log logs/access_www.log main;
}
}
啟動nginx服務
/application/nginx/sbin/nginx
6. wap服務器
處理移動端靜態文件請求
cd /application/nginx/html
# 因為沒有移動端前端頁面,所以這里簡單創建了一個測試頁面
mkdir wap
echo "mobile_page" > wap/index.html
Nginx配置
cat nginx.conf
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name www.meiduo.site;
location / {
root html/wap;
# 相對路徑,把前端文件夾放到Nginx安裝路徑下html目錄下,我這里的路徑是/application/nginx/html
index index.html index.htm;
}
access_log logs/access_www.log main;
}
}
啟動nginx服務
/application/nginx/sbin/nginx
7. MRCS服務器(資源有限,所以把這些東西安裝在一台服務器上面)
mkdir /project
# 掛載NFS服務器/project目錄到uwsgi服務器的/project
mount -t nfs 172.16.1.14:/project /project
# 查看當前服務器掛載情況
df -h
# 輸出
文件系統 容量 已用 可用 已用% 掛載點
/dev/mapper/centos-root 36G 2.4G 33G 7% /
devtmpfs 226M 0 226M 0% /dev
tmpfs 237M 0 237M 0% /dev/shm
tmpfs 237M 8.8M 228M 4% /run
tmpfs 237M 0 237M 0% /sys/fs/cgroup
/dev/sda1 1014M 143M 872M 15% /boot
tmpfs 48M 0 48M 0% /run/user/0
172.16.1.14:/project 17G 1.8G 16G 11% /project
# 創建虛擬環境
mkvirtualenv -p python3 meiduo
# 切換到meiduo虛擬環境
workon mediuo
# 安裝項目中用到的pip包
cd /project/meiduo/meiduo_mall
pip install -r requirements.txt # 這個文件是在開發環境中通過pip freeze >requirements.txt生成的
配置supervisor
mkvirtualenv -p python2 supervisor
# 這里創建python2的虛擬環境,因為supervisor不支持python3
workon supervisor
pip install supervisor
# 生成supervisor配置文件
echo_supervisord_conf > /etc/supervisord.conf
# 創建日志目錄
mkdir /var/log/celery
創建celery.ini文件
cat /etc/celery.ini
# 配置內容
[program:celery]
# celery命令的絕對路徑
command=/root/.virtualenvs/meiduo/bin/celery -A celery_tasks.main worker -l info
# 項目路徑
directory=/project/meiduo/meiduo_mall
# 日志文件路徑
stdout_logfile=/var/log/celery/celery.log
# 自動重啟
autorestart=true
# 如果設置為true,進程則會把標准錯誤輸出到supervisord后台的標准輸出文件描述符
redirect_stderr=true
修改/etc/supervisord.conf文件
[include]
files = celery.ini
supervisor命令
# 以守護進程的形式運行一組應用程序。
supervisord
# 更新新的配置到supervisord
supervisorctl update
# 查看正在守護的進程
supervisorctl
8. 訪問測試
在hosts文件里面添加本地解析
windows系統hosts文件路徑:系統盤\windows\system32\drivers\etc
Linux系統和MAC系統hosts文件路徑:/etc/hosts
172.16.1.10 www.meiduo.site api.meiduo.site
PC端訪問效果
