前几天和同事讨论起CGI的性能、CGI为什么是一项落后的技术的时候,发现其实很多人对CGI等的网关技术并不熟悉这里相信很多同学也都听过CGI、fastCGI、WSGI等的词语,但是应该很多同学都分辨不清它们的区别和联系,本篇文章,就和大家一起探讨这些技术的发展简史而本篇文章标题的GI,指的就是Gateway Interface(网关接口)的缩写,今天小编就来说说关于网关内部原理详细讲解?下面更多详细答案一起来看看吧!
网关内部原理详细讲解
前几天和同事讨论起CGI的性能、CGI为什么是一项落后的技术的时候,发现其实很多人对CGI等的网关技术并不熟悉。这里相信很多同学也都听过CGI、fastCGI、WSGI等的词语,但是应该很多同学都分辨不清它们的区别和联系,本篇文章,就和大家一起探讨这些技术的发展简史。而本篇文章标题的GI,指的就是Gateway Interface(网关接口)的缩写。
了解网关接口之前,我们需要先弄清楚两个东西,Web服务器和Web应用程序。什么是Web服务器?什么是Web应用程序?虽然在我的Django小程序课程里面,有对这两者的区别展开来介绍,但是这里考虑到很多同学并没有学习这门课,所以我们先把这两个概念弄清楚,否则在后面讨论起网关接口,也只会一知半解。
Web服务器
首先,什么是Web服务器。Web服务器是服务于网站后台的一个软件,是常驻于物理服务器的一个计算机程序。Web服务器可以向浏览器等Web客户端提供文档,也可以放置网站文件,让全世界浏览;可以放置数据文件,让全世界下载。目前最主流的三个Web服务器是Apache、 Nginx 、IIS。
Apache是世界使用排名第一的Web服务器软件。它可以运行在几乎所有广泛使用的计算机平台上,由于其跨平台和安全性被广泛使用,是最流行的Web服务器端软件之一。它快速、可靠并且可通过简单的API扩充,将Perl/Python等解释器编译到服务器中。
Nginx是一款轻量级的Web服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,在BSD-like 协议下发行。其特点是占有内存少,并发能力强,事实上Nginx的并发能力在同类型的网页服务器中表现较好,中国大陆使用Nginx网站用户有:百度、京东、新浪、网易、腾讯、淘宝等。
这里先简单讨论一下Nginx和Apache的区别,在资源上,Nginx占用的内存更少;在性能上,Nginx的并发能力更强;在社区方面,Nginx和Apache都拥有广泛的使用者,Apache的插件会比Nginx丰富一些。另外Nginx的功能比Apache要丰富一些,Nginx除了作为Web服务器以外,也经常作为反向代理服务器等使用,而Apache则主要作为Web服务器去使用。
还有IIS,IIS是微软公司在Windows Server提供的一个Web服务器,一般部署在Windows系统上,也有一定的使用者。
Web应用程序
了解了Web服务器,我们接着了解一下Web应用程序。
Web应用程序一般指的是完成业务逻辑的程序,比如熟悉Python语言的,经常会用Django、Flask、Tornado等框架来完成业务逻辑的处理,接受请求,返回结果;熟悉Java语言的,则经常会使用Spring、Spring Boot来完成业务逻辑处理;熟悉PHP语言的,则常用ThinkPHP、Laravel、CI等等框架来完成Web后台的开发;还有Golang、Node.js等等,都会有相应的框架来完成Web请求的处理。
这些就是定义为Web应用程序的东西,也就是我们常说的Web框架,比如一个Pythoner问另外一个Pythoner,你一般使用什么Web框架呀?这个就是Web应用程序。
那么Web服务器和Web应用程序有啥区别?其实在前面的描述里面,我已经说的比较清楚了,Web应用程序主要是完成业务逻辑的处理,Web服务器则主要是进行外部请求的接收和转发。这里需要注意的是,我们一般不应该把业务逻辑放在Web服务器上去处理,虽然说Web服务器支持广泛的脚本来进行拓展,但是我们一般情况下还是不应该把业务逻辑放在Web服务器去处理,比如拦截请求、鉴权处理等等的操作。
看到这里可能有些人又会有疑问了,在开发Web应用的时候,我们直接就可以把应用跑起来接受请求了呀,为啥还需要Web服务器的存在。比如说使用Django的时候,直接输入命令python manage.py runserver,就可以接收请求了,为啥还需要Web服务器呢。
这主要是从性能上去考虑的,Web应用虽然在开发阶段就可以通过一些命令来启动服务,但是这些功能主要是提供调试所使用的,真正部署上线的时候,如果流量较大,性能是不行的,所以需要有Web服务器的存在。Web服务器是专门用于接收外部请求并处理的软件,所以Web服务器在性能上会比Web应用更佳,毕竟术业有专攻。Web服务器处理静态资源请求(CSS、JS、HTML、图片)等,性能会比Web应用更好。另外对于一些非静态资源的请求,则需要转发到后台Web应用。
到这里,我们基本分清楚Web服务器和Web应用的区别了,这里面我们注意一个关键词“转发”,当Web服务器接受请求的时候,会把请求转发到后台Web应用去处理,我们本篇文章的主角,GI就工作在这个转发的过程中。
CGI
终于轮到主角“网关接口”。前面介绍了GI工作的地方,接下来我们就来一起探讨一下现在有哪些GI,他们有哪些特点和区别。
首先是CGI,CGI是Common Gateway Interface (通用网关接口)的缩写。CGI是一项古老的技术。最初是在1993年由美国国家超级电脑应用中心(NCSA)为NCSA HTTPd Web服务器开发的。CGI的原理非常简单粗暴,在支持CGI的Web服务器下,只需要写一个简单的脚本,然后在脚本中输出内容,这些内容就会返回给前台。举个简单的例子,使用Python实现一个hello.py:
#!/usr/bin/env python
print 'Hello, World! Hello CGI.'
然后把他改名为hello.cgi,部署到Web服务器下,当请求到达的时候,打印的字符串就会通过Web服务器返回到页面。我们常常称这种应用为console application (也可以称作command-line interface programs) 的程序,这样的脚本称为CGI脚本。
CGI工作完整的原理是这样的:
当用户访问我们的 Web 应用时,会发起一个 HTTP 请求。最终 Web 服务器接收到这个请求。
Web 服务器创建一个新的 CGI 进程。在这个进程中,将 HTTP 请求数据已一定格式解析出来,并通过标准输入和环境变量传入到 URL 指定的 CGI 程序。
Web 应用程序处理完成后将返回数据写入到标准输出中,Web 服务器进程则从标准输出流中读取到响应,并采用 HTTP 协议返回给用户响应。
一句话就是 Web 服务器中的 CGI 进程将接收到的 HTTP 请求数据读取到环境变量中,通过标准输入转发给CGI程序;当CGI程序处理完成后,Web 服务器中的CGI进程从标准输出中读取返回数据,并转换回 HTTP 响应消息格式,最终将页面呈现给用户。然后 Web 服务器关闭掉这个 CGI 进程。
可以说 CGI 协议特别擅长处理 Web 服务器和 Web 应用的通信问题。然而,它有一个严重缺陷,对于每个请求都需要重新 fork 出一个 CGI 进程,处理完成后立即关闭。当请求量比较大时,会有严重的性能问题,因为频繁的创建进程和回收进程,会占用非常多的服务器资源。因为CGI的性能问题,于是新一代的CGI技术,FastCGI应运而生。
FastCGI
快速通用网关接口(Fast Common Gateway Interface/FastCGI)是一种让交互程序与Web服务器通信的协议。FastCGI是早期通用网关接口(CGI)的增强版本。
FastCGI致力于减少网页服务器与CGI程序之间交互的开销,从而使服务器可以同时处理更多的网页请求。
而FastCGI的工作原理是这样的:
FastCGI 进程管理器启动时会创建一个 主(Master) 进程和多个 CGI 解释器进程(Worker 进程),然后等待 Web 服务器的连接。
Web 服务器接收 HTTP 请求后,将 CGI 报文通过 套接字(UNIX 或 TCP Socket)进行通信,将环境变量和请求数据写入标准输入,转发到 CGI 解释器进程。
CGI 解释器进程完成处理后将标准输出和错误信息从同一连接返回给 Web 服务器。
CGI 解释器进程等待下一个 HTTP 请求的到来。
所以FastCGI可以看作是解决原始CGI性能问题的一个升级版本。
WSGI
WSGI:全称是Web Server Gateway Interface,Web服务器网关接口,WSGI不是服务器,Python模块,框架,API或者任何软件,只是一种规范,描述前面Web服务器如何与Web应用通信的规范。
前面介绍网关接口的时候介绍了CGI、FastCGI等,那这里的WSGI主要是Python为Web服务器和Web应用程序之间通信而设计的。在Python中,常见的Web框架Tornado、Django、Flask都支持使用WSGI和Web服务器进行通信,而在采用WSGI协议的时候,则常常安装uWSGI模块来完成通信。
ASGI
与WSGI类似的还有一个ASGI,ASGI也是由Python实现的一类网关接口,这里的A指的是Async,异步的意思。ASGI是WSGI的扩展,支持除了原来的HTTP以外的WebSocket等的网络协议。
Servlet、Tomcat
终于来到Java阵营了,在前面的CGI、FastCGI、WSGI等等,主要都是PHP、C 、Python等语言实现Web应用程序和Web服务器通信的网关接口,尤其是CGI、FastCGI,在以前C 、PHP大行其道的时候,它们拥有广泛的用户基础,像腾讯等大企业,由于历史的关系,内部系统中还有很多保留着CGI、FastCGI等技术。那么在Java的阵营下,一般使用什么技术作为Web服务器和Web应用框架之间的通信呢?
Servlet,谈到Java不得不谈的一项技术,全称Server Applet,是用Java编写的服务器端程序,可以看做是前面我们介绍的Web应用程序。其主要功能在于交互式地浏览和修改数据,生成动态Web内容。Servlet最初诞生在1997年,最新的一个版本Servlet4.0于2017年9月份推出,Servlet拥有广泛的用户群体。
如果说Servlet是应用程序,那Servlet容器就是包含应用程序的Web服务器,常见的Servlet容器就有我们熟知的汤姆猫(Tomcat)、Jetty等,Servlet容器管理着Servlet应用,我们的Servlet程序一般通过Servlet容器对外进行服务。
随着Docker容器技术和K8S容器编排技术的成熟,今天微服务技术也是非常热门,而微服务离不开的Spring Boot、Spring Cloud的其中,就有Servlet、Servlet容器的身影。
我们说说Spring Boot,对于Spring Boot,大家都被他快捷的开发和部署方式所吸引,Spring Boot是由早期的Spring框架发展而来的,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。在我们开发使用Spring Boot开发Web后台的时候,我们在写完逻辑代码的时候,在本地只需要点击运行,就能通过浏览器进行调试,颇为方便;这和前面我们使用PHP、Python开发Web程序非常类似,我们在使用Flask、Tornado等框架开发Web程序的时候,也可以通过简单的启动,就可以在本地通过浏览器去调试。但是这里是有一些区别的,我们说Flask、Tornado等框架是Web应用框架,没有说他们是Web服务器,他们通过前面介绍的网关接口(GI)通信,但是在使用Spring Boot的时候,却很少说需要把它部署在Web服务器Apache、Nginx之下,一般部署Spring Boot应用的时候,我们直接把它打包成jar包,就可以在服务器跑起来对外服务了。这是为什么呢?
其实Spring Boot内嵌了Servlet容器Tomcat,也就是Spring Boot既充当了Web应用程序的角色,也充当了Web服务器的角色,在开发Spring Boot应用程序的过程中,我们是先通过代码实现了Web应用程序的逻辑,处理请求和应答,而Servlet容器的部分,完全不需要我们去配置,这就是Spring Boot简单、便捷,高效的开发效率的原因,所以现在很多同学都喜欢使用Spring Boot去开发Web的后台。Spring Boot提供了简单的开发模式,但是也带来一些问题,比如说很多同学根本无法分清楚Web应用程序和Web服务器的区别等等。
最后简单的回顾一下今天这篇文章,我们主要是介绍了现在Web后端各种网关接口,包括CGI、FastCGI、WSGI等,在理解这些之前,我们需要弄懂Web服务器和Web应用程序,而网关接口,就是主要工作在Web服务器和Web应用程序之间的。最后我们还介绍了Java阵营的技术,在Java现在大行其道的Spring Boot框架里面,我们不再特意强调Web服务器和Web应用程序,Spring Boot框架是把两个融合在一起的一个框架,Spring Boot可以便捷的开发和部署Web程序,就是因为内部包含了一个叫Tomcat的Servlet容器,也就是Web服务器。
最后希望这篇文章对大家捋清楚Web后台技术和网关接口,都能有一定的帮助。