首页 > 技术文章 > Django项目部署:使用uwsgi和nginx的方式

cpl9412290130 2018-11-26 14:04 原文

一、背景

前两天制作的个人博客网站基本完工,大致功能具备。但是在部署环节却也处处碰壁,这里也来总结以下,以备将来不时查看以及完善。

二、前提

2.1 需要的知识

  • django
Django是一个基于python开发的web开发框架,内容丰满,功能相比于它的同行flask、webpy要健全的多,具有丰富的第三方库。
  • uWSGI
uWSGI是一个实现WSGI协议、uwsgi协议、http协议的web服务器。
这里我们要区分一下WSGI、uWSGI、uwsgi:
       WSGI:是一种通信协议;
       uwsgi:是一种线路协议而不是通信协议,在此常用于在uWSGI服务器与其他网络服务器的数据通信,属于uWSGI自有的协议;
       uWSGI:是实现了uwsgi和WSGI两种协议的Web服务器。
  • nginx
相比Apache,是具有后起之秀的高性能代理服务器。
  • wsgi.py
它是Django项目自带的一个接口文件,与uWSGI通信。

2.2 项目流程
以上每个部分都具有什么作用呢?

首先客户端发起服务资源请求;
nginx作为本项目直接对外的服务接口,会优先接收到客户端发过来的http请求,并进行分析;
若请求的资源为静态文件,那么直接根据nginx配置文件.conf中的静态文件指定地址来返回请求的资源;
若为动态请求,nginx则会通过.conf文件中配置将请求发送给uWSGI;uWSGI将接收到的包进行处理,再转发给wsgi;
wsgi则根据请求调用Django项目的某个文件或函数,处理完后,Django将返回值给wsgi;
wsgi将返回值打包返回给uWSGI;
uWSGI再将其转发给nginx,nginx最终将资源返回给客户端;

作用:

  • nginx在整个项目中其实并非必须,直接用uWSGI也是可以的,但是在部署项目时Django要将debug设置为False,这时Django对静态文件的处理不是很好,所以需要nginx来处理会更高效;
  • 除此之外,nginx上可以做一些安全上的设置,保障网站运行的安全性;
  • uWSGI本身是内网接口,开启多个work和processes的话也可能会不够用,但是nginx可以代理多个uWSGI完成uWSGI的负载均衡;

三、安装与配置

默认您已经有了Django项目,当然如果您还没有Django项目的话,可以临时通过django-admin startproject 项目名称,来创建一个临时的项目;并确保您的项目是可运行的,python manange.py runserver 0.0.0.0:8000来检验。
我用的云服务器默认安装的是root权限,普通用户权限的最好安装时加上sudo,下面不一一列出。
Step1,安装uWSGI:

针对你使用的python版本来安装,我的是python3.6:
pip3 install uwsgi 

安装完成后,测试uWSGI,在你自定义的目录下新建test.py,内容可自定义,我参考官网如下:

def application(env, start_response):
    start_response('200 OK', [('Content-Type','text/html')])
    return [b"Hello World"]

运行:

uwsgi --http :8000 --wsgi-file test.py

访问127.0.0.1:8000,运行结果,正常显示:

如果此处有提示你的端口被占用,可以换一个端口(陌生不常见的),或者通过端口查看pid,杀死占用端口的进程:

1. lsof -i :8000

然后根据pid号,用kill命令杀死进程:

kill -9 pid

然后再去执行,就应该会看到结果了。
Step2,安装nginx:

apt-get install nginx

安装完后,先不用忙着配置,可以先启动nginx看看是否安装成功,启动命令如下:

通常这三种方式,任意其一都可以使用:
1、service nginx start    # 停止对应stop,重启restart,状态查看status
2、systemctl start nginx.service    # 停止对应stop,重启restart,状态查看status
3、/etc/init.d/nginx start  停止对应stop,重启restart,状态查看status

访问127.0.0.1:80,会看到:

说明nginx也已经成功安装了。
Step3配置uWSGI:

  • 先任意找一个位置,最好和你的项目同一个位置,创建存放uwsgi配置文件的文件夹,然后再开始进行相关配置:

第一步:创建uwsgi文件夹,命令:

mkdir uwsgi

第二步:进入文件夹,命令:

cd uwsgi

第三步:创建xxx.ini文件,文件名字自定义,我用uwsgi.ini;命令:

touch uwsgi.ini

第四步:对ini文件进行参数配置,内容如下,仅供参考:

