ASGI 解释:Python Web 开发的未来
Python Web 应用程序长期以来一直遵循 Web 服务器网关接口 (WSGI) 标准,该标准描述了它们如何与 Web 服务器通信。 WSGI 最初于 2003 年推出并于 2010 年更新,仅依赖于 Python 2.2 版本中原生可用且易于实现的功能。
因此,WSGI 很快被所有主要的 Python Web 框架和成为 Python 中 Web 开发的基石。 快进到 2022 年。Python 2 已经过时(终于)了,Python 现在具有处理网络调用等异步操作的本机语法。
WSGI 和其他默认采用同步行为的标准无法利用异步的性能和效率增益。这反过来意味着 WSGI 不能有效地处理像 WebSocket 这样的高级协议。 输入 ASGI,即异步服务器网关接口。
与 WSGI 一样,ASGI 描述了 Python Web 应用程序和 Web 服务器之间的通用接口。与 WSGI 不同,ASGI 允许每个应用程序有多个异步事件。此外,ASGI 支持同步和异步应用程序。
您可以将旧的同步 WSGI Web 应用程序迁移到 ASGI,以及使用 ASGI 构建新的异步 Web 应用程序。 WSGI 通过将 Python 函数(通常命名为应用程序或应用程序)暴露给 Web 服务器来工作。这个函数有两个参数: 函数返回的数据构成响应体。
一个简单的应用程序函数可能如下所示: def application(environ, start_response): start_response('200 OK', [('Content-Type', 'text/plain')]) return [b'Greetings Universe'] 如果你使用的是 WSGI 兼容的 web 框架与 Flask 一样,框架本身将提供一个应用程序功能,其所有组件都会自动连接起来。 WSGI 的缺点是双重的。首先,WSGI 一次只处理一个请求和响应,并假设响应会立即返回。
没有办法处理长时间保持的连接,例如 WebSocket 或长轮询 HTTP 连接。 其次,WSGI 只是同步的。即使您使用多线程连接池,每个连接都会阻塞,直到它返回响应。
许多 WSGI 设置具有处理线程池和进程池的能力,但这些都受到 WSGI 接口本身同步的限制。 ASGI 在外观上与 WSGI 相似。与 WSGI 一样,您定义了一个应用程序函数对象,除了它是一个具有三个参数而不是两个参数的异步函数: 一个简单的 ASGI 应用程序函数可能如下所示: async def application(scope, receive, send): await send({ 'type': 'http.
response.start', 'status': 200, 'headers': [ [b'content-type', b 'text/plain'], ], }) await send({ 'type': 'http.response.
body', 'body': b'Hello, world!', }) 就像一个 WSGI web 框架, ASGI Web 框架将生成自己的 application() 函数并根据需要将其连接起来。 与 ASGI 最明显的区别是我们在整个函数中使用了异步隐喻。函数本身是异步的,我们通过两个单独的 await send() 命令发送 HTTP 标头和响应正文。
这样,函数本身及其发送命令就不会阻塞任何东西;它们可以与应用程序的调用交错并同时从许多其他连接发送。 在这个例子中我们没有使用接收,但它也是一个异步函数。它让我们可以在不阻塞其他操作的情况下接收请求正文。
请求和响应可以通过这种方式增量地传入或传出服务器——这是我们无法优雅地完成的事情,或者根本无法使用 WSGI。 使用 ASGI 时,您需要尽可能多地使用异步函数和异步友好库。养成使用异步的习惯是值得的,因为使用仅同步代码的问题可能很严重。
对仅同步函数的任何长时间运行的调用都会阻塞整个调用链,从而获得使用异步的好处异步几乎蒸发了。 如果您在使用长时间运行的同步调用时遇到问题,请使用 asyncio.run_in_executor 将调用外包给线程或进程池。
每当您等待外部事件或等待外部事件时,都应使用线程池不是 CPU 密集型的任务。进程池应该用于 CPU 密集型的本地任务。 例如,如果您的 Web 应用程序中有一个路由可以调用远程网站,您应该使用线程,或者更好的是使用 aiohttp 库,它会发出异步 HTTP 请求。
如果您想调用 Pillow 图像库来调整图像大小,您可能应该将 run_in_executor 与进程池一起使用。尽管在进程之间来回传输数据会有一些轻微的开销,但使用 run_in_executor 不会阻塞其他事件。 可以通过实现 application() 对象来“手动”编写 ASGI Web 应用程序。
但是在绝大多数情况下,使用异步原生、以 ASGI 为中心会更简单(也不会让人头疼) Python 网络框架。以下是一些与 ASGI 配合良好的 Web 框架的常见选择:
Yorumlar
Yorum Gönder