# CGI、Wsgi和Asgi概述

# 概述

WSGI和ASGI都是Web服务器网关接口,它们是一种规范,描述了Web服务器如何与Web应用程序(客户端)通信,以及如何将Web应用程序链接在一起以处理一个请求。它们指定了Web服务器和Python Web应用程序或Web框架之间的标准接口,以提高Web应用在一系列Web服务器间的移植性。

WSGI全称Python Web Server Gateway Interface,是一种同步网关协议接口,基于HTTP协议模式开发,不支持Websocket。它是Python Web应用程序或Web框架与Web服务器之间的中间件,用于处理请求和响应。WSGI的主要优点是简单易用、灵活性高、移植性好。

ASGI实际上是异步网关协议接口,介于网络服务和Python应用程序之间的标准接口,能够处理多种通用的协议类型,包括HTTP、HTTP2和Websocket。ASGI的诞生解决了Python中的WSGI不支持当前的Web开发中的一些新的协议标准,同时ASGI支持原有模式和Websocket的扩展。ASGI的主要优点是异步处理请求、支持Websocket、能够处理更多的协议类型等。

# CGI

早期的Web服务器,只能响应浏览器发来的HTTP静态资源的请求,并将存储在服务器中的静态资源返回给浏览器。随着Web技术的发展,逐渐出现了动态技术,但是Web服务器并不能够直接运行动态脚本,为了解决Web服务器与外部应用程序(CGI程序)之间数据互通,于是出现了CGI(Common Gateway Interface)通用网关接口。简单理解,可以认为CGI是Web服务器和运行其上的应用程序进行“交流”的一种约定。

CGI(Common Gateway Interface,通用网关接口)是一种通用的Web服务器接口,它允许Web服务器与外部程序(通常是脚本程序)进行交互。通过CGI,Web服务器可以调用外部程序来处理客户端的请求,然后将处理结果返回给客户端。CGI程序可以用多种编程语言编写,如Perl、Python、C/C++等。

CGI程序的工作流程如下:

  1. 客户端向Web服务器发送HTTP请求。
  2. Web服务器接收到请求后,根据请求中的URL确定需要执行的CGI程序。
  3. Web服务器将请求传递给CGI程序,并将POST或GET请求中的参数传递给CGI程序。
  4. CGI程序接收到请求后,处理请求并生成HTML页面。
  5. CGI程序将生成的HTML页面返回给Web服务器。
  6. Web服务器将HTML页面发送给客户端。

CGI程序的优点是灵活性高,可以用各种编程语言编写,功能强大。但是缺点也很明显,每次请求都需要启动一个新的进程,会占用大量系统资源,而且性能较低,容易受到恶意攻击。因此,现在很少使用CGI来处理Web请求,而是采用更高效、更安全的替代方案,如FastCGI、PHP、ASP.NET等。

# WSGI

Web服务器网关接口(Python Web Server Gateway Interface,缩写为WSGI)是为Python语言定义的Web服务器和Web应用程序或框架之间的一种简单而通用的接口。即wsgi和CGI是同样的东西,都是连接Web服务和Web应用之间的桥梁。只不过两者规范的东西不一样。

wsgi的特殊之处在于简单通用

WSGI描述了Server与Framework之间通信的规范,WSGI协议主要包括server和application两部分:

  • WSGI server负责从客户端接收请求,将request转发给application,将application返回的response返回给客户端;
  • WSGI application接收由server转发的request,处理请求,并将处理结果返回给server。application中可以包括多个栈式的中间件(middlewares),这些中间件需要同时实现server与application,因此可以在WSGI服务器与WSGI应用之间起调节作用:对服务器来说,中间件扮演应用程序,对应用程序来说,中间件扮演服务器。

WSGI的出现是因为web框架会限制用户对可用web服务器的选择,而人们希望设计出一个Web服务器和Web应用程序之前的简单通用接口。这样就将框架的选择与 Web服务器的选择分开,让用户可以自由选择适合他们的配对,同时让框架和服务器开发人员可以专注于他们喜欢的专业领域。

WSGI协议其实是定义了一种server与application解耦的规范,有了这个,写Web框架的人,不需要考虑server部分的编写;写server的人就可以专注于写server,而不是写出来server没人用。这也导致了Python的Web框架泛滥。写框架的人不用管server。但是流行的框架就那么几个(Flask,Django,Tronado)。

更多详细的细节以及背景可以阅读PEP-3333 (opens new window),它是PEP-333的更新版本,略有修改以提高Python 3下的可用性,并纳入了WSGI协议的几个长期事实上的修正案。

现在的Python提供了一个内置的模块wsgiref,该模块是wsgi规范的实现。关于该模块的使用可以参考手册wsgiref (opens new window)

# ASGI

ASGI是WSGI的精神继承者,WSGI是用于Web服务器、框架和应用程序之间兼容性的长期存在的Python标准。

ASGI,是基于WSGI接口规范之上的异步服务器网关接口规范,是WSGI的延伸和扩展。A指的是Async,异步的意思。

WSGI成功地在Python网络空间中提供了更多的自由和创新,而ASGI的目标是将这一点继续推进到异步Python的领域。

原文如下:

ASGI is a spiritual successor to WSGI, the long-standing Python standard for compatibility between web servers, frameworks, and applications.

WSGI succeeded in allowing much more freedom and innovation in the Python web space, and ASGI’s goal is to continue this onward into the land of asynchronous Python.

这么一说,大家都明白了,ASGI和WSGI是一样的东西。那么为什么需要ASGI?以及ASGI的具体内容,可以参考asgi文档 (opens new window).

ASGI被设计为WSGI的超集,即ASGI是兼容WSGI的。 ASGI定义了两者之间的转换方式,允许WSGI应用程序通过转换包装器(在asgiref库中提供)在ASGI服务器内运行。

最后,我们可以看一眼Django3.2中的wsgi.py和settings.py中的内容。就明白了大致的过程。

# wsgi.py
import os

from django.core.wsgi import get_wsgi_application

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'chatroom.settings')

application = get_wsgi_application()
# settings.py
WSGI_APPLICATION = 'chatroom.wsgi.application'

# DJango中的Wsgi和Asigi

DJango在创建项目后,会自动生成一个asgi文件,可以通过其asgi:application​来启动ASGI服务器。

无法使用传统的runserver​命令启动ASGI服务器,这只会启动默认的WSGI服务器,即同步架构的服务器,为此我们需要安装专门的ASGI服务器,一般使用Daphne即可。