django + uWSGI + nginx works processes and deployment process

django + uWSGI + nginx works processes and deployment process

I. Introduction

Sharing of knowledge, should not just show up, you should also do so to explain why ...

Dedicated to like me ignorant for knowledge, progress of the people.

Give a man a fish, as delegate to fish!


Second, the necessary prerequisite knowledge

2.1 Preparation of knowledge

  1. Django

    .基于python的一个web框架,同类框架有Flask、Tornado...
  2. uWSGI

    .实现了WSGI协议的一个web服务器

    web servers and web frameworks

    .在理解uWSGI和WSGI之前,先要弄清楚web开发的两大块,web服务器和web框架。
    .web服务器即用来接受客户端请求,建立连接,转发响应的程序。至于转发的内容是什么,交由web框架来处理,即处理这些业务逻辑。如查询数据库、生成实时信息等。
    .Nginx就是一个web服务器,Django或flask就是web框架。

    uWSGI and WSGI

    .那么如何实现uWSGI和WSGI的配合呢?如何做到任意一个web服务器,都能搭配任意一个框架呢?
    这就产生了WSGI协议。只要web服务器和web框架满足WSGI协议,它们就能相互搭配。
    所以WSGI只是一个协议,一个约定。而不是python的模块、框架等具体的功能。
    .而uWSGI则是实现WSGI协议的一个web服务器。即用来接受请求,转发响应的程序。
    实际上,一个uWSGI的web服务器,再加上Django这样的框架,就已经可以实现网站功能了,那么为何还需要Nginx呢?

    Nginx is reason to

    一个普通的个人网站,访问量不大的时候,用uWSGI和Django部署是没问题的,但是一旦访问量过大,客户的请求连接就要进行长时间的等待。
    这个时候就出现了分布式服务器,也就是说我用多台服务器,这些服务器都能处理请求,但是谁来分配客户的的请求连接和web服务器呢?Nginx就是这样一个管家的存在,由他分配,这其实就是Nginx的反向代理,即代理服务器。
  3. Nginx brief

    .Nginx是俄罗斯人编写的十分轻量级的HTTP服务器,Nginx以事件驱动的方式编写,所以有非常好的性能,同时也是一个非常高效的反向代理、负载平衡。其拥有匹配Lighttpd的性能,同时还没有Lighttpd的内存泄漏问题。
    .nginx做为HTTP服务器,有以下几项基本特性:
     处理静态文件,索引文件以及自动索引;打开文件描述符缓冲.
     无缓存的反向代理加速,简单的负载均衡和容错.
     FastCGI,简单的负载均衡和容错.
     模块化的结构。包括gzipping, byte ranges, chunked responses,以及 SSI-filter等filter。如果由FastCGI或其它代理服务器处理单页中存在的多个SSI,则这项处理可以并行运行,而不需要相互等待。
     支持SSL 和 TLSSNI.
    .Nginx专为性能优化而开发,性能是其最重要的考量,实现上非常注重效率 。它支持内核Poll模型,能经受高负载的考验,有报告表明能支持高达 50,000个并发连接数。
    .Nginx具有很高的稳定性。其它HTTP服务器,当遇到访问的峰值,或者有人恶意发起慢速连接时,也很可能会导致服务器物理内存耗尽频繁交换,失去响应,只能重启服务器。例如当前apache一旦上到200个以上进程,web响应速度就明显非常缓慢了。而Nginx采取了分阶段资源分配技术,使得它的CPU与内存占用率非常低。nginx官方表示保持10,000个没有活动的连接,它只占2.5M内存,所以类似DOS这样的攻击对nginx来说基本上是毫无用处的。就稳定性而言,nginx比lighthttpd更胜一筹。
    .Nginx支持热部署。它的启动特别容易, 并且几乎可以做到7*24不间断运行,即使运行数个月也不需要重新启动。你还能够在不间断服务的情况下,对软件版本进行进行升级。
    .Nginx采用master-slave模型,能够充分利用SMP的优势,且能够减少工作进程在磁盘I/O的阻塞延迟。当采用select()/poll()调用时,还可以限制每个进程的连接数。
    .Nginx代码质量非常高,代码很规范,手法成熟, 模块扩展也很容易。特别值得一提的是强大的Upstream与Filter链。Upstream为诸如reverse proxy,与其他服务器通信模块的编写奠定了很好的基础。而Filter链最酷的部分就是各个filter不必等待前一个filter执行完毕。它可以把前一个filter的输出做为当前filter的输入,这有点像Unix的管线。这意味着,一个模块可以开始压缩从后端服务器发送过来的请求,且可以在模块接收完后端服务器的整个请求之前把压缩流转向客户端。
  4. wsgi.py

    django项目携带的一个wsgi接口文件
    如果项目名叫br_api的话,此文件就位于[br_api/br_api/wsgi.py]
  5. Relevant information

    .wsgi:一种实现python解析的通用接口标准/协议,俗称web服务网关接口
     需要搞清楚一点:wsgi不是服务器、Python模块、框架、API或者任何软件,它只是一种规范,描述web服务器与web程序通信的规范。
    .uwsgi:同wsgi一样,也是一种通信协议
     uwsgi协议是一个uWSGI服务器自有的协议,它用于定义传输信息的类型,它与wsgi相比是两样东西。
    .uWSGI:一种python web server或者可以这么称它:Server/Gatway
    uWSGI是实现了uWSGI和wsgi两种协议的Web服务器,负责相应python的web请求。
     uWSGI实现了wsgi协议、uwsgi协议、http协议

