【Django项目部署】Nginx+uWSGI+Django部署

前言


Django开发实际线上部署的最优架构:Nginx+uWSGI+Django。
采用动/静分离高效的WEB设计。

WEB发展史回顾


这里写图片描述

wsgi概念


WSGI,全称 Web Server Gateway Interface,
或者 Python Web Server Gateway Interface ,
是为 Python 语言定义的 Web 服务器和 Web 应用程序或框架之间的一种简单而通用的接口。
自从 WSGI 被开发出来以后,许多其它语言中也出现了类似接口。

很多框架都自带了 WSGI server ,比如 Flask,webpy,Django、CherryPy等等。
当然性能都不好,自带的 web server 更多的是测试用途,发布时则使用生产环境的WSGI server或者是联合 nginx 做 uwsgi

uWSGI概念


WSGI是一种Web服务器网关接口。
它是一个Web服务器(如nginx)与应用服务器(如uWSGI服务器)通信的一种规范。

uWSGI是一个Web服务器,它实现了WSGI协议、uwsgi、http等协议。
Nginx中HttpUwsgiModule的作用是与uWSGI服务器进行交换。

WSGI / uwsgi / uWSGI 三者区别:

WSGI是一种通信协议。
uwsgi同WSGI一样是一种通信协议。
而uWSGI是实现了uwsgi和WSGI两种协议的Web服务器。

为什么有了uWSGI为什么还需要nginx?
因为nginx具备优秀的静态内容处理能力,然后将动态内容转发给uWSGI服务器,这样可以达到很好的客户端响应。



Nginx+uWSGI+Django架构图


这里写图片描述

Nginx+uWSGI+Django部署流程

1、上传项目至目标服务器并安装项目所需的模块

包整项目能正常通过runserver启动并且检查没有问题

2、Linux 下Python安装[用是升级不影响现有Python/多版本共存]
下载Python

安装Python依赖包

yum -y install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gcc make 

解压和安装软件包(也可使用 yum install python3 )
tar -xzvf /opt/Python-3.6.1.tgz -C /usr/local/src/  # src目录是存放源码的目录解压到src目录
cd /usr/local/src/Python-3.6.1
./configure --prefix=/usr/local/python3
make && make install

添加环境变量:

cd /etc/profile.d/
# 编辑这个文件,在最底行写入PATH
vim /etc/profile 
  		
export PATH="$PATH:/usr/local/python3/bin"
source ../profile  # 重载文件
echo $PATH  # 查看当前环境变量是否添加

3、代码上传 xshell / Git 简单的Git命令

yum -y install git
git clone 你的git url 

注:通过ssh-keygen 生成公钥,并上传到git服务端完成下载
ssh-keygen -t rsa -C '152303832@qq.com'
cat .ssh/id_rsa.pub  

安装uwsgi 并使用uWSGI启动这个服务

pip3 install uwsgi

# 同时安装python库
python -m pip install tensorflow  -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com		# 配置豆瓣源
pip3 install  -r requerments.txt		# 安装文件中指定的库及版本

解决问题:OSError: mysql_config not found

原因是linux需要mysql相关的一些依赖包
yum install mysql-devel gcc gcc-devel python-devel

测试浏览器是否能够访问:

python3 manage.py runserver  ip址址:端口	# 0.0.0.0:8000

python3 manage.py runserver --settings=back-server.settings.dev

调试uWSGI服务来启动项目:
执行这条命令的时候:一定要在这个项目目录中~

uwsgi --http 192.168.31.123:80 --file teacher/wsgi.py --static-map=/static=static
注:--static-map=/static=static可不写

问题: pip install uwsgi 之后,运行uwsgi 报错:[uwsgi: command not found]
解决方案:建立软链接  	ln -s /usr/local/python3/bin/uwsgi /usr/bin/uwsgi

执行结果:

*** Starting uWSGI 2.0.18 (64bit) on [Thu Sep 19 07:04:13 2019] ***
compiled with version: 4.8.5 20150623 (Red Hat 4.8.5-39) on 19 September 2019 06:50:15
os: Linux-3.10.0-862.el7.x86_64 #1 SMP Fri Apr 20 16:44:24 UTC 2018
nodename: 8f051f9facfb
machine: x86_64
clock source: unix
pcre jit disabled
detected number of CPU cores: 8
current working directory: /opt/delivery_support/user_sso_api
detected binary path: /usr/local/python3/bin/uwsgi
uWSGI running as root, you can use --uid/--gid/--chroot options
*** WARNING: you are running uWSGI as root !!! (use the --uid flag) *** 
*** WARNING: you are running uWSGI without its master process manager ***
your memory page size is 4096 bytes
detected max file descriptor number: 1048576
lock engine: pthread robust mutexes
thunder lock: disabled (you can enable it with --thunder-lock)
uWSGI http bound on 127.0.0.1:80 fd 4
spawned uWSGI http 1 (pid: 2356)
uwsgi socket 0 bound to TCP address 127.0.0.1:39090 (port auto-assigned) fd 3
uWSGI running as root, you can use --uid/--gid/--chroot options
*** WARNING: you are running uWSGI as root !!! (use the --uid flag) *** 
Python version: 3.6.4 (default, Sep  5 2019, 15:51:40)  [GCC 4.8.5 20150623 (Red Hat 4.8.5-36)]
*** Python threads support is disabled. You can enable it with --enable-threads ***
Python main interpreter initialized at 0x257d670
uWSGI running as root, you can use --uid/--gid/--chroot options
*** WARNING: you are running uWSGI as root !!! (use the --uid flag) *** 
your server socket listen backlog is limited to 100 connections
your mercy for graceful operations on workers is 60 seconds
mapped 72920 bytes (71 KB) for 1 cores
*** Operational MODE: single process ***
WSGI app 0 (mountpoint='') ready in 0 seconds on interpreter 0x257d670 pid: 2355 (default app)
uWSGI running as root, you can use --uid/--gid/--chroot options
*** WARNING: you are running uWSGI as root !!! (use the --uid flag) *** 
*** uWSGI is running in multiple interpreter mode ***
spawned uWSGI worker 1 (and the only) (pid: 2355, cores: 1)


实际生产环境中使用配置文件uwsgi.ini启动uWSGI[ini]
文件内容如下:

[uwsgi]
# 项目目录
chdir=/opt/project_teacher/teacher/
# 启动uwsgi的用户名和用户组
uid=root
gid=root
# 指定项目的application
module=teacher.wsgi:application
# 指定sock的文件路径
socket=/opt/project_teacher/script/uwsgi.sock
# 启用主进程
master=true
# 进程个数
workers=5
pidfile=/opt/project_teacher/script/uwsgi.pid
# 自动移除unix Socket和pid文件当服务停止的时候
vacuum=true
# 序列化接受的内容,如果可能的话
thunder-lock=true
# 启用线程
enable-threads=true
# 设置自中断时间
harakiri=30
# 设置缓冲
post-buffering=4096
# 设置日志目录
daemonize=/opt/project_teacher/script/uwsgi.log   

注:uwsgi.ini 文件单独放置于自定义的script文件夹中

uwsgi启动项目:

[root@8f051f9facfb delivery_support]# uwsgi --ini scripts/user_sso_api/uwsgi.ini 
[uWSGI] getting INI configuration from scripts/user_sso_api/uwsgi.ini

查看进程:

ps -ef | grep -i  uwsgi # 查看进程是否启动

uwsgi停止项目:

[root@8f051f9facfb user_sso_api]# uwsgi --stop scripts/user_sso_api/uwsgi.pid 

安装Nginx

配置yum源:

vim /etc/yum.repos.d/nginx.repo	 # 配置yum源
[nginx]
name=nginx repo
# 下面这行centos根据你自己的操作系统修改比如:OS/rehel
# 6是你Linux系统的版本,可以通过URL查看路径是否正确
baseurl=http://nginx.org/packages/centos/6/$basearch/
gpgcheck=0
enabled=1

安装nginx

yum -y install nginx

添加配置文件

[root@8f051f9facfb user_sso_api]# vim /etc/nginx/nginx.conf 

……   
server {
     listen 80;
     server_name 10.129.205.183 ;
     access_log  /var/log/nginx/access.log  main;
     charset  utf-8;
     gzip on;
     gzip_types text/plain application/x-javascript text/css text/javascript application/x-httpd-php application/json text/json image/jpeg image/gif image/png application/octet-stream;

     error_page  404           /404.html;
     error_page   500 502 503 504  /50x.html;
     # 指定项目路径uwsgi
     location / {
         include uwsgi_params;
         uwsgi_connect_timeout 30;
         # 指定项目的sock文件位置
         uwsgi_pass unix:/opt/project_teacher/script/uwsgi.sock;	
     }
     # 指定静态文件路径
     location /static/ {
         alias  /opt/project_teacher/teacher/static/;
         index  index.html index.htm;
     }

} 

