WSGI/uwsgi/uWSGI
在 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投入生产的方法.
安装 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。
envvars
和magic
里面设置了一些环境变量相关的东西,没怎么看过。
剩下的6个目录两两一对,
available
文件夹里面是所有的配置,而enabled
目录里面则是启用的配置。
而conf
、mods
和sites
可以分别通过命令a2enconf
、a2enmod
、a2ensite
来启用,启用后会在enabled
目录下生成一个软链接,指向available
目录下的同名文件。
在apache2.conf
这个文件最后,是一些IncludeOptional
语句,用来将conf-enabled
、mods-enabled
、sites-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
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.conf
, mpm_worker.conf
和 mpm_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
每个窗口可以排队的人数.
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