站内链接:

1. WSGI

网关接口

网关接口是指在不同系统或网络之间进行通信和交互时所使用的接口或协议。它类似于两个相邻领域之间的门户,起到了连接和中转的作用。

想象一下,你正在家里使用 Wi-Fi 网络浏览互联网,但是你想访问公司内部的文件和资源。由于公司内部网络与你所在的家庭网络是隔离的,直接访问是不可能的。这时,公司可能会设置一个网关接口,作为内外网络之间的桥梁。

你的请求首先到达家庭网络的网关接口,然后通过网关接口转发到公司网络。网关接口将请求转发给公司网络中的相应资源,并将响应传回给你的家庭网络,最终你的设备接收到了所需的文件或资源。

网关接口实际上是两个不同网络之间的中间层,它处理不同网络之间的协议转换、数据传输和安全验证等工作。通过网关接口,不同系统或网络能够互相交流和访问彼此的资源,实现了信息的传递和共享。

类似于这个例子,网关接口在计算机网络、物联网、云计算等领域都有广泛的应用。它提供了一种统一的接口和协议,使得不同系统或网络能够互相连接和通信,实现了数据的传输、共享和管理。

SGI

SGI(Server Gateway Interface)是一种服务器网关接口,类似于 WSGI(Web Server Gateway Interface)和 ASGI(Asynchronous Server Gateway Interface)。SGI 定义了服务器和应用程序之间通信的接口规范,它提供了一种标准化的方式来连接服务器和应用程序,以实现请求和响应的传递。SGI 的组成要素包括:

  1. 服务器:SGI 依赖于特定的服务器实现,服务器负责接收客户端请求并将其转发给应用程序。服务器可以是常见的 Web 服务器,如 Apache、Nginx 等,也可以是其他类型的服务器(见 nginx 配置文章中的说明)。

  2. 应用程序:应用程序是服务器上运行的具体业务逻辑,它接收来自服务器的请求并生成响应。应用程序可以是基于特定框架开发的 Web 应用,也可以是其他类型的应用。

  3. SGI 接口:SGI 定义了服务器和应用程序之间的接口规范,包括请求对象、响应对象、环境变量等。通过遵循 SGI 接口规范,应用程序能够与服务器进行交互,处理请求并生成响应。

  4. 中间件:SGI 中的中间件组件用于对请求和响应进行处理和转换。中间件可以在请求到达应用程序之前对其进行预处理,也可以在应用程序生成响应后对其进行后处理。中间件可以实现日志记录、身份验证、缓存等功能。

  5. 扩展:SGI 支持扩展功能,允许开发人员通过添加自定义组件来增强服务器和应用程序的功能。这些扩展可以是第三方库、插件或自定义模块,用于处理特定的请求和响应需求。

总而言之,SGI 是一种服务器网关接口,它由服务器、应用程序、SGI 接口、中间件和扩展等要素组成。它提供了一种标准化的通信方式,使得服务器和应用程序能够互相交互和传递请求与响应。

WSGI

WSGI(Web Server Gateway Interface)是 Python Web 应用程序与 Web 服务器之间的标准接口规范。它定义了服务器和应用程序之间通信的约定和要素。以下是 WSGI 的主要要素:

  1. 应用程序(Application):应用程序是一个 Python 可调用对象,可以是函数、方法或实现了__call__方法的类。它接收两个参数:environstart_response,并生成响应内容。应用程序负责处理请求并生成响应。

  2. 服务器(Server):服务器负责接收客户端的请求,并将请求传递给应用程序进行处理。它可以是常见的 Web 服务器,如 Apache、Nginx 等,也可以是专门为 WSGI 而设计的服务器,如 Gunicorn、uWSGI 等。

  3. 环境变量(environ):environ是一个字典,包含了与当前请求相关的环境变量和元数据。它提供了请求的各种属性,如请求方法、URL、头部信息等。应用程序可以通过访问environ来获取请求的相关信息。

  4. 响应起始函数(start_response):start_response是一个可调用对象,用于发送响应的状态码和头部信息给服务器。应用程序在生成响应之前必须调用start_response函数,以便告知服务器响应的相关信息。它接收两个参数:状态码和头部信息。

  5. 响应内容(Response):响应内容是由应用程序生成的数据,可以是字符串、字节流、可迭代对象等。应用程序生成的响应内容将由服务器返回给客户端。

  6. 中间件(Middleware):中间件是介于服务器和应用程序之间的组件,用于对请求和响应进行处理。它可以修改environstart_response对象,也可以在请求传递给应用程序之前或响应返回给客户端之前执行其他操作。