重启nginx:

添加默认静态文件目录

vim ../teacher/teacher/settings.py
STATIC_ROOT = os.path.join(BASE_DIR, "static_all")

执行命令来收集项目中所有的静态文件重新生成新的静态文件夹
python3 manage.py collectstatic --noinput

注:以上配置将会解决admin组件静态文件无法访问的问题

Nginx配置静态文件简单修改

……
    # 指定静态文件路径
         location /static/ {
             alias  /opt/project_teacher/teacher/static_all/;
             index  index.html index.htm;
         }

添加管理脚本

cd /etc/init.d/
vim manage_teacher

#! /bin/sh
# chkconfig: 345 85 15
# 上面一行注释:哪些Linux级别需要启动manage_teacher(3,4,5);启动序号(85);关闭序号(15)。
# description: manage script is the teacher daemon.
# Author: luotianshuai
# 指定项目目录
PROJECT_DIR="/opt/project_teacher/teacher"
# 指定脚本目录在哪里
SCRIPTS_DIR="/opt/project_teacher/script"
# 描述
DESC="teacher daemon"
# 名称
NAME="teacher"
# 脚本名称
SCRIPT_FILENAME="manage_teacher.sh"
# 脚本目录名称
SCRIPTNAME=`pwd`/$SCRIPT_FILENAME

# PID
PID="uwsgi.pid"

# 启动函数
d_start(){
# 进入到项目目录
cd $SCRIPTS_DIR
# 判断这个PID是否存在
if [ ! -f $PID ];then
echo -e "\n\033[34m$NAME项目启动中........\033[0m"
# 如果不存在执行
uwsgi --ini uwsgi.ini
killall nginx
/etc/init.d/nginx start
# 自动收集静态文件
cd $PROJECT_DIR && python3 manage.py collectstatic --noinput
echo -e "\n\033[32m$NAME 项目启动完成........\033[0m"
exit 0
fi
echo -e "\n\033[33m$NAME 项目已启动请勿重复启动\033[0m"
}
# 关闭函数
# 关闭项目
d_stop(){
# 进入脚本目录
cd $SCRIPTS_DIR
# 判断这个pid文件是否存在
if [ ! -f "uwsgi.pid" ];then
# 这个项目已经关闭了
echo -e "\n\033[33m$NAME 项目已经关闭了请先启动\033[0m"
fi
echo -e "\n\033[34m$NAME 项目关闭中........\033[0m"
echo -e "\nStop $DESC: $NAME"
# 如果没有关闭
uwsgi --stop uwsgi.pid
# 是否停掉Nginx根据实际需要来操作~~!因为Nginx有对静态文件缓存[注意]
killall nginx
/etc/init.d/nginx start
echo -e "\n\033[32m$NAME 项目关闭完成........\033[0m"
}

d_restart(){
d_stop
sleep 1
d_start
}

case "$1" in
start)
echo -e "\nstarting $DESC: $NAME"
d_start
;;
stop)
echo -e "\nStop $DESC: $NAME"
d_stop
;;
restart)
echo -e "\nRestart $DESC: $NAME"
d_restart
;;
*)
echo "Usage: $SCRIPTNAME {start|stop|restart}" >&2
exit 3
;;
esac

添加服务

将自动部署脚本复制一份到/etc/init.d/目录中,不需要后缀名.sh
chkconfig --add manage_teacher

设置为开机启动

[root@localhost init.d]# chkconfig manage_teacher on 

查看启动级别

[root@localhost init.d]# chkconfig --list manage_teacher 
manage_teacher 	0:off	1:off	2:on	3:on	4:on	5:on	6:off

至此,就可以通过命令启动整个完整项目

[root@localhost ~]# service manage_teacher start
[root@localhost ~]# service manage_teacher stop
[root@localhost ~]# service manage_teacher restart

快速部署[一键部署脚本]

–你现在没有时间看原理和实际部署
–一键部署的脚本 deployment.sh 去部署Nginx+uWSGI+Django
–可能会有一些局限性

一键部署操作步骤:

1、上传项目
2、安装模块和uwsgi
3、仔细阅读一键部署文档说明

您需要修改的地方有:

# [config1]项目名称
PROJECT_NAME="teacher"

# [config2]nginx域名或者IP地址和端口,我们用来访问的
SERVER_NAME="192.168.31.123" #也可以是域名
SERVER_PORT=80

# 重载环境变量
export PATH=\$PATH:/usr/local/python3.6/bin  # 这里是你python的bin目录

4、执行部署脚本

5、执行脚本命令:

service manage_你的项目名 start|stop|restart|

以项目名teacher为例:

service manage_teacher  {start|stop|restart}

# 系统版本是CentOS 6.5 Python 3.6.1

一键部署脚本具体内容:

#! /bin/sh
# description:一键部署Nginx+uWSGI+Django
# Author: luotianshuaiA

#使用说明
#1、环境:
#一键部署脚本前提您已经保证Django可以通过runserver启动起来并且测试无代码问题
#
#2、目录要求:
#请保证这个脚本,和项目在同一级目录
#    [root@localhost opt]# tree -L 1 project_teacher/
#    project_teacher/
#    |-- deploy_project.sh  #部署脚本
#    `-- teacher  #项目目录
#
#    1 directory, 1 file
#    [root@localhost opt]#
#
#    # 比如脚本在/opt/project_teacher目录下面那么请把项目上传到这个目录下面
#3、您需要的配置项有
#[config1]
#[config2]
#
#4、本脚本使用会自动添加Nginx配置,请确保没有安装Nginx,并且系统为Centos6.5
#

# 这里不需要动,保证脚本目录所在的目录中包含了项目目录即可
MANAGE_DIR=`pwd`
#**************************您的配置区域其他的无需修改**************************
# [config1]项目名称
PROJECT_NAME="teacher"
# [config2]nginx域名或者IP地址和端口,我们用来访问的
SERVER_NAME="192.168.31.123" #也可以是域名
SERVER_PORT=80

#******************************************************************************
# 项目目录
PROJECT_DIR=$MANAGE_DIR/$PROJECT_NAME


# 检查项目目录是否存在
check_project(){
if [ ! -d $PROJECT_DIR ]; then
echo -e "\n\033[33m PROJECT_DIR 没有指定,请指定项目目录\033[0m"
exit 0
elif [ -d $PROJECT_DIR ]; then
echo -e "\033[32m项目目录存在是:$PROJECT_DIR........\033[0m"
fi


}