2.2 Project Process Analysis

Process

1.首先客户端向服务器发送请求,请求资源,
2.nginx作为直接对外的服务接口,接收到客户端发送过来的http请求,会解包、分析,
    如果是静态文件请求就根据配置的静态文件目录,返回请求的资源,
    如果是动态请求,nginx就通过配置文件,将请求传递给uWSGI,uWSGI将接收到包进行处理,并转发给wsgi,3.wsgi根据返回值进行打包,转发给uSWGI,
    uWSGI接收后转发给nginx,nginx最终将返回值返回给客户端(如浏览器)
*.这里需要了解一点:不同的组件之间的信息传递涉及到数据格式和协议的转换

analysis

1.首先,守在最外面的nginx并不是必须的,uwsgi完全可以完成整个与浏览器(前端)交互的流程;
2.在nginx上加上安全性或其他限制,可以达到保护程序的作用;
3.uWSGI本事是内网接口,开启多个work和processes可能都不够用,而nginx可以代理堕胎uWSGI完成uWSGI的   负载均衡;
4.django在某些情况下对静态文件的处理能力不是很好,二用nginx来处理会更加高效。

Third, the installation and configuration

3.1 base installation environment

First of all, the project is deployed on the server, the environment is centeos, linux system environment

Use xshell project to build a remote connection server environment

3.1.1 update the system software package
yum update -y
3.1.2 install software packages and management may use to rely
yum -y groupinstall "Development tools"

yum install openssl-devel bzip2-devel expat-devel gdbm-devel readline-devel sqlite-devel psmisc libffi-devel
3.1.3 Installation Python3.6.7
1)前往用户根目录cd ~
2)下载 或 上传 Python3.6.7
wget https://www.python.org/ftp/python/3.6.7/Python-3.6.7.tar.xz
3)解压安装包
tar -xf Python-3.6.7.tar.xz
4)进入目标文件
cd Python-3.6.7
5)配置安装路径
./configure --prefix=/usr/local/python3
6)编译并安装
make && sudo make install
7)建立软连接:终端命令 python3,pip3
ln -s /usr/local/python3/bin/python3 /usr/bin/python3
ln -s /usr/local/python3/bin/pip3.6 /usr/bin/pip3
8)删除安装包与文件(可选)
cd ..
rm -rf Python-3.6.7
rm -rf Python-3.6.7.tar.xz
3.1.4 source configuration pip acceleration (Ali and Tencent accelerate cloud server comes with source, do not do this step)
1)创建pip配置路径mkdir ~/.pip
2)进入目录编辑配置文件:填入下方内容
cd ~/.pip && vim pip.conf

[global]
index-url = http://pypi.douban.com/simple
[install]
use-mirrors =true
mirrors =http://pypi.douban.com/simple/
trusted-host =pypi.douban.com
3.1.5 Installing the Virtual Environment

The default working directory ~ / .virtualenvs

1)安装依赖
pip3 install virtualenv
pip3 install virtualenvwrapper

2)建立虚拟环境软连接
ln -s /usr/local/python3/bin/virtualenv /usr/bin/virtualenv

3)配置虚拟环境服务默认启动:
vim ~/.bash_profile
添加下方内容:
VIRTUALENVWRAPPER_PYTHON=/usr/bin/python3
source /usr/local/python3/bin/virtualenvwrapper.sh
4)退出保存
esc >>> :wq
5)让配置文件生效
source ~/.bash_profile