通过遵循 WSGI 规范,Web 服务器和应用程序可以实现解耦,使得应用程序可以在不同的 Web 服务器上运行,并且服务器可以支持多种不同的应用程序。WSGI 的设计目标是简单、通用和易于实现,为 Python Web 开发提供了灵活和可扩展的基础。

下面是一个简单的 WSGI 服务器案例,使用 Python 内置的wsgiref模块实现:

1
2
3
4
5
6
7
8
9
10
11
12
from wsgiref.simple_server import make_server

def application(environ, start_response):
status = '200 OK'
headers = [('Content-type', 'text/plain')]
start_response(status, headers)

return [b'Hello, World!']

if __name__ == '__main__':
server = make_server('localhost', 8000, application)
server.serve_forever()

在这个案例中,我们使用wsgiref模块提供的make_server函数创建了一个简单的 WSGI 服务器。服务器监听在本地主机的 8000 端口上,并使用application函数作为应用程序处理请求。

在分析这个案例时,我们可以对 WSGI 的要素进行说明:

  1. 应用程序(Application):application函数是一个符合 WSGI 规范的应用程序。它接收environstart_response两个参数,根据请求生成响应内容,并通过调用start_response函数设置响应的状态码和头部信息。

  2. 环境变量(environ):environ是一个字典,包含了与当前请求相关的环境变量和元数据。在这个案例中,environ作为application函数的第一个参数,可以用来获取请求的相关信息,如请求方法、URL、头部信息等。

  3. 响应起始函数(start_response):start_response是一个可调用对象,用于发送响应的状态码和头部信息给服务器。在这个案例中,start_response作为application函数的第二个参数,用于设置响应的状态码为’200 OK’,并设置头部信息为Content-type: text/plain

  4. 响应内容(Response):application函数返回的内容是一个包含字节流的可迭代对象,即[b'Hello, World!']。在这个案例中,返回的响应内容是简单的字符串’Hello, World!’,由于 WSGI 要求返回的内容必须是字节流,因此我们使用字节流进行表示。

通过这个案例,我们可以看到 WSGI 的实际应用过程。服务器接收到客户端的请求后,调用应用程序处理请求,并将应用程序返回的响应内容返回给客户端。应用程序通过访问environ获取请求的相关信息,通过调用start_response设置响应的状态码和头部信息,然后返回响应内容。整个过程实现了服务器和应用程序的解耦,使得应用程序可以在不同的 WSGI 服务器上运行。

WSGI 和 ASGI

ASGI(Asynchronous Server Gateway Interface)和 WSGI(Web Server Gateway Interface)是用于在 Python Web 应用程序和 Web 服务器之间建立连接的接口规范。它们在以下几个方面存在区别:

  1. 异步支持:ASGI 是为异步 Web 应用程序设计的接口规范,而 WSGI 是为同步 Web 应用程序设计的接口规范。ASGI 允许使用异步编程模型来处理请求和响应,可以处理高并发和长连接的情况,提供更高的性能和可伸缩性。WSGI 只支持同步方式,每个请求都在单独的线程或进程中处理。

  2. 中间件:ASGI 引入了中间件的概念,可以在请求和响应处理的过程中插入中间件组件,进行额外的处理和扩展。WSGI 没有内置的中间件概念,中间件通常是由 Web 框架自己提供的。

  3. WebSocket 支持:ASGI 原生支持处理 WebSocket 协议,可以与 WebSocket 通信进行双向实时通信。WSGI 无法直接处理 WebSocket 协议,需要借助其他库或服务器来实现 WebSocket 支持。

总的来说,ASGI 相对于 WSGI 具有更高级的异步支持和更丰富的功能,适用于处理高并发、长连接和实时通信的应用程序。而 WSGI 适用于传统的同步 Web 应用程序,其简单易用且广泛支持。下面从 WSGI 要素的角度分析这两者, 得出如下的概念:

