这篇文章推荐了一个好东西,确实是,但是在介绍之前,需要先补充一些背景知识。在学习Web开发的时候,我们肯定会接触到以下几个概念。
那么它们之间有什么区别呢?这是一个总结。
WSGI
WSGI的全称是Web(Web ),是描述Web服务器和Web应用程序(使用Web框架编写的程序,如Flask)之间通信的规范和协议。
由于任何框架编写的服务都必须运行在Web服务器上,因此两者必须遵循相同的通信规范,这个规范就是WSGI。实现WSGI协议的框架称为WSGI框架,实现WSGI协议的服务器称为WSGI服务器。
uWSGI
实现WSGI协议的Web服务器可以通过在uWSGI服务器上部署使用Web框架编写的应用程序来直接对外提供服务。当然,除了uWSGI之外,还有其他的WSGI服务器。它们不仅实现了WSGI协议,还实现了uwsgi协议和HTTP协议。
nginx
它也是一个Web服务器,但是它可以提供比uWSGI更多的功能,比如反向代理、负载均衡、缓存静态资源、对HTTP请求更加友好等,这些都是uWSGI不具备或者不擅长的。
所以我们在uWSGI后面部署了Web服务之后,还需要在前面再搭建一层Nginx。此时uWSGI不再暴露HTTP服务,而是暴露TCP服务。因为它与Nginx通信,所以使用TCP速度更快,并且Nginx将HTTP服务暴露给外界。
吴晓雅
用于 Nginx 和 uWSGI 之间通信的协议。因为uWSGI是连接Nginx的,所以两者必须遵循相同的协议。这个协议就是uwsgi。对于一个HTTP请求,Nginx收到后会做出判断。
Nginx内部有一个模块,它的作用是使Nginx能够与uWSGI进行通信。
在 WSGI 出现之前,选择框架可能会限制 Web 服务器可用的接口种类,因为两者之间没有标准化的接口。 WSGI 通过提供一个简单的 API 解决了这个问题。 2004年,随着PEP-333的出现,它已经成为Web应用程序部署的事实上的标准。
让我们构建一个最小的 WSGI 应用程序。
# main.py def application(env, start_response): print(env) start_response("200 OK", [("Content-Type", "text/html")]) return [b"WSGI hello!"]
然后在命令行输入main即可启动。
图片
有人可能会好奇,是不是只要定义一个函数就可以启动呢?答案是肯定的,WSGI协议要求应用程序必须实现一个名为的可调用对象,并接收两个参数:一个是包含HTTP请求信息的字典对象,另一个是用于发送响应的回调函数。应用程序需要从请求字典中获取请求信息,然后使用回调函数返回响应。
服务器会自动调用这个,这是双方都同意的,受WSGI协议规范。我们访问本地8000端口,看看输出是否正常。
图片
结果正常。我们看一下程序中参数env的打印结果。
图片
里面有一些请求信息,从这些信息可以看出WSGI只支持请求/响应生命周期。这意味着 WSGI 无法与 WSGI 等长期连接协议一起使用,并且也不支持异步工作负载。
于是就有了ASGI。它的定位与WSGI相同,但是通过重新设计API并使用协程来解决这个问题。 ASGI 是异步Web 应用程序和服务器之间的接口规范。它是对WSGI规范的扩展和补充,旨在解决WSGI无法有效处理异步IO操作的问题。
因此,与 WSGI 相比,ASGI 支持异步应用程序和服务器,可以处理非阻塞 IO 操作,包括长轮询、HTTP/2 等。它提供了标准化的接口,可以实现 Web 服务器和框架之间的异步通信。
此外,ASGI还指定了一些标准化的环境变量和协议,以确保不同的Web服务器和框架可以协同工作。与 WSGI 一样,ASGI 允许开发人员选择不同的 Web 服务器和框架,并且仍然使它们彼此兼容。
简而言之,ASGI和WSGI做的是同样的事情,但是ASGI在WSGI之上做了很多扩展。让我们将上面的 WSGI 示例转换为 ASGI。
# main.py async def application(scope, receive, send): await send( {"type": "http.response.start", "status": 200, "headers": [(b"Content-Type", b"text/html")]} ) await send({"type": "http.response.body", "body": b"ASGI hello!"})
ASGI的函数接收三个参数:
那么如何启动上面的程序呢?正如启动 WSGI 程序需要 WSGI 服务器一样,启动 ASGI 程序自然也需要 ASGI 服务器。
目前最流行的ASGI服务器,它是建立在更高效的事件循环实现之上的,是一个高性能的HTTP解析库。
我们可以通过运行 pip 命令来安装它,由于不支持该平台,如果在 .
然后通过 main: 运行应用程序。
图片
到目前为止我们知道了什么是ASGI和WSGI。然后就有了ASGI服务器(实现ASGI协议),我们还需要一个ASGI框架,而不是仅仅在文件中写一个协程(当然ASGI框架也是建立在这个之上的)。
至于ASGI框架有很多,比如,,它们都是ASGI框架,都实现了ASGI协议。至于使用这些框架编写的服务,也必须运行在实现ASGI协议的服务器上,ASGI服务器包括等等。
例如:
图片
不管是还是,它们都支持ASGI协议,因此都可以在服务器上运行,甚至启动方式都保持不变。当然,可以从命令行启动,也可以通过代码中调用run方法来启动。
那么我想补充一点,对于最简单的ASGI程序来说,只需要定义一个协程函数来启动它即可。这意味着创建的app对象必须在内部实现了方法,否则无法像函数一样被调用。
图片
我们的分析是正确的。所谓的框架就是基于这个简单的协程函数,一点一点的扩展。
好了,说了这么多,我们回到主题吧。我们的主题是什么?是的,这家伙做的事情和ASGI类似,所以它也是一个ASGI服务器。
天哪,我无法用一句话解释这么多。不像网上那些水视频,视频看到一半才开始讲重点。
那么问题来了,相比之下有什么优势吗?显然,肯定有优点,但即使抛开优点,我们也应该把注意力转向它是用 Rust 编写的,编程语言世界的 。
众所周知,Rust 就像当年的黄埔军校,从里面出来的每个人都有自己的光环。毕竟,使用 Rust,性能和安全性都有保证。如果你信任 Rust,就不会有 bug [doge]。
废话不多说,先说一下它的特点。
现在我们来安装一下,直接使用pip,然后测试一下。
from blacksheep import Application, Request app = Application() @app.router.get("/index") async def index(request: Request): return {"message": "Hello World"}
文件名为main.py。我们在命令行输入:app--启动服务。
图片
因为它实现了ASGI协议,所以仍然可以在其上运行。经过一群朋友测试,ASGI框架选择,ASGI服务器选择,速度都这么快。
然后看一下启动命令。里面有一个--,表示除了ASGI之外,还支持其他的。没错,支持 WSGI、ASGI、RSGI。
让我们演示一下这三者之间的区别:
# WSGI def wsgi_application(env, start_response): start_response("200 OK", [("Content-Type", "text/html")]) return [b"WSGI hello!"] # ASGI async def asgi_application(scope, receive, send): await send( {"type": "http.response.start", "status": 200, "headers": [(b"Content-Type", b"text/html")]} ) await send({"type": "http.response.body", "body": b"ASGI hello!"}) # RSGI async def rsgi_application(scope, proto): assert scope.proto == "http" proto.response_str( status=200, headers=[ ("content-type", "text/html") ], body="RSGI Hello!" )
启动命令如下:
由于RSGI是自建的,目前的框架不支持,所以就用ASGI吧。
除了--之外,还支持很多其他参数,例如:
具体参数可以通过--help查看,注释很详细。