前言

一、webserver、software、WSGI、CGI、Fastcgi是什么?

1、什么是webserver

1.1 webserver的作用

1.2 webserver怎么工作的?

1.3 有哪些产品是webserver

1.4 static webserver  VS dynamic webserver

2、python software

3、WSGI、CGI、Fast CGI是什么?

3.1 WSGI是什么?

3.2 CGI是什么?

3.3 mode_python是什么?

3.4 FastCGI是什么?

3.5 mode_wsgi是什么?

3.6 WSGI是什么?

3.6 WSGI server 是什么?

二、WSGI / CGI / FastCGI的工作流程?

三、参考文章


前言

这篇文章知识满满,如果大家看到这篇文章时,也正好是你想要了解的内容,请好好看。

 

首先,先说点题外话。

1、这篇文章纯属是我总结的一些stack overflow、python官方文档、其他英文资料形成的。我想说的是:有能力阅读英文的,直接去阅读英文资料。网上查阅中文的资料(比如CSDN)绝大多数就是浪费自己的时间。没有能力阅读英文的,逼着自己去读,除非你一点英文都不懂,时间长了自然就能阅读英文了。

2、那么有人问,怎么找英文资料?有条件的直接google,没条件的上biying,biying有国际版和中文版,也可以很快的搜到优质的英文资源。百度搜索就不说了,自己尝试吧。

 

进入正题

为什么写这篇文章呢?这是我在看《python网络编程》第三版 这本书的时候,里面介绍到了4种基于python的架构模式,如下:

看到这张框架图时,我就有点蒙了。平时总是说wsgi、gunicorn、nginx,但是他们是怎么与python代码结合起来提供服务的呢?一查资料又引出了CGI、Fastcgi这些又是什么呢?

这篇文章就将这些问题讲透彻。当然,原英文文章讲的才是最好的,如果大家有兴趣还是去读原文。

 

一、webserver、software、WSGI、CGI、Fastcgi是什么?

1、什么是webserver

web服务器是使用HTTP(超文本传输协议)和其他协议来响应通过万维网发出的客户机请求的软件和硬件。web服务器的主要工作是通过存储、处理和发送网页给用户来显示网站内容。除了HTTP协议外,web服务器还支持SMTP (Simple Mail Transfer Protocol,简单邮件传输协议)和FTP (File Transfer Protocol,文件传输协议),用于电子邮件、文件传输和存储。

1.1 webserver的作用

网络服务器用于网络托管,或为网站和基于Web的应用程序托管数据。如下图所示。

通俗的可以这样理解:

Web服务器提供响应。他们坐在那里,耐心地等待,然后毫无预兆地,突然:

  • 客户端进程发送请求。客户端进程可以是一个web服务器,一个机器人,一个移动应用程序,等等。他只是个“客户端”
  • web服务器接收到这个请求
  • 然后服务器会交给一个黑盒子运行一些程序
  • web服务器向客户端返回一些信息
  • Web服务器再次闲置
  • 继续服务

1.2 webserver怎么工作的?

当我们在浏览器上发起一个请求,到webserver返回给我们内容,到底经历了什么呢?

比如谷歌Chrome或Firefox,需要一个托管在网络服务器上的文件,浏览器会通过HTTP请求该文件。当请求被web服务器接收时,HTTP服务器将接受请求,找到内容并通过HTTP将其发送回浏览器。

更具体地说,当浏览器从web服务器请求页面时,该过程将遵循一系列步骤。首先,用户将在网页浏览器的地址栏中指定一个URL。网络浏览器将获得域名的IP地址——要么通过DNS(域名系统)翻译URL,要么在其缓存中搜索。这将把浏览器带到一个web服务器。然后浏览器将通过HTTP请求从web服务器请求特定的文件。web服务器将响应,再次通过HTTP向浏览器发送所请求的页面。如果请求的页面不存在或出现错误,web服务器将响应一个错误消息。浏览器将能够显示该网页。

由于websever可以托管程序,经常被用于一下用途:

  • 收发电子邮件;
  • 下载文件传输协议(FTP)文件请求;和
  • 建立和发布网页

