python web 服务器架构(django,flask,fastapi都可以用这个架构)
uwsgi,WSGI和uWSGI是什么,uWSGI和Nginx
背景知识
-
web服务器/http服务器
Web服务器的主要功能是存储,处理和传递网页给客户。客户端和服务器之间的通信使用超文本传输协议(HTTP)进行。交付的页面最常见的是HTML文档,除了文本内容之外,还可能包含图像,样式表和脚本。
Web服务器的基本功能就是提供Web信息浏览服务。它只需支持HTTP协议、HTML文档格式及URL。与客户端的浏览器配合。因为Web服务器主要支持的协议就是HTTP,所以通常情况下HTTP服务器和WEB服务器是相等的 -
应用服务器/应用容器
应用程序服务器提供的是客户端应用程序可以调用的方法。确切一点,你可以说:Web服务器专门处理HTTP请求(request),但是应用程序服务器是通过很多协议来为应用程序提供商业逻辑 (business logic)。
根据我们的定义,作为应用程序服务器,它通过各种协议(也可以包括HTTP),把商业逻辑暴露给(expose)客户端应用程序。Web服务器主要是处理向浏览器发送HTML以供浏览,而应用程序服务器提供访问商业逻辑的途径以供客户端应用程序使用。应用程序使用此商业逻辑就象你调用对象的一个方法(或过程语言中的一个函数)一样。
我们现在使用的应用程序框架(如django/flask等)通常就是处于应用服务器里,或者通过某个协议域应用程序服务器直接通信。
简而言之,web服务器则主要是让客户可以通过浏览器进行访问,处理HTML文件(相当于前台接待)。应用服务器处理业务逻辑(相当于业务分析员和处理员)。
- WEB服务器:Apache、IIS、Nginx(也是反向代理服务器)
- 应用服务器:Tomcat、Weblogic、Jboss
- web服务器通常比应用服务器简单
一、WSGI、uwsgi和uWSGI是什么?
python web的最简单架构如下图所示,server端会先收到用户的请求,然后会根据规范的要求调用application端:
1.WSGI
为什么需要WSGI?
Web 应用的开发通常都会涉及到 Web 框架(django, flask)的使用,各个 Web 框架内部由于实现不同相互不兼容,给用户的学习,使用和部署造成了很多麻烦。
正是有了WSGI这个规范,它约定了wsgi server 怎么调用web应用程序的代码,web 应用程序需要符合什么样的规范,只要 web 应用程序和 wsgi server 都遵守 WSGI 协议,那么,web 应用程序和 wsgi server就可以随意的组合。 比如uwsgi+django , uwsgi+flask, gunicor+django, gunicor+flask 这些的组合都可以任意组合,因为他们遵循了WSGI规范。
全称:Web Server Gateway Interface, 翻译过来就是Web服务器网关接口;WSGI是一种通信协议。WSGI 不是框架,也不是一个模块,而是介于 Web应用程序(Web框架)与 Web Server 之间交互的一种规范。
在WSGI中定义了两个角色,Web服务器端称为server或者gateway,应用程序端称为application或者framework(因为WSGI的应用程序端的规范一般都是由具体的框架来实现的)。Web Server一般指Nginx或Apache,application由Python的各种框架来实现的,如Django,Flask。
uWSGI/gunicorn等 综合型服务器
uWSGI
- uWSGI是一个快速的、自维护、对开发者和系统管理者友好的应用程序容器(应用服务器),
- 同时uWSGI也实现了uwsgi、WSGI、http等协议的Web服务器,但作为web服务器它的并发性很差,性能很差。
开发环境
开发环境下,架构搭建如下:
生产环境
如果项目要上生产环境,考虑并发等性能时,会需要uWSGI和专门的高性能web服务器(如nginx)搭配使用。这是因为uWSGI作为web服务器的性能太差,并发性很低。
这时,我们还需要在uWSGI/gunicorn与nigix之间有一个通信协议,这就是uwsgi协议。
uWSGI配置
uwsgi执行一般有两种方式:命令行和文件配置,但是命令行可能需要识记很多参数,因此采用文件配置是更通用的做法,文件格式支持很多种比如ini、xml、yaml等,推荐采用比较简单key-value形式ini模式。实际项目一般采用文件形式,文件目录如下。
uwsgi.ini配置实例:
[uwsgi]
socket = 127.0.0.1:8001
master = false
chdir = /var/www/cmpvirtmgr/
module = cmpvirtmgr.wsgi
home = /var/www/env
workers = 2
reload-mercy = 10
vacuum = true
max-requests = 1000
limit-as = 512
buffer-size = 30000
pidfile = /etc/uwsgi/uwsgi.pid
执行:uwsgi --ini /path/to/uwsgi.ini
参数解释:
socket:socket文件,也可以是地址+端口;
master:是否启动主进程来管理其他进程;
chdir:项目的根目录;
module:wsgi文件相对路径;
home:虚拟环境目录;
workers:开启的进程数量;
reload-mercy:设置在平滑的重启(直到接收到的请求处理完才重启)一个工作子进程中,等待这个工作结束的最长秒数;
vacuum:服务结束后时候删除对应的socket和pid文件;
max_requests:每个工作进程设置的请求上限;
limit_as:限制每个uwsgi进程占用的虚拟内存数目;
buffer_size:设置用于uwsgi包解析的内部缓存区大小;
pid_file:指定pid文件;
harakiri:请求的超时时间;
daemonize:进程后台执行,并保存日志到特定路径;如果uwsgi进程被supervisor管理,不能设置该参数;
uwsgi
uwsgi是一个二进制协议(线路协议),而不是通信协议,能够携带任何类型的信息,常用于在uWSGI服务器与其他网络服务器的数据通信。uwsgi数据包的前4个字节用于描述信息的类型,主要工作在TCP方式下。
uwsgi协议是一个uWSGI服务器自有的协议,它用于定义传输信息的类型(type of information),每一个uwsgi packet前4byte为传输信息类型描述,它与WSGI相比是两样东西。
二、Nginx和uWSGI
如果项目要上生产环境,考虑并发等性能时,会需要uwsgi和nginx搭配使用。
nginx 是一个开源的高性能的 HTTP 服务器和反向代理:
作为 web 服务器,它处理静态文件和索引文件效果非常高;
它的设计非常注重效率,最大支持 5 万个并发连接,但只占用很少的内存空间;
稳定性高,配置简洁;
强大的反向代理和负载均衡功能,平衡集群中各个服务器的负载压力应用
项目访问流程如下:
- 首先浏览器发起 http 请求到 nginx 服务器,Nginx 根据接收到请求包,进行 url 分析,判断访问的 资源类型,
- 如果是静态资源,直接读取静态资源返回给浏览器,
- 如果请求的是动态资源就转交给 uWSGI 服务器,uWSGI服务器根据自身的 uwsgi 和 WSGI协议,找到对应的 Django(flask等) 框架,Django 框架下的 应用进行逻辑处理后,将返回值发送到 uwsgi 服务器,然后 uwsgi 服务器再返回给 nginx,最后 nginx 将返回值返回给浏览器进行渲染显示给用户。