Python3 基于 Nginx 部署 Django 项目
Python3 基于 Nginx 部署 Django 项目
参考链接:https://blog.csdn.net/yilovexing/article/details/82969103
一、工作原理
Django 的部署可以有很多方式,采用 nginx + uwsgi 的方式是其中比较常见的一种方式。
在这种方式中,我们的通常做法是,将 nginx 作为服务器最前端,它将接收 web 的所有请求,统一管理请求。nginx 把所有静态请求自己来处理(这是 nginx 的强项)。然后,nginx 将所有非静态请求通过 uwsgi 传递给 Django,由 Django 来进行处理,从而完成一次 web 请求。
可见,uwsgi 的作用就类似一个桥接器,起到桥梁的作用。
Linux 的强项是用来做服务器,所以,下面的整个部署过程我们选择在 Ubuntu 16.04 下完成。
技术扩展:
WSGI 是 Web Server Gateway Interface 的缩写。以层的角度来看,WSGI 所在层的位置低于 CGI。但与 CGI 不同的是 WSGI 具有很强的伸缩性且能运行于多线程或多进程的环境下,这是因为 WSGI 只是一份标准并没有定义如何去实现。实际上 WSGI 并非 CGI,因为其位于 web 应用程序与 web 服务器之间,而 web 服务器可以是 CGI。可以理解为是 Python 内置的一个测试 web 服务器。
uWSGI 是一个Web服务器,它实现了 WSGI 协议、uwsgi、http 等协议。Nginx 中HttpUwsgiModule 的作用是与 uWSGI 服务器进行交换。WSGI 是一种 Web 服务器网关接口。比如把 HTTP 协议转化成 WSGI 协议,让 Python 可以直接使用。
二、项目环境
操作系统: Ubuntu 18
编程语言: Python 3.5.2
Web 框架: Django 2.0.3
Web 服务器: uWSGI 2.0.17
Web 服务器: Nginx 1.10.3
具体的安装这里不做详述,Ubuntu 使用 apt-get 安装特别方便。
sudo apt-get install python3
sudo apt-get install python3-pip
sudo apt-get install nginx
三、uWSGI 安装配置
安装
sudo pip3 install uwsgi
测试
创建 test.py 文件
#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
def application(env, start_response):
start_response('200 OK', [('Content-Type','text/html')])
return [b'Hello World']
通过 uWSGI 运行该文件
uwsgi --http :8000 --wsgi-file test.py
在浏览器中输入 127.0.0.1:8000,出现 “Hello World”表示安装成功。
四、Django 与 uWSGI 之间的通信
4.1 安装 Django
sudo pip3 install Django==2.0.3
4.2 创建 Django 项目
django-admin startproject web_say_hello
4.3 创建app
python3 manage.py startapp hello_app
4.4 一个小样例
4.4.1 向template中添加hello_main.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello</title>
</head>
<body>
hello
</body>
</html>
4.4.2 向 hello_app中的views中添加
from django.shortcuts import render
# Create your views here.
def hello_main(request):
return render(request, "hello_main.html")
4.4.3 向web_say_hello的settings.py中修改
ALLOWED_HOSTS = ['*']
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'hello_app.apps.HelloAppConfig',
]
4.4.5 向web_say_hello的url.py中添加一行导航
urlpatterns = [
path("", hello_app.views.hello_main),
path('admin/', admin.site.urls),
]
4.5 使用uwsgi启动网站
我的 Django 项目位置为:/root/web_say_hello
使用以下命令启动网站,然后就可以在8000端口看到hello了。
uwsgi --http :8000 --chdir /root/web_say_hello/ --wsgi-file web_say_hello/wsgi.py --master --processes 4 --threads 2
常用选项
http: 协议类型和端口号
processes: 开启的进程数量
workers: 开启的进程数量,等同于 processes
chdir: 指定运行目录
wsgi-file: 载入 wsgi-file
stats: 在指定的地址上,开启状态服务
threads: 运行线程。由于 GIL 的存在,我觉得这个真心没啥用。
master: 允许主进程存在
daemonize: 使进程在后台运行,并将日志打到指定的日志文件或者 udp 服务器(daemonize uWSGI)。实际上最常用的,还是把运行记录输出到一个本地文件上。
pidfile: 指定pid文件的位置,记录主进程的pid号。
vacuum: 当服务器退出的时候自动清理环境,删除 unix socket 文件和 pid 文件
当然了一般不用命令启动
五、Nginx、uWSGI、Django 之间的通信
接下来,我们要将三者结合起来
5.1 配置 Django 和 uWSGI
先在 Django 项目根目录下新建一个 uWSGI 的配置文件 uwsgi.ini
touch uwsgi.ini
此时 Django 项目的目录文件结构如下:
web_say_hello/
├── db.sqlite3
├── hello_app
│ ├── admin.py
│ ├── apps.py
│ ├── __init__.py
│ ├── migrations
│ │ ├── __init__.py
│ │ └── __pycache__
│ │ ├── __init__.cpython-36.pyc
│ │ └── __init__.cpython-38.pyc
│ ├── models.py
│ ├── __pycache__
│ │ ├── admin.cpython-36.pyc
│ │ ├── admin.cpython-38.pyc
│ │ ├── apps.cpython-36.pyc
│ │ ├── apps.cpython-38.pyc
│ │ ├── __init__.cpython-36.pyc
│ │ ├── __init__.cpython-38.pyc
│ │ ├── models.cpython-36.pyc
│ │ ├── models.cpython-38.pyc
│ │ ├── views.cpython-36.pyc
│ │ └── views.cpython-38.pyc
│ ├── tests.py
│ └── views.py
├── manage.py
├── run.sh
├── templates
│ └── hello_main.html
├── uwsgi.ini
└── web_say_hello
├── asgi.py
├── __init__.py
├── __pycache__
│ ├── __init__.cpython-36.pyc
│ ├── __init__.cpython-38.pyc
│ ├── settings.cpython-36.pyc
│ ├── settings.cpython-38.pyc
│ ├── urls.cpython-36.pyc
│ ├── urls.cpython-38.pyc
│ ├── wsgi.cpython-36.pyc
│ └── wsgi.cpython-38.pyc
├── settings.py
├── urls.py
└── wsgi.py
7 directories, 37 files
在我们通过 Django 创建 myweb 项目时,在子目录 myweb 下已经帮我们生成的 wsgi.py文件。所以,我们只需要再创建 uwsgi.ini 配置文件即可。
uwsgi 支持多种类型的配置文件,如 xml、ini 等。此处,使用 ini 类型的配置。
接下来打开刚刚创建好的配置文件 uwsgi.ini 添加如下配置:
[uwsgi]
socket = :8000
chdir = /root/web_say_hello
module = web_say_hello.wsgi
master = true
processes = 2
vacuum = true
这个配置,其实就相当于在上一小节中通过 wsgi 命令,后面跟一堆参数的方式,给文件化了。
socket: 指定项目执行的端口号。
chdir: 指定项目的目录。
module: wsgi.py 文件。
其它几个参数,可以参考上一小节中参数的介绍。
由于是配置的socket,uwsgi被配置成使用socket方式(为tcp协议)进行通信。如果打开浏览器访问uwsgi指定的端口,那么浏览器请求uwsgi的方式为http协议,而不是socket方式。就会导致以下错误信息:
invalid request block size: 21573 (max 4096)...skip
invalid request block size: 21573 (max 4096)...skip
如果希望通过 uwsgi 命令读取 uwsgi.ini 文件启动项目
需要先将
socket = :8000
修改为:
http :8000
然后使用命令启动
uwsgi --ini uwsgi.ini
这样启动会有一个会话不能关,另一种启动方法:
uwsgi -d /root/web_say_hello/uwsgi.pid /root/web_say_hello/uwsgi.ini
停止命令:
sudo pkill -f uwsgi -9
记得把http改回来啊,我们接下来要用nginx通过socket访问了
5.2 配置 Nginx
Nginx 默认的配置文件都在 /etc/nginx 目录下
nginx 文件结构
... #全局块
events { #events块
...
}
http #http块
{
... #http全局块
server #server块
{
... #server全局块
location [PATTERN] #location块
{
...
}
location [PATTERN]
{
...
}
}
server
{
...
}
... #http全局块
}
1、全局块:配置影响nginx全局的指令。一般有运行nginx服务器的用户组,nginx进程pid存放路径,日志存放路径,配置文件引入,允许生成worker process数等。
2、events块:配置影响nginx服务器或与用户的网络连接。有每个进程的最大连接数,选取哪种事件驱动模型处理连接请求,是否允许同时接受多个网路连接,开启多个网络连接序列化等。
3、http块:可以嵌套多个server,配置代理,缓存,日志定义等绝大多数功能和第三方模块的配置。如文件引入,mime-type定义,日志自定义,是否使用sendfile传输文件,连接超时时间,单连接请求数等。
4、server块:配置虚拟主机的相关参数,一个http中可以有多个server。
5、location块:配置请求的路由,以及各种页面的处理情况。
默认的nginx.conf中有一句:
include /etc/nginx/conf.d/*.conf;
所以我们的django网站的配置文件放到conf.d目录中即可。
如web_say_hello.conf:
upstream django
{
# server unix:///path/to/your/mysite/mysite.sock; # for a file socket
server 127.0.0.1:8000; # for a web port socket (we'll use this first)
}
# configuration of the server
server
{
# the port your site will be served on
listen 80;
# the domain name it will serve for
server_name your_server_ip domain_name; # substitute your machine's IP address or FQDN
charset utf-8;
# max upload size
client_max_body_size 75M; # adjust to taste
location /static
{
alias /root/web_say_hello/static; # 指向django的static目录
}
# Finally, send all non-media requests to the Django server.
location /
{
uwsgi_pass django;
include uwsgi_params; # the uwsgi_params file you installed
}
}
说明
listen: 指定的是 nginx 代理 uwsgi 对外的端口号。
server_name: 服务器的ip和域名(如果有域名的话)
include uwsgi_params; #include 必须指定为 uwsgi_params。
uwsgi_pass 127.0.0.1:8000; #uwsgi_pass 指的是本机 IP 和端口号,并且要与 uwsgi.ini 配置文件中的 IP 和端口号必须保持一致。
由于这里我设置了一个upstream名字叫django。
所以就写成了 uwsgi_pass django;
现在重新启动 nginx
sudo service nginx restart
然后浏览器访问 服务器的ip或域名或你在本地搭建的访问127.0.0.1
至此结束