Django+uWSGI+Nginx的生产环境部署

时间:2022-12-21 08:08:53

环境

  1. Django 1.11
  2. CentOS 7.2
  3. Python 2.7.11

使用runserver可以使我们的django项目很便捷的在本地运行起来,但这只能在局域网内访问,如果在生产环境部署django,就要多考虑一些问题了。比如静态文件处理,安全,效率等等,本篇文章总结归纳了一下基于uwsgi+Nginx下django项目生产环境的部署

经测试,网上大部分教程在Django1.11的情况下,使用uwsgi进行反向代理,django应用无法正常运行,故对现有资料整理后,整理出django1.11通过uWSGI的方式启动,提供动静分离的访问方式。

一、安装依赖包

yum install python-pip -y
yum install python-devel
pip install django
pip install uwsgi

注意:直接使用pip 命令安装uwsgi可能会导致失败。按照官方文档,可使用解决

pip install https://projects.unbit.it/downloads/uwsgi-lts.tar.gz

这样大体的流程是:nginx作为服务器最前端,负责接收client的所有请求,统一管理。静态请求由Nginx自己处理。非静态请求通过uwsgi传递给Django,由Django来进行处理,从而完成一次WEB请求。
通信原理是:

the web client <-> the web server(nginx) <-> the socket <-> uwsgi <-> Django

二、 测试uwsgi

在linux上创建一个Django项目,这个不详述。可详见django官方文档。该测试文档目录结构如下:

[root@localhost djangoproject]# tree
.
├── db.sqlite3
├── djangoproject
│ ├── __init__.py
│ ├── __init__.pyc
│ ├── settings.py
│ ├── settings.pyc
│ ├── urls.py
│ ├── urls.pyc
│ ├── wsgi.py
│ └── wsgi.pyc
├── manage.py
├── nohup.out
├── test.py
└── uwsgi.ini

完成后,执行shell命令。

uwsgi --http :8000 --wsgi-file djangoproject/wsgi.py

报错信息1:

uwsgi: option '--http' is ambiguous; possibilities: '--http-socket' '--https-socket-modifier2' '--https-socket-modifier1' '--https-socket' '--http-socket-modifier2' '--http-socket-modifier1'
getopt_long() error

参考文档将启动参数改为:

uwsgi --http-socket :8000 --plugin python --wsgi-file djangoproject/wsgi.py

报错信息2:

uwsgi --http-socket :8000 --module djangoproject.wsgi
uwsgi: unrecognized option '--wsgi-file'
getopt_long() error

此处应加上–plugin python是告诉uWSGI在使用python插件。但加上参数执行时,会报错。需要通过yum安装uwsgi-plugin-python插件,否则uwsgi无法调用python

yum install uwsgi-plugin-python -y

再次运行uwsgi

uwsgi --http-socket :8001 --plugin python --module djangoproject.wsgi

正确输出如下:

nodename: hostname
machine: x86_64
clock source: unix
pcre jit disabled
detected number of CPU cores: 2
current working directory: /data/django_uwsgi
detected binary path: /usr/sbin/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 processes number limit is 31858
your memory page size is 4096 bytes
detected max file descriptor number: 484946
lock engine: pthread robust mutexes
thunder lock: disabled (you can enable it with --thunder-lock)
uwsgi socket 0 bound to TCP address :8001 fd 3
Python version: 2.7.5 (default, Nov 6 2016, 00:28:07) [GCC 4.8.5 20150623 (Red Hat 4.8.5-11)]
*** Python threads support is disabled. You can enable it with --enable-threads ***
Python main interpreter initialized at 0x1dcd910
your server socket listen backlog is limited to 100 connections
your mercy for graceful operations on workers is 60 seconds
mapped 72768 bytes (71 KB) for 1 cores
*** Operational MODE: single process ***
WSGI app 0 (mountpoint='') ready in 0 seconds on interpreter 0x1dcd910 pid: 26832 (default app)
*** uWSGI is running in multiple interpreter mode ***
spawned uWSGI worker 1 (and the only) (pid: 26832, cores: 1)