1.3 有哪些产品是webserver

webserver其实就是一个软件(software),这个软件也是用我们平时用的语言所写的,最出名的就是nginx、Apache HTTP Server。以下为常见的web server。

  • Apache HTTP server:由Apache软件基金会开发,它是一个免费和开源的web服务器,适用于Windows, Mac OS X, Unix, Linux, Solaris和其他操作系统;它需要Apache许可。
  • Microsoft Internet Information Services (IIS):由微软为微软平台开发;它不是开源的,但是被广泛使用。
  • Nginx:一个流行的开放源码web服务器,因为它的资源利用率和可伸缩性很低。由于其事件驱动的体系结构,它可以处理许多并发会话。Nginx也可以用作代理服务器和负载均衡器。
  • Lighttpd:FreeBSD操作系统自带的免费网络服务器。它被认为是快速和安全的,同时消耗更少的CPU功率。
  • Sun Java System Web Server:Sun Microsystems提供的免费网络服务器,可以在Windows、Linux和Unix上运行。它有很好的设备来处理大中型网站。

web server它会等待request返回响应,但是注意:

Web服务器就是:服务器。他们对内容一无所知,他们更不会准备内容,对用户一无所知,实际上除了等待请求的到来和可靠地回复之外什么都不知道。

你选择的网络服务器应该反映你的交付偏好(比如你是觉得nginx好用,而不用apache),而不是你的软件(也就是你基于代码框架写的 web 程序)。你的web服务器应该负责服务,而不是处理或逻辑事务。

那么,他们webserver返回的内容从哪里而来呢?这就要分两种情况了。见下面

1.4 static webserver  VS dynamic webserver

web服务器既可以用于提供静态内容,也可以用于提供动态内容。

静态内容指的是原样显示的内容,而动态内容可以更新和更改。

一个 static webserver将由一台计算机和HTTP软件组成。它被认为是静态的,因为服务器将向浏览器发送托管文件。所以只需要web server就能干这件事。

而dynamic webserver将由网络服务器和其他软件(如应我们基于框架写的app或者数据库)组成。它被认为是动态的,因为应用服务器可以在将任何托管文件发送到浏览器之前用于更新它们。当从数据库请求时,web服务器可以生成内容。虽然这个过程比较灵活,但也比较复杂。但是这是我们常用的模式。

那么,问题来了,我不能直接把代码集成到webserver吗,答案是可以的。许多基本的web服务器也将支持服务器端脚本,在web服务器上使用脚本,可以自定义对客户端的响应。服务器端脚本在服务器机器上运行,通常具有广泛的特性集,其中包括数据库访问。但是局限性比较强,首先你要和web server的语言环境一致,比如apache http server使用java写的,那我们需要将java代码集成进去,使用python就不行了。并且将代码集成到webserver也不是一个好想法,非常的不灵活且code起来比较难。

所以一般dynamic webserver都是遵循下图的结构:server接受到请求,发现是动态内容,然后会开启进行运行我们写好的app,得到输出后,生成response,返回给client。

这里插一点项目中的经验:还记得我们部署前后端时最常用得方式吗?

使用nginx做转发,当请求得是前端文件css、js等static文件时,我们直接代理本地文件夹(这时候就是static webserver),当请求得是后端程序时,我们直接代理到请求后端(这时候是static webserver)

2、python software

这个东西又是什么呢?这其实就是我们写的web程序。其实我们前面已经很多处讲到这个概念,也就是上图的app部分。负责生成动态数据并交付给web server。

当然这个software可以是任何语言写成的app,并且app不是一直存在的,只有在webserver给运行app获取数据时,app才会存在。

3、WSGI、CGI、Fast CGI是什么?

好了,上面已经铺垫这么多了。想必也都理解了webserver是什么,software(app)是什么了。那么开始说WSGI、CGI、Fast CGI。

3.1 WSGI是什么?

WSGI(web server gateway interface)是为Python语言定义的Web服务器Web应用程序(app)或框架之间的一种简单而通用的接口

