Centos7部署django+uwsgi+nginx

Django + uwsgi + nginx on Centos7

wsgi 介绍

本小节来自 廖雪峰 wsgi 一文

一个Web应用的本质就是:

  1. 浏览器发送一个HTTP请求;
  2. 服务器收到请求,生成一个HTML文档;
  3. 服务器把HTML文档作为HTTP响应的Body发送给浏览器;
  4. 浏览器收到HTTP响应,从HTTP Body取出HTML文档并显示。

因此,一个最简单的静态网站就是一堆固定的 HTML 文档,然后用一个现成的HTTP服务器软件,接收用户请求,从文件中读取HTML,返回。Apache、Nginx、Lighttpd等这些常见的静态服务器就是干这件事情的。

但是 Django 是动态的生成 HTML 文档的,如果要动态生成HTML,就需要把上述步骤自己来实现:接受HTTP请求、解析HTTP请求、发送HTTP响应... ,为了省去这些操作,python 引入了 WSGI:Web Server Gateway Interface

WSGI接口只要求 Web 开发者实现一个函数,就可以响应HTTP请求。我们来看一个最简单的Web版本的“Hello, web!”:

def application(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/html')])  # 发送响应码和请求头
    return [b'<h1>Hello, web!</h1>']  # 发送响应的 Body

上面的application()函数就是符合WSGI标准的一个HTTP处理函数,它接收两个参数:

  • environ:一个包含所有 HTTP 请求信息的 dict 对象;
  • start_response:一个发送HTTP响应的函数。

application()函数中,调用 start_response 便可完成响应。start_response 有两个参数:一个是HTTP响应码,一个是一组 list 表示的 HTTP Header。

有了WSGI,我们关心的就是如何从environ这个dict对象拿到HTTP请求信息,然后构造HTML,通过start_response()发送Header,然后返回 Body。

整个application()函数本身没有涉及到任何解析HTTP的部分,也就是说,底层代码不需要我们自己编写,我们只负责在更高层次上考虑如何响应请求就可以了。而且 application()函数不是我们手动调用的,它必须由 WSGI服务器来调用。Python 内置了一个 WSGI服务器,这个模块叫 wsgiref,它是用纯 Python 编写的 WSGI服务器的参考实现。所谓“参考实现”是指该实现完全符合WSGI标准,但是不考虑任何运行效率,仅供开发和测试使用。

一个示例如下:

hello.py

def application(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/html')])
    body = '<h1>Hello, %s!</h1>' % (environ['PATH_INFO'][1:] or 'web')
    return [body.encode('utf-8')]

server.py

# 从wsgiref模块导入:
from wsgiref.simple_server import make_server
# 导入我们自己编写的application函数:
from hello import application

# 创建一个服务器,IP地址为空,端口是8000,处理函数是application:
httpd = make_server('', 8000, application)
print('Serving HTTP on port 8000...')
# 开始监听HTTP请求:
httpd.serve_forever()

运行 python server.py ,然后浏览器访问:localhost:8000

一些概念

WSGI:Web Server Gateway Interface,即Web服务网管接口,它是一种 Web 通信规范。

WSGI 服务器:实现了 wsgi 的服务器,可以和应用程序(如 Django)交互(Django 本身就带一个 wsgi 服务器,只不过该服务器通常仅用于开发测试,在部署项目时,要换成别的 wsgi 服务器)

WSGI Application:如 Django,flask,属于 WSGI 应用,需要配合 WSGI 服务器才能使用

uWSGI:它是一个 wsgi 服务器

nginx:Nginx是一款轻量级的Web服务器、反向代理服务器,由于它的内存占用少,启动极快,高并发能力强。它可以处理静态文件,并直接处理返回给客户端。

安装 python3.9

查看:centos7 安装 python3.9 教程

看完上面的教程后,创建虚拟环境,在虚拟环境中安装 django, uwsgi 两个库

django 设置

首先,将 django 项目放到 linux 服务器上。设置 django 项目的配置文件:/root/blog_site/blog/settings.py (这是本文项目配置文件的地址, blog_site 是项目文件夹)

修改 settings.py 中的如下三个参数:

DEBUG = False          # 关闭调试模式

ALLOWED_HOSTS = ['*']  # 允许其他主机访问连接

STATIC_ROOT = BASE_DIR / 'static'  # 添加这个变量,用来收集所有的静态资源

执行:

python manage.py collectstatic 

将项目中所有用到的静态文件,统统收集到 STATIC_ROOT 定义的文件夹中,这样,在 nginx 中配置这个目录,Nginx 就可以用来访问所有的静态资源。

Nginx 配置

nginx 安装和基础了解,查看:Nginx 简介

修改 nginx 的配置文件:

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

worker_processes  1;

events {
    worker_connections  1024;
}


http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;

    keepalive_timeout  65;
    
    upstream django {         # 定义一组名为 django 的服务器池
        server 0.0.0.0:8082;  # 使用这个地址和 uwsgi 通信
    }

    server {
        listen       80;
        server_name  ip_address;  # 这里填写你自己服务器的 ip 

        charset    utf-8;
        gzip on;
        gzip_disable "msie6";
        gzip_proxied any;
        gzip_min_length 1k;
        gzip_comp_level 4;

        access_log  logs/host.access.log;
        
        # 当用户访问 /media 和 /static 时,代表请求的是静态文件,我们可以直接给他们返回 /root/mysite/media 和 /root/blog_site/static 目录下的静态文件
        location /media  {
            alias /root/mysite/media;  # 指向 django 的 media 目录(绝对路径)
        }
        location /static  {
            alias /root/blog_site/static;  # 指向 django 的 STSTIC_ROOT 目录(绝对路径)
        }

		# 当用户访问其他 url 时,我们需要让 nignx 将请求转发给 django 服务器池,然后找到池中的服务器 0.0.0.0:8082 来进行转发。
        location / {
            uwsgi_pass django;   # 对 uWSGI 进行代理,目标是我们上面定义的 django 服务器池
            include /usr/local/nginx/conf/uwsgi_params;  # include uwsgi 的配置
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}

重新加载 ngnix 设置:

# 先进入你 nginx 安装目录的 sbin 下
./nginx -s reload

uwsgi 配置

先在 python 虚拟环境下安装 uwsgi

然后创建 /root/blog_site/uwsgi.ini: (注意这个配置文件,放到了 django 项目的根目录)

[uwsgi]
chdir = /root/blog_site  # 项目的绝对路径
module = blog.wsgi:application  # 指明 django 项目的 wsgi.py 文件路径,它包含了 application 函数,应用服务器用它与 django 代码交互
home = /root/Envs/venv  # 指明你的 python 虚拟环境的目录
processes = 5  # 指明通过uwsgi,启动多少个进程
master = True  # 配置启动管理主进程

# 使用 unix socket 与 nginx 通信;Nginx 配置中 uwsgi_pass 应指向这个 socket 文件
socket = 0.0.0.0:8082

# 在退出 uwsgi 环境后,自动清理文件
vacuum = true

当 WSGI 服务器(uWSGI、Gunicorn等)加载应用时,Django 需要导入配置模块。

Django 利用 DJANGO_SETTINGS_MODULE 环境变量来决定使用哪个 settings.py

若未设置该变量, wsgi.py 默认将其设置为 your_site.settingsyour_site 即工程名字。

你可以在 wsgi.py 中强制设置 os.environ["DJANGO_SETTINGS_MODULE"] = "mysite.settings" 来重新指定要使用的配置文件

执行命令:

cd /root/blog_site

uwsgi --ini uwsgi.ini  # 运行 uwsgi 服务器

完成,此时在浏览器访问:linux服务器的ip ,应该就能访问你的 django 网站了。

本文只能算是一个 demo,不能面向复杂的实际场景,尤其是 nginx 的配置。

可选部分

uwsgi 和 Nginx 有三种通信方式,上文中我们用的是:

# uwsgi.ini
socket = 0.0.0.0:8082

# nginx.conf
        location / {
            uwsgi_pass 0.0.0.0:8082;   # 上文中用的其实是 uwsgi_pass django; 但效果是一样的。 
            include /usr/local/nginx/conf/uwsgi_params;
        }

注意:uwsgi 服务器可以和 nginx 服务器运行在不同的机器上,只要把 IP 改成 uwsgi 服务器所在的主机就行。

其实还有其他方式来让两者通信。

两者在同一台机器上,可以用 socket 方式通讯:

# uwsgi.ini
socket=/run/uwsgi/project.sock

# nginx.conf
location / {     
    include /etc/nginx/uwsgi_params;
    uwsgi_pass unix:/run/uwsgi/project.sock;
}

两者在不同机器上,可以使用 TCP socket 通信:

# uwsgi.ini
socket=0.0.0.0:8082

# nginx.conf
location / {     
    include /etc/nginx/uwsgi_params;
    uwsgi_pass uswsgi的ip:8082;
}

两者在不同机器上,可以使用 http 通信:

# uwsgi.ini
http=0.0.0.0:8082

# nginx.conf
location / {     
    proxy_pass http://uwsgi的ip:8082;
}
posted @ 2022-04-20 22:45  wztshine  阅读(341)  评论(0编辑  收藏  举报