要素 WSGI ASGI
应用程序 接收 environstart_response 参数 接收 scopereceivesend 函数
环境变量 environ 字典 scope 字典
响应起始函数 start_response 可调用对象
响应内容 可迭代对象返回字节流 使用 send 函数发送消息、接收 receive 函数接收消息

通过以上对比可以看出,WSGI 和 ASGI 在要素上存在一些显著的差异:

  1. 应用程序:在 WSGI 中,应用程序是一个可调用对象,接收environstart_response两个参数;而在 ASGI 中,应用程序是一个可调用对象,接收scopereceivesend函数。ASGI 引入了scope的概念,通过scope传递请求的相关信息。

  2. 环境变量:WSGI 中使用environ字典传递请求的环境变量和元数据;ASGI 中使用scope字典传递请求的环境变量和元数据,scope包含更多的信息,如协议、主机、路径等。

  3. 响应起始函数:WSGI 中使用start_response可调用对象设置响应的状态码和头部信息;ASGI 中不再需要响应起始函数,而是通过send函数发送消息。

  4. 响应内容:WSGI 中应用程序返回的内容是一个可迭代对象,每个元素是字节流;ASGI 中通过send函数发送消息,应用程序使用send函数发送消息,使用receive函数接收消息。

总的来说,ASGI 相比于 WSGI 在要素上进行了一些扩展和改进,引入了更灵活的消息传递机制,使得支持实时、异步的 Web 应用成为可能。ASGI 的设计使得开发者可以使用异步框架构建高性能、并发处理的 Web 应用,适用于实时聊天、数据推送等场景。而 WSGI 则更适合传统的同步请求响应模型的 Web 应用开发。

WSGI 服务器

以下是一些常见的 WSGI 服务器,按照使用量逆序排列的列表:

名称 发布时间 功能 使用场景
uWSGI 2001 年 高性能的 WSGI 服务器 部署 Python Web 应用程序
Gunicorn 2010 年 Python WSGI HTTP 服务器网关接口 部署 Python Web 应用程序
Meinheld 2011 年 高性能的 WSGI 服务器 部署 Python Web 应用程序
Waitress 2011 年 简单但高效的 WSGI 服务器 小型应用或开发环境
CherryPy 2002 年 轻量级的 Web 框架和 WSGI 服务器 构建中小型 Web 应用
Bjoern 2010 年 高性能的异步 WSGI 服务器 处理高并发的 Web 应用

这些服务器都是常见的用于部署和运行 WSGI 应用程序的工具,可以根据不同的需求和场景选择合适的服务器进行部署。

uwsgi

说明

uWSGI 是一个 Web 服务器网关接口(Web Server Gateway Interface,WSGI)的实现,也是一个用于部署 Python Web 应用的软件工具。它提供了一个快速、灵活和可扩展的 Web 服务器,可以与多种 Web 框架和应用程序进行集成。

uWSGI 最初是为了与 WSGI 应用程序进行交互而设计的,它可以作为一个 HTTP 服务器运行,接收 HTTP 请求并将其转发给后端的 WSGI 应用程序进行处理。与传统的 CGI 方式相比,uWSGI 具有更高的性能和并发能力。

除了与 WSGI 应用程序的集成,uWSGI 还支持与其他编程语言和框架进行集成,例如 PHP、Ruby、Perl 等,这使得它成为一个多语言的 Web 服务器。

uWSGI 具有以下特点和功能:

  1. 高性能:uWSGI 采用多线程和异步处理等技术,具有高并发和高吞吐量的特性,适用于处理大量的并发请求。

  2. 负载均衡:uWSGI 支持负载均衡,可以将请求分发到多个后端应用程序实例上,提高应用程序的可扩展性和容错性。

  3. 可扩展性:uWSGI 支持多进程和多线程模式,可以根据需要进行水平扩展,以适应不同规模和负载的应用场景。

  4. 插件系统:uWSGI 具有丰富的插件系统,可以扩展其功能,如缓存、压缩、身份验证等。

  5. 配置灵活:uWSGI 提供了丰富的配置选项,可以灵活地配置和调整服务器的行为,以满足不同的需求。

总之,uWSGI 是一个功能强大的 Web 服务器和应用程序部署工具,提供了高性能、可扩展性和灵活性,适用于部署 Python 和其他语言的 Web 应用程序。

命令