在上面我们介绍的webserver和app,他们之间是怎么说话的呢?这时候就需要一个翻译官:WSGI。

我们也可以理解WSGI为一种协议或者规则,用来在web server 和 web应用程序来进行来回翻译。

WSGI规则分为2部分:

第一部分是为web服务器端编写的,它说:“好吧,如果你想处理一个WSGI应用程序,以下是软件加载时的思考方式。以下是必须提供给应用程序的内容,以及每个应用程序都可以拥有的界面(布局)。此外,如果出现任何问题,这是该应用程序的思维方式,以及你可以期待它的行为。”

第二部分是为Python应用程序软件编写的,内容是“好,如果您想处理一个WSGI服务器,以下是服务器在与您联系时的思考方式。下面是必须提供给服务器的东西,下面是每个服务器都可以使用的界面(布局)。此外,如果出现任何问题,以下是您应该采取的行为方式,以及您应该告诉服务器的内容。”

所以你就明白了,服务器就是服务器,软件就是软件,这里有一种方法可以让他们很好地相处而不用考虑对方的具体情况。这是WSGI。

另一方面,mod_wsgi是Apache的一个插件,它可以让Apache与wsgi兼容的软件对话,换句话说,mod_wsgi是Apache中上述规则手册第一部分规则的实现。

3.2 CGI是什么?

他其实和WSGI的作用是一样的,都是作为webserver和app之间的翻译官-网关接口。那么CGI又有什么特点呢?

我们可以看看python-docs的说法,以下为翻译过来的,原文可以去翻阅python-docs

CGI的缺点:

被称作“CGI”的接口是最古老的,几乎所有的web服务器都支持它。每个请求都需要由服务器启动使用CGI与web服务器通信的程序。因此,每个请求都会启动一个新的Python解释器——启动它需要一些时间——因此整个接口只能用于低负载的情况。

CGI的优点

它很简单——编写一个使用CGI的Python程序只需要大约三行代码。这种简单性是有代价的:它对开发人员的帮助很少。

它的配置文件经常会出现一些神秘的错误,让人一脸懵。

CGI脚本配置方法

同时,我们可以对CGI进行配置,目前支持CGI脚本配置比较好的是Apache HTTP server 和 lighttpd 。具体配置方式,由于每种http server的配置方式均不相同,所以还是到相应http server的官方文档去查看配置方法。

不推荐使用CGI配置

所以,虽然编写CGI程序虽然仍然可行,但不再推荐使用。使用WSGI(本文档后面将讨论的主题),可以编写模拟CGI的程序,因此如果没有更好的选项,它们可以作为CGI运行。

3.3 mode_python是什么?

它也是一个网关接口,但是它的原理不太一样。

mode_python指的将python解释器和python代码集成到web server里面去的一种方式。

经常使用PHP的人,对这种方式非常了解,因为web server里可以很好的集成PHP代码写的app。mode_python提供了接口可以将python代码集成到web server里面,就像PHP代码做的那样,但是副作用很大,所以这种方式很少使用。

mode_python主要有以下几个问题:

  • 与PHP解释器不同,Python解释器在执行文件时使用缓存,因此对文件的更改需要重启web服务器
  • 另一个问题是基本概念——Apache启动子进程来处理请求,而每个子进程都需要加载整个Python解释器,即使它不使用它。这会使整个web服务器变慢
  • 因为mod_python链接到python-lib的特定版本,所以不可能在不重新编译mod_python的情况下从旧版本切换到新版本
  • 因为mod_python也绑定到Apache web服务器,所以用mod_python编写的程序具有特殊性,不能轻松地在其他web服务器上运行

3.4 FastCGI是什么?

FastCGI和SCGI试图用另一种方式解决CGI的性能问题。它们不是提供将解释器嵌入到web服务器中的接口,而是创建长时间运行的后台进程来运行我们的app代码。在web服务器中还有一个模块,它可以使web服务器与后台进程“对话”。由于后台进程独立于服务器,所以它可以用任何语言编写,包括Python。语言只需要一个库来处理与web服务器的通信。

