1.CGI (Common Gateway Interface) 通用网关接口
CGI 是一种通用接口,它定义了Web服务器与后端应用程序(通常是CGI脚本)之间如何交互,特别是输入输出格式以及数据传递的方式。 CGI程序 =>每个请求启动一个新进程,效率低。
-
CGI规范则是一个定义了Web服务器与应用程序之间的数据交互规范。它并不规定如何通过网络传输数据,而是定义了Web服务器和后端程序(如CGI脚本或Web应用)如何通过标准输入输出流(stdin/stdout)以及环境变量进行数据交换。
-
细节:
-
Web 服务器 → CGI 网关:Web 服务器接收到客户端的 HTTP 请求后,它会将请求内容转换为 CGI 需要的环境变量,并通过标准输入(stdin)将请求传递给 CGI 程序。Web 服务器与 CGI 网关之间的通信本质上是通过 标准输入输出(stdin, stdout)来完成的。
- 例如,Web 服务器会把请求头信息(如请求路径、HTTP 方法)转化成环境变量传递给 CGI 程序。
-
CGI 网关 → Web 服务器:CGI 程序会根据请求处理逻辑执行操作(比如数据库查询、文件处理等),然后通过标准输出(stdout)将响应返回给 Web 服务器。
- CGI 程序会生成 HTTP 响应头(如
Content-Type: text/html)和响应内容(如 HTML 页面),并通过标准输出传递回 Web 服务器。
- CGI 程序会生成 HTTP 响应头(如
-
-
实现了Web服务器网关接口的软件有:uWSGI(注意大小写)、uvicorn、gunicorn
**WSGI (Web Server Gateway Interface)
WSGI 是 Python Web 应用和 Web 服务器之间的标准接口,它比 CGI 高效,因为它不是每次请求都启动新的进程,而是保持一个 Web 服务器和 Python 应用之间的连接。WSGI 通过一个“中介”来传递请求和响应,所以它使得 Python 的 Web 框架(如 Flask、Django)能够与 Web 服务器(如 Nginx、Apache)协同工作。
通俗说法:WSGI 就像是 Web 服务器和 Python 应用之间的桥梁,它们通过这座桥来沟通。服务器把请求丢到桥上,应用在桥上做处理,然后把结果从桥上返回给服务器。不同于 CGI,它不需要每次请求都启动新的程序。
ASGI (Asynchronous Server Gateway Interface)
ASGI 是 WSGI 的升级版,它不仅支持传统的同步请求,还支持异步处理。这就意味着你可以在同一个 Web 应用中同时处理多个请求,而不需要等待一个请求完成才能处理下一个,这对于高并发应用(例如 WebSocket 或长连接)非常重要。
通俗说法:ASGI 是一个更“高效”的版本,它让 Web 应用能处理大量的同时请求,不会被一个请求阻塞。想象一下你在一个忙碌的餐厅工作,ASGI 就像是一个能够同时接待多个顾客、让每个顾客都得到及时服务的系统。
Q&A
-
自己实现一个socket 就可以实现 客户端与后端应用程序通信 那么就不需要cgi 所以cgi不是必需?
-
CGI并不是必需的,它只是提供了一个标准化的方式来实现Web服务器与后端应用程序的交互。CGI是为Web服务器和应用程序交互定义的协议,它规定了如何传递请求参数、如何调用应用程序并返回结果。通过Socket,你可以绕过CGI协议,直接与后端应用程序建立通信。但是 直接通过Socket与后端应用程序进行通信,灵活性更高,但也需要更多的自定义工作。
-
CGI的必要性:虽然绕过CGI协议,直接通过Socket与后端应用程序通信,但CGI协议在早期的Web开发中起到了很重要的作用,尤其是在Web服务器和后端应用程序之间实现标准化的接口时。CGI协议的作用主要体现在以下几点:
- 标准化接口:CGI为Web服务器与后端应用程序提供了一种标准的通信方式,不同的Web服务器和后端应用程序都可以遵循这个标准进行交互。
- Web服务器和应用程序解耦:Web服务器不需要直接知道应用程序的细节,只需要按照CGI协议调用应用程序即可。这使得Web服务器和应用程序之间的耦合度更低,更容易维护和替换。
- 动态内容生成:CGI让Web服务器能够调用外部程序(如CGI脚本或Web应用),从而生成动态内容,而不只是返回静态页面。
-
-
FastAPI 是使用ASGI(Asynchronous Server Gateway Interface)支持异步的,那么ASGI 的核心机制 是啥? 事件循环 + 协程
- 基于事件循环(Event Loop)
- 使用协程(Coroutine)进行任务切换
- I/O 操作时让出 CPU,继续处理其他请求
-
何为事件循环?
📌 事件循环(Event Loop)
ASGI 使用 Python 的
asyncio事件循环 来管理任务。
事件循环(Event Loop) 本质上是一个任务调度器,负责管理和执行协程(Coroutine) 。 async / await 让 Python 支持协程,但协程本身不会自动运行,必须由事件循环来驱动它们。具体流程如下:
- 执行任务
- 遇到 I/O 操作时暂停(await)
- 切换去执行其他任务
- I/O 完成后恢复执行
-
ASGI 服务器(Uvicorn)如何管理请求?
以 FastAPI + Uvicorn 为例,服务器的请求处理流程如下:
1️⃣ 客户端发送请求
2️⃣ Uvicorn 服务器接收请求,交给事件循环
3️⃣ FastAPI 处理请求,遇到 I/O 操作(数据库查询)时,await让出 CPU
4️⃣ 事件循环继续处理其他请求
5️⃣ I/O 操作完成后,FastAPI 继续执行并返回响应
6️⃣ Uvicorn 发送响应给客户端 -
传统的 Flask + WSGI 工作方式是咋样的?
- 每个请求都会创建一个线程或进程 来执行视图函数。
- 函数必须执行完毕后,才能处理下一个请求(单线程时)。
- 遇到 I/O 操作(如数据库查询)时,会阻塞线程,直到 I/O 结束。
Flask 之所以没有事件循环机制,主要是因为它基于 WSGI(Web Server Gateway Interface),而 WSGI 本身是 同步阻塞 的,无法像 ASGI 那样原生支持异步任务和事件循环。让我们深入看一下原因。
-
WSGI 是同步的:当请求到达 WSGI 服务器时,服务器会创建一个进程或线程来处理该请求。这个请求会被顺序处理,直到响应返回。
-
阻塞执行:如果某个请求涉及到 I/O 操作(如数据库查询、文件读写、网络请求),整个处理过程就会阻塞,直到 I/O 完成,才能继续处理下一个请求。
-
没有事件循环:在 WSGI 中,每个请求都是独立的,它们不能并发执行,也不能中断当前的处理过程去处理其他请求。
-
async/await + 事件循环 = 非阻塞 I/O?
当 Python 代码中使用
async和await:- 遇到
await时,当前任务会暂停,并让出 CPU 给其他任务(不会阻塞线程)。 - 当 I/O 操作(如数据库查询)完成后,事件循环会恢复任务的执行。
- 遇到
-
为啥说 flask和django自身携带的wsgi鸡肋 还需要使用uwsgi 或 gunicon?
- Flask 使用的是内置的 Werkzeug 服务器,Django 使用的是
runserver命令启动的服务器)内置的服务器非常简单,主要功能是帮助开发者进行调试,不具备生产环境下所需的高并发和高性能特性。它们通常不支持多线程或多进程处理,也没有高级的负载均衡、连接池、请求队列等功能。 - Flask 和 Django 自带的 WSGI 服务器是同步的,这意味着每个请求都必须按顺序完成。对于高并发、IO密集型的应用(如实时聊天、文件上传下载等),内置的 WSGI 服务器无法有效利用异步编程优势。而 Gunicorn 和 uWSGI 等更强大的 WSGI 服务器支持并行的工作进程,可以更好地处理这些情况。
- Flask 使用的是内置的 Werkzeug 服务器,Django 使用的是