WSGI/uwsgi/uWSGI

Web 开发的重要概念辨析:CGI、WSGI、uWSGI、ASGI

在 Python Web 开发中,经常使用 Uwsgi 配合 Nginx 部署一个 Web 框架,如 Django 或 flask。同时又会说,框架和 Web 服务器之间要符合 WSGI 协议。

Web 服务器和 Web框架

Web 开发的两大块,Web服务器和Web框架。

Web服务器即用来接受客户端请求,建立连接,转发响应的程序。至于转发的内容是什么,交由Web框架来处理,即处理这些业务逻辑。如查询数据库、生成实时信息等。Nginx就是一个Web服务器,Django或flask就是Web框架。

如何实现uWSGI和WSGI的配合?如何做到任意一个Web服务器,都能搭配任意一个框架呢?这就产生了WSGI协议.

只要Web服务器和Web框架满足WSGI协议,它们就能相互搭配。所以WSGI只是一个协议,一个约定。而不是Python的模块、框架等具体的功能。

而uWSGI,则是实现了WSGI协议的一个Web服务器。即用来接受客户端请求,转发响应的程序。实际上,一个uWSGI的Web服务器,再加上Django这样的Web框架,就已经可以实现网站的功能了

WSGI

WSGI,(WEB SERVER GATEWAY INTERFACE),Web服务器网关接口,是一种Web服务器网关接口,它是一个Web服务器(如Nginx,uWSGI等服务器)与Web应用(如Flask框架写的程序)通信的一种规范。当前运行在WSGI协议之上的Web框架有Bottle,Flask,Django

实现了Python Web程序与服务器之间交互的通用性。有了这个东西,web.py或者bottle或者django等等的Python Web开发框架,就可以轻松地部署在不同的Web server上了.

WSGI协议其实是定义了一种server与application解耦的规范,即可以有多个实现WSGI server的服务器,也可以有多个实现WSGI application的框架,那么就可以选择任意的server和application组合实现自己的Web应用。

例如 uWSGI和 Gunicorn都是实现了WSGI server协议的服务器,Django,Flask是实现了WSGI application协议的Web框架,可以根据项目实际情况搭配使用。

像Django,Flask框架都有自己实现的简单的WSGI server,一般用于服务器调试,生产环境下建议用其他WSGI server,WSGI服务器的选择很多,包括uWSGI和gunicorn.

uwsgi

同WSGI一样是一种通信协议.

uwsgi协议是一个uWSGI服务器自有的协议,它用于定义传输信息的类型(type of information),每一个uwsgi packet前4byte为传输信息类型描述,它与WSGI相比是两样东西。

uWSGI (服务器)

它是一个Web服务器,它实现了WSGI协议、uwsgi、http等协议。用于接收前端服务器转发的动态请求并处理后发给 Web 应用程序。

因为apache也好,Nginx也罢,它们自己都没有解析动态语言如php的功能,而是分派给其他模块来做,比如apache就可以说内置了php模块,支持的非常爽,让人感觉好像apache就支持php一样。uwsgi实现了WSGI协议、uwsgi、http等协议。Nginx中HttpUwsgiModule的作用是与uWSGI服务器进行交换。

uWSGI是使用C编写的,显示了自有的uwsgi协议的Web服务器。它自带丰富的组件,其中核心组件包含进程管理、监控、IPC等功能,实现应用服务器接口的请求插件支持多种语言和平台,比如WSGI、Rack、Lua WSAPI,网管组件实现了负载均衡、代理和理由功能

uWSGI也可以当做中间件。

  • 如果是Nginx+uWSGI+App,那uWSGI就是一个中间件
  • 如果是uWSGI+App,那它就是服务器

Nginx+uWGSI

假设使用 Python 的 Django 框架写了一个网站,现在要将它挂在网上运行,一般需要:

  • Nginx 做为代理服务器:负责静态资源发送(js、css、图片等)、动态请求转发以及结果的回复。
  • uWSGI 做为后端服务器:负责接收 Nginx 转发的请求并处理后发给 Django 应用以及接收 Django 应用返回信息转发给 Nginx。
  • Django 应用收到请求后处理数据并渲染相应的返回页面给 uWSGI 服务器。

一个Django应用,通过WSGI协议连接uWSGI服务器,uWSGI服务器实现WSGI、http等协议,通过uwsgi协议和Nginx服务器实现http的动态请求和转发以及结果.

问题:有uWGSI了,Django为什么还需要 Nginx?

一个普通的个人网站,访问量不大的话,当然可以由 uWSGI 和 Django 构成。但是一旦访问量过大,客户端请求连接就要进行长时间的等待。这个时候就出来了分布式服务器,可以多来几台 Web 服务器,都能处理请求。

但是谁来分配客户端的请求连接和 Web 服务器呢?Nginx 就是这样一个管家的存在,由它来分配。这也就是由 Nginx 实现反向代理,即代理服务器。

Nginx 是一个 HTTP 和反向代理服务器

  • 正向代理:正向的就是由浏览器主动的想代理服务器发出请求,经代理服务器做出处理后再转给目标服务器
  • 反向代理:反向的就是不管浏览器同不同意,请求都会经过代理服务器处理再发给目标服务器

使用Nginx作为反向代理服务器的好处:

  • 安全

不管什么请求都要经过代理服务器,可以避免外部程序直接攻击Web服务器

  • 负载均衡

根据请求情况和服务器负载情况,将请求分配给不同的Web服务器,保证服务器性能

  • 提高Web服务器的IO性能