# 创建脚本管理配置
make_script_init(){
echo -e "\033[32m开始创建script目录........\033[0m"
mkdir script
echo -e "\033[32m开始创建管理文件........\033[0m"
cat > script/manage_$PROJECT_NAME<<EOF
#! /bin/sh
# chkconfig: 345 85 15
# 上面一行注释:哪些Linux级别需要启动manage_teacher(3,4,5);启动序号(85);关闭序号(15)。
# description: manage script is the $PROJECT_NAME daemon.
# Author: luotianshuai
# 重载环境变量
export PATH=\$PATH:/usr/local/python3.6/bin
# 指定项目目录
PROJECT_DIR=$PROJECT_DIR
# 指定脚本目录在哪里
SCRIPTS_DIR=$MANAGE_DIR/script
# 描述
DESC="$PROJECT_NAME daemon"
# 名称
NAME=$PROJECT_NAME
# 脚本名称
SCRIPT_FILENAME=manage_$PROJECT_NAME
# 脚本目录名称
SCRIPTNAME=$MANAGE_DIR/script
# PID
PID="uwsgi.pid"

# 启动函数
d_start(){
# 进入到项目目录
cd $MANAGE_DIR/script/
# 判断这个PID是否存在
if [ ! -f "uwsgi.pid" ];then
echo -e "\n\033[34m$NAME项目启动中........\033[0m"
# 如果不存在执行
uwsgi --ini uwsgi.ini
killall nginx
/etc/init.d/nginx start
# 自动收集静态文件
cd $MANAGE_DIR/$PROJECT_NAME&& python3 manage.py collectstatic --noinput
echo -e "\n\033[32m$NAME 项目启动完成........\033[0m"
exit 0
fi
echo -e "\n\033[33m$NAME 项目已启动请勿重复启动\033[0m"
}
# 关闭函数
# 关闭项目
d_stop(){
# 进入脚本目录
cd $MANAGE_DIR/script/
# 判断这个pid文件是否存在
if [ ! -f "uwsgi.pid" ];then
# 这个项目已经关闭了
echo -e "\n\033[33m$NAME 项目已经关闭了请先启动\033[0m"
fi
echo -e "\n\033[34m$NAME 项目关闭中........\033[0m"
echo -e "\nStop $DESC: $NAME"
# 如果没有关闭
uwsgi --stop uwsgi.pid
# 是否停掉Nginx根据实际需要来操作~~!因为Nginx有对静态文件缓存[注意]
killall nginx
/etc/init.d/nginx start
echo -e "\n\033[32m$NAME 项目关闭完成........\033[0m"
}

d_restart(){
d_stop
sleep 1
d_start
}

case "\$1" in
start)
echo -e "\nstarting $DESC: $NAME"
d_start
;;
stop)
echo -e "\nStop $DESC: $NAME"
d_stop
;;
restart)
echo -e "\nRestart $DESC: $NAME"
d_restart
;;
*)
echo "Usage: $SCRIPTNAME {start|stop|restart}" >&2
exit 3
;;
esac
EOF
chmod 755 $MANAGE_DIR/script/manage_$PROJECT_NAME
echo -e "\033[32m开始添加uwsgi.ini配置文件........\033[0m"
cat > script/uwsgi.ini<<EOF
[uwsgi]
# 项目目录
chdir=$PROJECT_DIR
# 启动uwsgi的用户名和用户组
uid=root
gid=root
# 指定项目的application
module=$PROJECT_NAME.wsgi:application
# 指定sock的文件路径
socket=$MANAGE_DIR/script/uwsgi.sock
# 启用主进程
master=true
# 进程个数
workers=5
pidfile=$MANAGE_DIR/script/uwsgi.pid
# 自动移除unix Socket和pid文件当服务停止的时候
vacuum=true
# 序列化接受的内容,如果可能的话
thunder-lock=true
# 启用线程
enable-threads=true
# 设置自中断时间
harakiri=30
# 设置缓冲
post-buffering=4096
# 设置日志目录
daemonize=$MANAGE_DIR/script/uwsgi.log
EOF
echo  "STATIC_ROOT = os.path.join(BASE_DIR, 'static_all')">> $MANAGE_DIR/$PROJECT_NAME/$PROJECT_NAME/settings.py
}

make_nginx_init(){
echo -e "\033[32m初始化Nginx........\033[0m"
cat > /etc/yum.repos.d/nginx.repo<<EOF
[nginx]
name=nginx repo
# 下面这行centos根据你自己的操作系统修改比如:OS/rehel
# 6是你Linux系统的版本,可以通过URL查看路径是否正确
baseurl=http://nginx.org/packages/centos/6/\$basearch/
gpgcheck=0
enabled=1
EOF
yum -y install nginx
echo -e "\033[32m添加Nginx配置文件........\033[0m"

cat > /etc/nginx/conf.d/$PROJECT_NAME.conf<<EOF
    server {
                    listen $SERVER_PORT;
                    server_name $SERVER_NAME ;
                    access_log  /var/log/nginx/access.log  main;
                    charset  utf-8;
                    gzip on;
                    gzip_types text/plain application/x-javascript text/css text/javascript application/x-httpd-php application/json text/json image/jpeg image/gif image/png application/octet-stream;

                    error_page  404           /404.html;
                    error_page   500 502 503 504  /50x.html;
                    # 指定项目路径uwsgi
                    location / {
                        include uwsgi_params;
                        uwsgi_connect_timeout 30;
                        uwsgi_pass unix:$MANAGE_DIR/script/uwsgi.sock;
                    }
                    # 指定静态文件路径
                    location /static/ {
                        alias  $MANAGE_DIR/$PROJECT_NAME/static_all/;
                        index  index.html index.htm;
                    }

    }
EOF
}
add_server(){
echo -e "\033[32m添加管理至服务........\033[0m"
cp $MANAGE_DIR/script/manage_$PROJECT_NAME /etc/init.d/
chkconfig --add /etc/init.d/manage_$PROJECT_NAME
chkconfig /etc/init.d/manage_$PROJECT_NAME on

# 启动服务
echo -e "\033[32m启动服务........\033[0m"
service manage_$PROJECT_NAME start
}


check_project
make_script_init
make_nginx_init
add_server

```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值