在通过pip install uwsgi之后就可以在系统中使用 uwsgi 命令, uWSGI 命令的格式如下:

1
uwsgi [options] <uwsgi_config_file>

其中,options是可选的命令选项,用于配置 uWSGI 服务器的行为和属性。<uwsgi_config_file>是必需的 uWSGI 配置文件,用于指定服务器的详细配置。

uWSGI 命令支持许多选项,用于控制服务器的运行方式、并发处理、请求超时等方面的行为。以下是一些常用的命令选项:

  • -s <socket>:指定 uWSGI 服务器绑定的套接字地址。
  • -H <virtualenv>:设置虚拟环境的路径。
  • -w <module>:<callable>:指定应用程序模块和可调用对象的名称。
  • -p <processes>:设置启动的进程数量。
  • -t <threads>:设置每个进程的线程数量。
  • --http <host:port>:指定 HTTP 服务器的主机和端口。
  • --https <host:port>,<certfile>,<keyfile>:指定 HTTPS 服务器的主机、端口以及证书文件路径和密钥文件路径。
  • --master:启用主进程模式。
  • --enable-threads:启用多线程支持。
  • --processes <processes>:设置启动的进程数量。
  • --threads <threads>:设置每个进程的线程数量。
  • --plugins <plugin1>,<plugin2>,...:加载指定的 uWSGI 插件。

这些选项可以根据具体需求进行组合和调整,以满足不同场景下的需求。通过使用合适的命令选项和配置文件,可以定制 uWSGI 服务器的行为和性能。

配置可选项

  1. uwsgi.ini配置文件中,常见的大项配置包括:
  • [uwsgi]:定义全局的 uWSGI 配置选项。
  • [logging]:配置日志相关的选项,包括日志级别、日志文件路径等。
  • [socket]:配置 uWSGI 服务器监听的套接字相关选项,如套接字类型、套接字地址等。
  • [http]:配置 HTTP 服务器相关选项,如 HTTP 主机、端口、超时等。
  • [https]:配置 HTTPS 服务器相关选项,如证书路径、密钥路径等。
  • [route-label]:定义路由标签,用于在路由规则中引用特定的处理逻辑。
  • [route]:定义路由规则,将请求路由到指定的处理逻辑。
  • [uwsgi-process]:配置 uWSGI 进程相关选项,如进程数量、进程类型、启动命令等。
  • [uwsgi-server]:配置 uWSGI 服务器相关选项,如服务器名称、工作目录、应用程序模块等。

这些大项配置提供了不同方面的配置选项,可以根据具体需求对 uWSGI 服务器进行灵活的配置和定制。

  1. [uwsgi]配置选项
  • uid:指定运行 uWSGI 进程的用户 ID。
  • gid:指定运行 uWSGI 进程的用户组 ID。
  • umask:设置 uWSGI 进程的文件权限掩码。
  • processes:设置启动的进程数量。
  • threads:设置每个进程的线程数量。
  • master:启用或禁用主进程模式。
  • harakiri:设置请求超时时间,超过该时间将会被强制终止。
  • max-requests:设置每个工作进程处理的最大请求数量,达到该数量后会自动重启进程。
  • reload-on-rss:设置工作进程的内存占用阈值,超过该阈值将会自动重启进程。
  • reload-on-as:设置工作进程的虚拟内存占用阈值,超过该阈值将会自动重启进程。
  • reload-on-rss:设置工作进程的内存占用阈值,超过该阈值将会自动重启进程。
  • buffer-size:设置缓冲区的大小。
  • logto:指定日志文件的路径。
  • daemonize:将 uWSGI 进程转为守护进程模式。
  • pidfile:指定保存进程 ID 的文件路径。
  • stats:启用统计信息,用于监控 uWSGI 服务器的性能指标。

这些全局配置选项用于配置 uWSGI 服务器的基本行为,如进程数量、线程数量、权限设置、日志输出等。根据具体需求,可以调整这些选项来满足不同的运行环境和性能要求。

uwsgi 和 gunicorn