[uwsgi]
chdir=/home/work_blog                        # 项目地址
home=/root/myblog                             # 虚拟环境地址(如果你的项目部署在虚拟环境中,那么这一步是必须的,否则会报错)
module=work_blog.wsgi:application             # wsgi文件地址,不能像home和chdir那样写,这个写法官网固定,例如我这种(wsgi.py文件的父目录).wsgi:application
workers=4                                  # 子进程,也可以用processes=4这样来写
pidfile = /home/uwsgi/master.pid           # 在uwsgi文件夹下自动创建pid文件
harakiri=30                                # 30s后重启进程,值可自定义
max-requests=5000                             # 设置最大请求数
master=true                              # 开启主进程
uid=root
gid=root
thunder-lock=true
post-buffering=4096
daemonize = /home/uwsgi/myblog.log             # 在uwsgi文件夹下自动创建log日志文件
vacuum=true
enable-threads=true
socket=0:9000                             # socket通信,主要用来和nginx通信使用
chmod-socket=666

然后保存退出:wq
第五步:启动该ini配置

uwsgi --ini uwsgi.ini

这时候你去用ps -aux | grep uwsgi命令查看uwsgi,会发现有多个进程:

如果进程没启动,可能需要重载一下uwsgi目录下的pid文件,即uwsgi --reload xxx.pid,通常就可以了。
关闭这些进程,使用uwsgi --stop xxx.pid命令执行。
重启ini配置时,使用uwsgi --reload xxx.pid的命令;不要使用uwsgi --ini uwsgi.ini,因为这样会导致生成很多新的子进程,如果生成过多子进程,请使用:

killall -9 uwsgi

然后再重新加载ini配置。


注:如果遇见uwsgi有这样的错误日志的:!!!no internal routing support, rebuild with pcre support!!!
有以下解决方法推荐,我的这样解决了,不一定对你也适用,故推荐:

①centos:1、pip/pip3 uninstall uwsgi 2、yum install pcre pcre-dedvel pcre-static 3、pip/pip3 install uwsgi -I --no-cache-dir
②ubuntu:1、pip/pip3 uninstall uwsgi 2、apt-get install libpcre3-devel 3、pip/pip3 install uwsgi -I --no-cache-dir

这样做完后,重新去执行ini文件,应该就可以了。。。


Step4配置nginx:

  • nginx的配置,首先进入/ect/nginx/路径下。有的人是直接在nginx.conf文件改的,有的是在sites-available/default文件中修改的,不过我这里是在sites-available下新创建了mysite.conf文件,并在其中进行配置。
server {
    listen 80;                                                            # 设置监听端口,也即为你用外网访问你的项目的端口
    server_name www.runstone.top;                       # 你的项目域名
    charset utf-8;                                                      # 设置字符集为utf-8
    client_max_body_size 75M;                               # 最大上传大小
    location /media {                                                # 项目media路径指引
        alias /home/work_blog/media;
    }
	
    location /favicon.ico {                                        # 网站图标路径指引,该项不为必须项
	alias /home/work_blog/favicon.ico;
    }
	
    location /static {                                                  # 项目静态文件static路径指引,所有的js、css、image等资源都在这下面
        alias /home/work_blog/static_collected;
    }

    location / {
        include /etc/nginx/uwsgi_params;                # uwsgi_params文件路径,通常会在/etc/nginx下面;
        uwsgi_pass 0:9000;                                     # socket通信端口,对应于uwsgi.ini中的socket的设置
        uwsgi_connect_timeout 30;               # 可不配置
        uwsgi_read_timeout 1800;                # 可不配置
        uwsgi_send_timeout 300;                 # 可不配置
        proxy_read_timeout 300;                  # 可不配置
    }
}
  • 配置完后,要对该文件做一个软链接,ln -s /etc/nginx/sites-available/mysite.conf /etc/nginx/sites-enabled/mysite.conf。
  • 重新启动nginx,service nginx restart
  • 上述配置中没有注明nginx的log文件地址,默认的地址为:/var/log/nginx/access.log以及/var/log/nginx/error.log。当然这两个文件的路径你也可以给设置到项目路径下,在上述文件中添加:
access_log   xxx/your project/project_access.log;
error_log   xxx/your project/project_error.log;

即可。这样方便日后项目多时,日志查看与项目维护。

四、最后运行项目

经过上面配置后,还有最后一步需要做。

  • 对Django中项目目录下的settings.py中进行修改:


  • 收集静态文件:


最后最好分别重启nginx,以及加载uwsgi.ini(uwsgi --reload xxx.pid),让二者协同运行该项目,项目至此应该可以运行了。打开本地浏览器,输入你的服务器外网地址以及nginx中的监听端口,例如:http://127.0.0.1:18888;就可以看到完整的项目效果了。

部署过程中遇到错误,一定要多看日志文件来判断错误类型并解决错误。


推荐阅读