使用虚拟环境部署项目
1.先创建一个虚拟环境:
mkvirtualenv 虚拟环境名称
2.创建完毕会自动进入该虚拟环境,第二次进入方法
workon 虚拟环境名称
3.查看已经存在的虚拟环境
workon
4.推出当前虚拟环境
deactivate
3.1.6 install Mysql 5.7
1)前往用户根目录cd ~
2)下载mysql57
wget http://dev.mysql.com/get/mysql57-community-release-el7-10.noarch.rpm
3)安装mysql57
yum -y install mysql57-community-release-el7-10.noarch.rpm
yum -y install mysql-community-server
4)启动mysql57并查看启动状态
启动 systemctl start mysqld.service
状态 systemctl status mysqld.service
5)Mysql5.7在第一次启动会设置一个默认初始密码,需要查看root用户、登录并修改,然后退出,重新登录
查看 grep "password" /var/log/mysqld.log
登录 mysql -uroot -p
修改 ALTER USER 'root'@'localhost' IDENTIFIED BY 'new password';
退出 exit
6)创建项目数据库和独立用户(注意本地Django项目settings文件需要配置对应数据库名称和密码)
创建数据库 
create database '数据库名' default charset=utf8;
创建用户并授予权限(注意密码必须包含字符、数字和特殊字符)
grant 权限(create, update) on 库.表 to '账号'@'host' identified by '密码'
grant all privileges on xxx.* to 'xxx'@'%' identified by 'xxx';
grant all privileges on xxx.* to 'xxx'@'localhost' identified by 'xxx';
刷新生效
flush privileges;
非root户查看数据库只能看到授权的数据库列表,而root可以看到全部
查看用户相关信息
select user,host,authentication_string from mysql.user;
3.1.7 install Redis
1)前往用户根目录
cd ~
2)下载redis-5.0.5
wget http://download.redis.io/releases/redis-5.0.5.tar.gz
3)解压安装包
tar -xf redis-5.0.5.tar.gz
4)进入目标文件
cd redis-5.0.5
5)编译环境
make
6)复制环境到指定路径完成安装
cp -r ~/redis-5.0.5 /usr/local/redis
7)配置redis可以后台启动:修改下方内容
vim /usr/local/redis/redis.conf
daemonize yes
8)完成配置修改
esc0
:wq
9)建立软连接
ln -s /usr/local/redis/src/redis-server /usr/bin/redis-server
ln -s /usr/local/redis/src/redis-cli /usr/bin/redis-cli
10)后台运行redis
redis-server &
ctrl + c
11)测试redis环境
redis-cli
config set requirepass '12345'
ctrl + c
12)关闭redis服务
pkill -f redis -9

3.2 Installation and configuration nginx uWSGI, deploy django project

3.2.1 nginx installation
1)前往用户根目录
cd ~
2)下载nginx1.13.7
wget http://nginx.org/download/nginx-1.13.7.tar.gz
3)解压安装包
tar -xf nginx-1.13.7.tar.gz
4)进入目标文件
cd nginx-1.13.7
5)配置安装路径:/usr/local/nginx
./configure --prefix=/usr/local/nginx
6)编译并安装
make && sudo make install
7)建立软连接:终端命令 nginx
ln -s /usr/local/nginx/sbin/nginx /usr/bin/nginx
8)删除安装包与文件:(非必须)
rm -rf nginx-1.13.7
rm -rf nginx-1.13.7.tar.xz
9)测试Nginx环境,服务器运行nginx,本地访问服务器ip
nginx
服务器绑定的域名 或 ip:80

nginx operation command

1)启动
nginx
2)关闭nginx
nginx -s stop
3)重启nginx
nginx -s reload
4)查看端口,强行关闭
ps -aux|grep nginx
kill <进程编号>
查看端口占用
netstat -tunlp|grep 8000
3.2.2 uwsgi installation
1).安装(如果是虚拟环境记得在虚拟环境下再安装一遍)
pip3 install uwsgi
2).建立软连接
ln -s /usr/local/python3/bin/uwsgi /usr/bin/uwsgi
3).测试一下:
在本地新建test.py文件,写入内容
def application(env, start_response):
    start_response('200 OK', [('Content-Type','text/html')])
    return [b"Hello World"]
然后保存复制到服务器root目录
cd ~
sudo uwsgi --http 0.0.0.0:8000 --wsgi-file test.py
本地浏览器输入http://118.25.94.126:8000/ (前面是我的公网ip)
tips:
如果端口被占用,使用
lsof -i :8000
列出占用端口的程序pid号,杀掉进程再执行一遍就可以了
sudo kill -9 pid
3.2.3 Configuring nginx and uwsgi

Before configuring the required environment to meet the requirements

.python pip已安装
.django项目文件已经上传服务器,当然django已经安装完毕
.django项目所依赖的第三方模块都已经安装完毕(安装方法同与本地一样,通过pip install ***安装)
    django项目测试在项目目录下:python manage.py runserver 0.0.0.0:8000

3.2.3_1 nginx configuration

Nginx project to establish a separate configuration file

View nginx default configuration file directory (nginx.conf) path

nginx -t

Showing results Reference:

nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful

So nginx default configuration file path:

/usr/local/nginx/conf/nginx.conf

Creating nginx configuration file

.确保nginx.conf的同目录下有[uwsgi_params]文件
    使用命令cd /usr/local/nginx/conf/进行查看
.没有的话根据链接(https://github.com/nginx/nginx/blob/master/conf/uwsgi_params)获取,后面要用到。
.在自己的工程目录下(/home/project/br_api/),建立如                                       br_api.conf(/home/project/br_api/br_api.conf)的配置文件;
复制nginx.conf里面全部的内容,全部写入br_api.conf中。
然后按照下面写的,把全部写入br_api.conf配置文件中的server段部分全部替换掉。
⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇
server {
        listen 80;
        server_name 127.0.0.1;
        charset     utf-8;
        access_log      /home/project/br_api/nginx_access.log;
        error_log       /home/project/br_api/nginx_error.log;
        client_max_body_size 75M;


        location /static {
            alias /home/project/br_api/static;
        }
        location /media {
            alias /home/project/br_api/media;
        }
        location / {
            root        /home/project/br_api;
            include     /usr/local/nginx/conf/uwsgi_params;
            uwsgi_pass  127.0.0.1:8001;
        }
    }
替换内容说明:
.listen 80 代表服务器开放80端口,也就是说外界可以通过服务器ip:80端口访问到nginx服务器,这里80端口默认可以不写
.access_log与error_log 定义nginx访问日志和错误日志的存放路径,这里我把他们全部放到项目br_api项目根目录下
.location /目录名 {} 代表项目路径的引导
.location /static {} 项目的静态文件定位配置
    django静态文件的绝对路径是根据自己的实际情况来确定的,一般在自己的django项目根目录的/static目录下,或自己python manage.py collectstatic后的路径下。
    像我的是在/home/project/br_api/static下。 
.location / 指访问项目根目录时,nginx要做的事。其中需要指定 uwsgi_params文件的绝对路径,上面已经提到了;如果还有media文件之类的静态目录,仿照static的写法,自己补充。
.uwsgi_pass 指uWSGI绑定的监听地址,这里使用了9090端口,这里需要和下面的uwsgi配置文件中的socket一致

3.2.3_2 uwsgi Configuration

Uwsgi.ini project root directory create a file, writes the following

[uwsgi]
socket = 127.0.0.1:8001
chdir=/home/project/br_api
module=br_api.wsgi:application
master = true         
processes=2
threads=2
max-requests=2000
chmod-socket=664
vacuum=true
daemonize = /home/project/br_api/uwsgi.log

3.2.3_3 configuration path Overview

Project Configuration Configuration path
Project Path /home/project/br_api
The static file path /home/project/br_api/static
Project media file path /home/project/br_api/media
wsgi.py path /home/project/br_api/br_api/wsgi.py
uwsgi.ini path /home/project/br_api/uwsgi.ini
uwsgi log path /home/project/br_api/uwsgi.log
br_api.conf path /home/project/br_api/br_api.conf
uwsgi_params path /usr/local/nginx/conf/uwsgi_params
nginx access log path /home/project/br_api/nginx_access.log
nginx error log path /home/project/br_api/nginx_error.log

It can be found in almost all my projects related configuration files and log files are placed in the project directory, and to facilitate later maintenance and troubleshooting.

Fourth, start

Start uWSGI

sudo uwsgi --ini /home/project/br_api/uwsgi.ini

Start nginx

.在这之前,我们要先去nginx配置文件的根目录拷贝mime.types(/usr/local/nginx/conf/mime.types)到工程目录(/home/project/br_api/mime.types),和br_api.conf放在一起。 否则启动时会报错
.当然,如果不想拷贝mime.types文件,也可以将配置文件中“include mime.types;”一项,改成绝对路径“include /usr/local/nginx/conf/mime.types;” 
如果nginx已经开启,先关闭nginx(service nginx stop或nginx -s stop),再执行以下命令:
如果nginx已经开启,先关闭nginx(service nginx stop或nginx -s stop),再执行以下命令:
nginx -c /home/project/br_api/br_api.conf
这里的-c 表示加载配置文件启动
nginx -s reload

supplement

502 If an error occurs, view uwsgi.log module files are missing, if this is wrong, you can add an environment variable parameter in br_api / br_api / wsgi.py in:

import os, sys
sys.path.append('/home/project/br_api')
# 添加的2个环境变量,将第三方模块包所在目录添加进去
sys.path.append('/root/.virtualenvs/br_api/lib/python3.6/site-packages')


from django.core.wsgi import get_wsgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'br_api.dev')
application = get_wsgi_application()

Guess you like

Origin www.cnblogs.com/suguangti/p/11334692.html