请求从客户端传到Web服务器是需要时间的,传递多长时间就会让这个进程阻塞多长时间,而通过反向代理,就可以由反向代理完整接受该请求,然后再传给Web服务器,从而保证服务器性能,而且有的一些简单的事情(比如静态文件)可以直接由反向代理处理,不经过Web服务器

apache2 部署 Django 应用

Django 测试环境一般采用 python3 manage.py runserver 来运行服务器.

正式发布的服务,需要一个可以稳定而持续的服务器,比如Apache, Nginx等.

使用Apache和mod_wsgi部署Django 是一种久经考验的将Django投入生产的方法.

如何使用 Apache 和 mod_wsgi 托管 Django

在Apache上部署Django项目

Django部署(Apache)

安装 Django 及相关包

pip3 install django==3.2.7
pip3 install celery==4.4.7
pip3 install redis==3.5.3

安装apache2及相关包

sudo apt-get install apache2

#apache2解析python的包 wsgi程序包
sudo apt-get install libapache2-mod-wsgi-py3
#安装完成后 进入 /usr/lib/apache2/modules 目录
#cd /usr/lib/apache2/modules
#查看是否存在mod_wsgi.so-3.x

sudo apt-get install php5 libapache2-mod-php5
sudo apt-get install libapache2-mod-perl2

sudo a2enmod include
sudo a2enmod rewrite
#sudo a2enmod cgi
sudo a2enmod wsgi # 启用wgsi配置
sudo service apache2 reload
sudo service apache2 restart
#sudo systemctl restart apache2.service

1、CGI是一种为用户动态提供所需数据的设计思想,它有很多各种不同语言的实现。
2、WSGI是Python对CGI进行的一种包装,核心使用Python实现,具体实现通常来说也需要使用Python,目前Django、Google webapp框架都实现了WSGI

apache2 配置文件路径 /etc/apache2/.

apache2 文件目录结构

Apache2 的配置文件目录是/etc/apache2,该目录下的文件结构如下:

.
|-- apache2.conf
|-- conf-available
|-- conf-enabled
|-- envvars
|-- magic
|-- mods-available
|-- mods-enabled
|-- ports.conf
|-- sites-available
|-- sites-enabled

其中,

apache2.conf是主配置文件,里面包括系统的设置,如Timeout的时长、Log的等级和格式等。

ports.conf文件配置了监听的端口号,以及是否启用SSL。

envvarsmagic里面设置了一些环境变量相关的东西,没怎么看过。

剩下的6个目录两两一对,

available文件夹里面是所有的配置,而enabled目录里面则是启用的配置。

confmodssites可以分别通过命令a2enconfa2enmoda2ensite来启用,启用后会在enabled目录下生成一个软链接,指向available目录下的同名文件。

apache2.conf这个文件最后,是一些IncludeOptional 语句,用来将conf-enabledmods-enabledsites-enabled目录下的配置文件包含到主配置文件中。这样的好处是每个配置文件配置一个条目,比较清晰明了,易于查错。

配置网站

[1] - 新建配置文件,如:

sudo vim /etc/apache2/sites-available/proxy.conf

内容如:

WSGIScriptAlias /demo-proxy /worker/demo-proxy/mysite/wsgi.py
WSGIPythonPath /worker/demo-proxy

<Directory /worker/demo-proxy/mysite>
<Files wsgi.py>
Require all granted
</Files>
</Directory> 
sudo vim /etc/apache2/sites-enable/proxy.conf

内容如:

WSGIScriptAlias /demo-proxy /worker/demo-proxy/mysite/wsgi.py #关联 apache2 和 django
WSGIPythonPath /worker/demo-proxy

<Directory /worker/demo-proxy/mysite>
<Files wsgi.py>
Require all granted
</Files>
</Directory> 

生效配置:

 sudo a2ensite proxy.conf

修改wsgi.py文件

"""
WSGI config for mysite project.

It exposes the WSGI callable as a module-level variable named ``application``.

For more information on this file, see
https://docs.djangoproject.com/en/1.9/howto/deployment/wsgi/
"""

import os

from django.core.wsgi import get_wsgi_application

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")

application = get_wsgi_application()

激活新网站

sudo a2ensite proxy 或 sudo a2ensite proxy.conf

https://code.ziqiangxuetang.com/django/django-deploy.html

apache2 日志

路径:

/var/log/apache2
/var/log/apache2/access.log
/var/log/apache2/error.log

查看 apache 进程

ps aux | grep apache
ps aux | grep apache | wc -l #查看进程数
ps -eLf | grep apache | wc -l #查看线程数

apache2 MPM模式

apache2 服务器的性能,在很大程度上取决于参数配置.

不同模式对应的配置文件在/etc/apache2/mods-available/下,有mpm_prefork.confmpm_worker.confmpm_event.conf.

MPM(Multi -Processing Modules,多道处理模块)

apachectl -V | grep -i mpm

cat /etc/apache2/mods-available/mpm_event.conf
'''
<IfModule mpm_event_module>
        StartServers              2
        MinSpareThreads          25
        MaxSpareThreads          75
        ThreadLimit              64
        ThreadsPerChild          25
        MaxRequestWorkers       150  #最大并发进程数
        MaxConnectionsPerChild   0   #最大连接数限制
</IfModule>
'''

理解,就像食堂窗口打饭,其中 MaxRequestWorkers 是总共有多少个窗口,MaxConnectionsPerChild 每个窗口可以排队的人数.

Apache优化:修改最大并发连接数

Apache2 跨域配置

sudo a2enmod headers

sudo vim /etc/apache2/sites-available/000-default.conf
#编辑添加:
#    LoadModule headers_module modules/mod_headers.so
#    Header set Access-Control-Allow-Origin *

sudo service apache2 restart
Last modification:September 16th, 2022 at 06:57 pm