并且,Fast CGI也像CGI一样,可以使用script配置。不同的web server的配置方式不同,还是需要查看相关 web server 的文档。

3.5 mode_wsgi是什么?

mod_wsgi是专门为承载WSGI应用程序而设计的,用在WSGI和web server之间的一个插件。使WSGI可以直接嵌入到Apache web服务器。

Mod_wsgi试图摆脱底层网关。

考虑到FastCGI、SCGI和mod_python主要用于部署WSGI应用程序,mod_wsgi开始直接将WSGI应用程序嵌入Apache web服务器。mod_wsgi是专门为承载WSGI应用程序而设计的。它使WSGI应用程序的部署比使用其他低级方法的部署容易得多,后者需要粘合代码。

缺点是mod_wsgi仅限于Apache web服务器,其他服务器需要它们自己的mod_wsgi实现。

mod_wsgi支持两种模式:嵌入模式(它与Apache进程集成)和守护模式(更类似于fastcgi)。与FastCGI不同,mod_wsgi自己处理工作进程,这使得管理更容易。

3.6 WSGI是什么?

WSGI (Web Server Gateway Interface)它是目前进行Python Web编程的最佳方式。虽然它对于编写框架的程序员来说很好,但普通的web开发人员一般不需要直接用它编程。我们可以选择一款支持WSGI的框架,这些框架会把WSGI封装起来,以提供给我们更加简单的接口。

WSGI共有两大好处:程序编程接口的统一、中间件

  • 程序编程接口的统一:当你的程序与WSGI兼容时——这在外部层面意味着你使用的框架支持WSGI——你的程序就可以通过任何有WSGI包装器的web服务器接口进行部署。你不需要关心应用程序的使用的是mod_python还是FastCGI还是mod_wsgi——使用WSGI时,你的应用程序可以智能的在任何网关接口上工作。
  • 中间件特性:这算是WSGI最伟大的一点,中间件是围绕程序的一层,它可以为程序添加各种功能。已经有相当多的中间件可用。例如设置登录验证中间件、日志打印中间件、设置gzip数据格式的中间件等

最初,Python web框架倾向于将开发网站所需的所有服务作为一个巨大的、集成的工具集。没有两个web框架是可互操作的,2个web程序也不可能相互借鉴轮子,除非进行大量的重新设计工作。

但是自从WSGI出现以来,Python web框架世界一直在朝着基于WSGI标准的互操作性发展。现在许多web框架,都是由可重用组件集合构建的,这些组件可以用于多个框架。因此WSGI也促进了python web 框架的发展。

目前我使用过的:Django、Flask、Fast API都是基于WSGI的框架。

3.6 WSGI server 是什么?

WSGI要在web server 和应用app见起到网关作用,那么意味着它要在web server端实现一部分代码,又要在应用app端实现一部分代码。

那么在web server 端的实现的WSGI部分就叫做 WSGI server。

那么我们编程时,为什么没有在app端实现WSGI的代码呢?因为你选择的框架(如flask、fastapi)都已经帮你实现好了。如果你不用这些框架,可以自己实现app端的wsgi代码,从而直接和wsgi对话。

二、WSGI / CGI / FastCGI的工作流程?

首先注意:

CGI, FastCGI and SCGI 是可以适应任何语言的, 你可以用Perl、Python、C、bash等任何语言编写CGI脚本。CGI根据URL定义调用哪个可执行文件,以及如何调用:参数和环境。它还定义了当你的可执行文件完成时,如何将返回值传递回web服务器。我们要做的就是编辑CGI脚本,与编写执行文件(app)。

WSGI 只适用python。它的标准接口被定位为如下,只能用python调用

def simple_app(environ, start_response):
    """Simplest possible application object"""
    status = '200 OK'
    response_headers = [('Content-type','text/plain')]
    start_response(status, response_headers)
    return ['Hello world!\n']

支持WSGI的web服务器(例如带有mod_wsgi的Apache)可以在请求到达时调用这个函数。

这样做的好处在于,我们可以避免从HTTP GET/POST到CGI再到Python的复杂转换过程。这是一种更直接、更清洁、更有效的联系。