打开http,可以看到django已经被启动

三、 配置uwsgi

uwsgi支持通过配置文件的方式启动,可以接受更多的参数,高度可定制。我们在Django项目目录下新建uwsgi.ini

touch uwsgi.ini

[uwsgi]
# uwsgi监听以socket模式启动
http-socket = /data/djangoproject/app.sock
# django项目的根目录
chdir = /data/djangoproject/
module = djangoproject.wsgi
# django项目中 wsgi.py 文件所在地址
wsgi-file = djangoproject/wsgi.py
plugin = python
#工作进程数量
processes = 4
threads = 2
buffer-size = 65535
daemonize = /data/djangoproject/uwsgi.log

在shell中执行:

uwsgi --ini uwsgi.ini

注,该启动方式为前台启动,需要添加nohup参数后台启动,正确输出如下:

[uWSGI] getting INI configuration from uwsgi.ini
*** Starting uWSGI 2.0.15 (64bit) on [Wed Sep 6 22:31:33 2017] ***
compiled with version: 4.8.5 20150623 (Red Hat 4.8.5-11) on 19 May 2017 14:33:49
os: Linux-3.10.0-514.26.2.el7.x86_64 #1 SMP Tue Jul 4 15:04:05 UTC 2017
nodename: d-awscn-paas-devops-01
machine: x86_64
clock source: unix
pcre jit disabled
detected number of CPU cores: 2
current working directory: /data/djangoproject
detected binary path: /usr/sbin/uwsgi


uWSGI running as root, you can use --uid/--gid/--chroot options
*** WARNING: you are running uWSGI as root !!! (use the --uid flag) ***
chdir() to /data/djangoproject
your processes number limit is 31858
your memory page size is 4096 bytes
detected max file descriptor number: 484946
lock engine: pthread robust mutexes
thunder lock: disabled (you can enable it with --thunder-lock)
uwsgi socket 0 bound to TCP address :8001 fd 3
Python version: 2.7.5 (default, Nov 6 2016, 00:28:07) [GCC 4.8.5 20150623 (Red Hat 4.8.5-11)]
*** Python threads support is disabled. You can enable it with --enable-threads ***
Python main interpreter initialized at 0xeda930
your server socket listen backlog is limited to 100 connections
your mercy for graceful operations on workers is 60 seconds
mapped 363840 bytes (355 KB) for 4 cores
*** Operational MODE: preforking ***
WSGI app 0 (mountpoint='') ready in 1 seconds on interpreter 0xeda930 pid: 26885 (default app)
mountpoint already configured. skip.
*** uWSGI is running in multiple interpreter mode ***
spawned uWSGI master process (pid: 26885)
spawned uWSGI worker 1 (pid: 26886, cores: 1)
spawned uWSGI worker 2 (pid: 26887, cores: 1)
spawned uWSGI worker 3 (pid: 26888, cores: 1)
spawned uWSGI worker 4 (pid: 26889, cores: 1)
^CSIGINT/SIGQUIT received...killing workers...

四、配置Nginx

配置nginx的时候,用uwsgi模块没有代理成功,最终通过反向代理的方式解决
django.conf

upstream django_jquery {
server unix:/data/djangoproject/app.sock fail_timeout=0;
}

server{
listen 80;
# 访问你django项目所需要的域名 多个域名可以用【空格】分开
server_name ip address or domain;
charset utf-8;
client_max_body_size 50M;
#django 静态文件映射
location /static/ {
#指向我们django目录中的static文件夹
root /data/djangoproject/static/;
}

#django映射
location / {
proxy_pass http://djangoproject;
proxy_http_version 1.1;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_buffers 8 32k;
proxy_buffer_size 64k;

}
}

五、收集Django静态文件

把Django自带的静态文件收集到同一个static中,不然访问Django的admin页面会找不到静态文件。在django的setting文件中,添加下面一行内容:

STATIC_PATH = os.path.join(BASE_DIR, 'static')
STATIC_URL = '/static/'
STATICFILES_DIRS = (
STATIC_PATH,
)

到此,django程序被正常启动。