uWSGI 和 Gunicorn 是两个常用的 WSGI 服务器,用于部署 Python Web 应用程序。它们在一些方面有所差异,以下是对它们进行比较的一些方面:

  1. 性能和并发处理能力:uWSGI 在性能和并发处理能力方面表现出色。它采用了多进程和多线程模型,并提供了高级的并发特性,如异步处理和协程支持,可以处理更多的并发请求。Gunicorn 也具备不错的性能,但相对 uWSGI 来说,在高并发负载下的处理能力可能稍逊一筹。

  2. 灵活性和可定制性:uWSGI 提供了丰富的配置选项,可以根据需求进行高度定制,包括进程管理、线程池配置、请求缓存等。它还支持多种编程语言和应用框架,并提供了插件系统,使得功能扩展更加灵活。Gunicorn 也具备一定的可定制性,但相对 uWSGI 而言,配置选项较少。

  3. 稳定性和生态系统:uWSGI 经过多年的发展和广泛应用,具有相对稳定的性能和可靠性。它在 Python Web 应用部署中被广泛使用,有一个成熟的生态系统和丰富的社区支持。Gunicorn 也是一个稳定可靠的 WSGI 服务器,但相对于 uWSGI,它的用户基础和社区规模可能稍小一些。

  4. 部署和配置:Gunicorn 在部署和配置方面较为简单和直观。它提供了一些默认配置,可以快速启动和运行应用程序。uWSGI 的配置选项较多,需要一些额外的学习和配置工作,适用于更复杂的部署场景。

综上所述,选择 uWSGI 还是 Gunicorn 取决于具体的需求和项目要求。如果需要更高的性能和并发处理能力,并且对定制化配置有较高的需求,uWSGI 可能是一个更好的选择。如果对简单部署和配置更为看重,且应用规模较小,Gunicorn 可以是一个更合适的选择。

gunicorn 相比 uwsgi 更加简单和方便可以从下面几个方面比较得出:

  1. 命令行界面:Gunicorn 提供了简单易用的命令行界面,可以通过简单的命令就能够启动应用程序,例如:

    1
    gunicorn myapp:app

    这样就可以启动一个使用 Gunicorn 作为服务器的应用程序。相比之下,uWSGI 的命令行选项较多,配置较为复杂。

  2. 配置文件:Gunicorn 支持通过配置文件来定义服务器的设置,例如绑定的地址和端口,工作进程数量等。这使得配置更加直观和易于管理。而 uWSGI 通常需要在命令行中指定各种参数,不如配置文件直观。

  3. 兼容性:Gunicorn 与 WSGI 兼容性良好,可以无缝地与大多数基于 WSGI 的 Python 应用程序集成。大多数基于 Flask、Django 等框架开发的应用程序可以直接使用 Gunicorn 进行部署,无需额外的配置。相比之下,uWSGI 在与应用程序集成方面可能需要更多的配置和调整。

总的来说,Gunicorn 提供了更简单、直观的部署选项,适用于快速启动和运行应用程序。它适合于中小型项目或者对部署要求相对简单的情况。对于简单的 Python 应用程序,使用 Gunicorn 可能更加便捷和快速。但对于复杂的、高性能、大规模的项目,uWSGI 提供了更多的配置选项和灵活性,能够满足更复杂的需求。

uwsgi 配置示例

设置一个 flask 应用实例, 其中入口文件 main.py, APP 的实例名: application-01

设置 uwsgi.ini 配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[uwsgi]
uid = bifeng
gid = staff

base = /Users/bifeng/Public/bamboo-api
chdir = %(base)
home = /Users/bifeng/.virtualenvs/server

wsgi-file = main.py
callable = application

# http = 127.0.0.1:3838
socket = 127.0.0.1:3838
stats = 127.0.0.1:9494

master = true
processes = 2
threads = 4
chmod-socket = 644
enable-threads = true
logto = %(base)/logs/uwsgi.log

使用 supervisor 来管理 uwsgi:

1
2
3
4
5
6
[program:api]
command = /Users/bifeng/.virtualenvs/server/bin/uwsgi --ini /Users/bifeng/Public/bamboo-api/uwsgi.ini
; process_name = %(program_name)s_%(process_num)02d
; numprocs = 4
stdout_logfile = /var/log/supervisor/api.log
stderr_logfile = /var/log/supervisor/api_err.log

设置 nginx 静态服务器, 将所有流量upstream到上游 socket 服务器:

1
2
3
4
localtion / {
include uwsgi_params;
uwsgi_pass 127.0.0.1:3838;
}

参考