如果一个请求需要做的只是一个函数调用,那么在web服务器背后长时间运行框架也会变得容易得多。使用普通的CGI,你必须为每个单独的请求启动整个框架。

要获得WSGI支持,您需要安装一个WSGI模块(如mod_wsgi),或者使用一个内置WSGI的web服务器(如CherryPy)

 

下图,是我对WSGI、CGI的工作流程,以及各种mode_python、mod_wsgi、mod_fastcgi的使用的总结

 

 

Apache监听端口80。它得到一个HTTP请求。它解析请求以找到响应的方法。Apache有很多响应选择。一种响应方式是使用CGI运行脚本。另一种响应方式是简单地提供文件。如果是简单提供文件就直接返回了;如果是动态内容,就要交给CGI等去执行。

 

对于CGI, Apache准备一个环境并通过CGI协议调用脚本。这是一个标准的Unix Fork/Exec情况——CGI子进程继承了一个包含socket和stdout的操作系统环境。CGI子进程写一个响应,返回Apache;Apache将此响应发送给浏览器。

而使用CGI是原始的和烦人的。主要是因为它为每个请求派生一个子流程,并且子流程必须退出或关闭stdout和stderr以表示响应结束。

 

而WSGI是一个基于CGI设计模式的接口。它不一定是CGI——它不需要为每个请求fork一个子进程。它可以是CGI(也就是可以完全模拟CGI来执行代码),但也可以不是(自己单独的执行方式)。

WSGI以几个重要的方式添加到CGI设计模式中。它为您解析HTTP请求头并将它们添加到环境中。它作为环境中的类文件对象提供任何面向post的输入。它还提供了一个用于格式化响应的函数,省去了大量格式化细节。

 

因为派生子流程的代价很高。现在有两种方法可以解决这个问题:

  • embedded模式的 mod_wsgi或mod_python在Apache内嵌入Python,这样不会创建子进程,而是Apache直接运行Django应用程序。
  • Demon模式的  mod_wsgi或mod_fastcgi,允许Apache使用WSGI协议与单独的守护进程(或“长时间运行的进程”)交互。启动长时间运行的Django进程,然后配置Apache的mod_fastcgi来与这个进程通信。

注意,mod_wsgi可以在两种模式下工作:嵌入式模式(embedded)或守护模式(Demon)。

 

当你阅读mod_fastcgi时,你会看到Django使用flup根据mod_fastcgi提供的信息创建了一个wsgi兼容的接口。管道是这样工作的。

Apache -> mod_fastcgi -> FLUP (via FastCGI protocol) -> Django (via WSGI protocol)

三、参考文章

https://stackoverflow.com/questions/3937224/differences-and-uses-between-wsgi-cgi-fastcgi-and-mod-python-in-regards-to-py

https://whatis.techtarget.com/definition/Web-server#:~:text=A%20web%20server%20is%20software%20and%20hardware%20that,through%20storing%2C%20processing%20and%20delivering%20webpages%20to%20users.

https://izziswift.com/how-python-web-frameworks-wsgi-and-cgi-fit-together/

https://stackoverflow.com/questions/4929626/what-are-wsgi-and-cgi-in-plain-english#:~:text=Both%20CGI%20and%20WSGI%20define%20standard%20interfaces%20that,pretty%20much%20like%20a%20bare%20HTTP%20server%20response.

https://docs.python.org/zh-cn/2/howto/webservers.html

https://stackoverflow.com/questions/219110/how-python-web-frameworks-wsgi-and-cgi-fit-together

https://stackoverflow.com/questions/219110/how-python-web-frameworks-wsgi-and-cgi-fit-together

Logo

GitCode 天启AI是一款由 GitCode 团队打造的智能助手,基于先进的LLM(大语言模型)与多智能体 Agent 技术构建,致力于为用户提供高效、智能、多模态的创作与开发支持。它不仅支持自然语言对话,还具备处理文件、生成 PPT、撰写分析报告、开发 Web 应用等多项能力,真正做到“一句话,让 Al帮你完成复杂任务”。

更多推荐