上犹电脑信息网我们一直在努力
您的位置:上犹电脑信息网 > 文件问题 > 从PHP请求看CGI协议-cgi文件怎么打开

从PHP请求看CGI协议-cgi文件怎么打开

作者:上犹日期:

返回目录:文件问题

1. 什么是CGI?

CGI(Common Gateway Interface)是一个Web服务器主机提供信息服务的标准接口。

通过CGI接口,Web服务器就能够获取客户端提交的信息,转交给服务器端的CGI程序进行处理,最后返回结果给客户端。

我们知道,web服务器所处理的内容都是静态的,要想处理动态内容,需要依赖于web应用程序,如php、jsp、python等。但是web server如何将动态的请求传递给这些应用程序?它所依赖的就是cgi协议。也就是web server和web应用程序交流时的规范。换句话说,通过cgi协议,再结合已搭建好的web应用程序,就可以让web server也能"处理"动态请求,你肯定知道处理两字为什么要加上双引号。

简单版的cgi工作方式如下:

从PHP请求看CGI协议

例如,在浏览器中搜索一个关键词"http",对应的URL为:

https://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=0&rsv_idx=1&tn=baidu&wd=http&rsv_pq=ae0fdcf200028d17&rsv_t=ead5cgwZA%2FJcvKfh16x7TDRimaaqWVjLEXrpFCrFUO4EiMe1VSKd636fNu4&rqlang=cn&rsv_enter=1&rsv_sug3=4&rsv_sug1=4&rsv_sug7=100&rsv_sug2=0&inputT=1575&rsv_sug4=1576

当百度的web server收到该请求后,先分析该url,从中知道了要执行search程序,并且还知道了一系列要传递给search的参数及其对应的value。web server会将这些程序参数和其它一些环境变量根据cgi协议通过TCP或套接字等方式传递给已启动的cgi程序(可能是cgi进程,或者是已加载的模块cgi模块)。当cgi进程接收到web server的请求后,调用search程序并执行,同时还会传递参数给search程序。search执行结束后,cgi进程/线程将处理结果返回给web server,web server再返回给浏览器。

有多种方式可以执行cgi程序,但对http的请求方法来说,只有get和post两种方法允许执行cgi脚本(即上面的search程序)。

2.各种术语释疑

说实话,对于一个没接触过编程语言的人来说,刚接触cgi概念的时候肯定会有一堆疑问,这到底是什么鬼,处理动态内容的东西不是像php一样的应用程序吗,跟cgi有几毛钱关系,fastcgi又是什么?我想,非科班出身的强迫症患者(包括我)一定会被这些概念折腾的死去活来。

以php为例,我将一次动态请求相关的概念大致都简单解释一遍。

cgi:它是一种协议。通过cgi协议,web server可以将动态请求和相关参数发送给专门处理动态内容的应用程序。

fastcgi:也是一种协议,只不过是cgi的优化版。cgi的性能较烂,fastcgi则在其基础上进行了改进。

php-cgi:fastcgi是一种协议,而php-cgi实现了这种协议。不过这种实现比较烂。它是单进程的,一个进程处理一个请求,处理结束后进程就销毁。

php-fmp:是对php-cgi的改进版,它直接管理多个php-cgi进程/线程。也就是说,php-fpm是php-cgi的进程管理器因此它也算是fastcgi协议的实现。

cgi进程/线程:在php上,就是php-cgi进程/线程。专门用于接收web server的动态请求,调用并初始化zend虚拟机。

cgi脚本:被执行的php源代码文件。

zend虚拟机:对php文件做词法分析、语法分析、编译成opcode,并执行。最后关闭zend虚拟机。

cgi进程/线程和zend虚拟机的关系:cgi进程调用并初始化zend虚拟机的各种环境。

以php-fpm为例,web server从转发动态请求到结束的过程大致如下:

从PHP请求看CGI协议

而每个php-cgi进程的作用大致包括:(有些功能分类错误,请无视,知道大致功能就够了)

从PHP请求看CGI协议

注意,尽管php-fpm的全称为PHP FastCGI Process Manager,但严格地讲,php-fpm不是fastcgi的进程管理器,而是php fastcgi即php-cgi的进程管理器。fastcgi只是一种协议,不是进程。就像http协议一样,apache对它的实现是httpd,nginx对它的实现就叫nginx。

再次说明,cgi和fastcgi是一种协议。各种支持和WEB交互的编程语言对cgi/fastcgi协议都做了各自的实现(当然,任何一种语言都能写cgi脚本),而php上的php-cgi和php-fpm正是php对fastcgi协议的实现。

3. web server和CGI的交互模式

web server对cgi进程/线程来说,它的作用就是发起动态处理请求,传递一些参数和环境变量,最后接收cgi的返回结果。再通俗而不严谨地说,web server通过cgi/fastcgi协议将动态请求转发给执行cgi脚本的应用程序。通过下面httpd.conf中的转发配置应该很容易理解(httpd和php-fpm的交互):

ProxyRequests off

ProxyPassMatch ^/(.*\.php)$ fcgi://127.0.0.1:9000/usr/local/apache/htdocs/$1

以最典型的apache httpd和php为例,对于httpd来说,web server和php-cgi有3种交互模式。

cgi模式:httpd接收到一个动态请求就fork一个cgi进程,cgi进程返回结果给httpd进程后自我销毁。

动态模块模式:将php-cgi的模块(例如php5_module)编译进httpd。在httpd启动时会加载模块,加载时也将对应的模块激活,php-cgi也就启动了。(注:纠正一个小小错误,很多人以为动态编译的模块是可以在需要的时候随时加载调用,不需要的时候它们就停止了,实际上不是这样的。和静态编译的模块一样,动态加载的模块在被加载时就被加入到激活链表中,无论是否使用它,它都已经运行在apache httpd的内部。可参考LoadModule指令的官方手册)

php-fpm模式:使用php-fpm管理php-cgi,此时httpd不再控制php-cgi进程的启动。可以将php-fpm独立运行在非web服务器上,实现所谓的动静分离。

实际上,借助模块mod_fastcgi还可以实现fastcgi模式。同cgi一样,管理模式的先天缺陷决定了这并不是一种好方法。

3.1 CGI模式

使用CGI模式时,当动态请求到达,httpd临时启动一个cgi解释器,并通过cgi协议转发要运行的内容。当cgi脚本运行结束后,将结果返回给httpd,然后cgi解释器进程自我销毁。当多个动态请求到达时,将先后启动懂个cgi解释器。因此,这种方法效率极低。

在注释掉php5_module的LoadModule相关行后,使用action指令指定要使用cgi运行的类型。但注意,action指令是mod_action提供的,所以必须已经加载该模块。

例如:指定MIME类型为image/gif的请求使用images.cgi运行。显然,images.cgi脚本你必须先写好。

Action image/gif /cgi-bin/images.cgi

还可以通过添加handler来复合文件类型,再使用某个cgi脚本去运行这个handler中的任意类型。

AddHandler my-file-type .xyz

Action my-file-type "/cgi-bin/program.cgi"

对于php来说,则可以使用安装php时bin目录下提供的php-cgi程序作为cgi程序。

[root@xuexi php]# ls /usr/local/php/bin/

pear peardev pecl phar phar.phar php php-cgi php-config phpize

# 复制到apache默认的cgi-bin目录下,方便管理

[root@xuexi php]# cp /usr/local/php/bin/php-cgi /usr/local/apache/cgi-bin/

# 在httpd.conf中添加以下行

Action application/x-httpd-php /usr/local/php/bin/cgi-bin/php-cgi

3.2 模块方式

在编译php时,将php5_module模块编译到apache中,例如在编译php时在./configure配置中加上"--with-apxs2=/usr/local/apache/bin/apxs"。

这种交互模式下,httpd在启动时加载并激活php_module。也就是说,php-cgi常驻在httpd进程内部。当动态请求到达时,httpd不用再生成cgi解释器,而是直接将动态请求转发给它内部php-cgi。

配置实用这种交互模式非常简单,只需使用LoadModule加载php_module,再添加对应的MIME处理器即可。

LoadModule php5_module modules/libphp5.so

# 在mime模块中添加对应的类型

<IfModule mime_module>

AddType application/x-httpd-php .php

AddType applicaiton/x-httpd-php-source .phps

</IfModule>

3.3 php-fpm方式

前面说了,php-fpm是php-cgi的进程管理器。这种交互方式实际上是让php-cgi以独立于httpd的方式存在,目前基本使用php-fpm的方式管理php-cgi进程。也就是说,这种模式下,php-cgi和httpd已经分离了,它们的分离意味着请求的动静分离变为可能:httpd和php-fpm分别运行在不同服务器上。动静分离后,压力也分散到各自的服务器上。

要让php-fpm以这种方式运行,需要在编译的./configure配置选项中添加"--enable-fpm"选项。当然,还得启动php-fpm服务。例如:

service php-fpm start

这样php-cgi进程就开放着端口(默认9000)等待httpd转发动态请求。要让httpd能够转发请求到php-cgi上,需要在httpd.conf中关闭正向代理,并设置fastcgi协议代理参数。例如,转发到192.168.100.54主机上的php-fpm。

# 加载代理模块

LoadModule proxy_module modules/mod_proxy.so

LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so

# 添加MIME类型

AddType application/x-httpd-php .php

AddType application/x-httpd-php-source .phps

# 在需要转发的虚拟主机中配置转发代理

ProxyRequests off

ProxyPassMatch ^/(.*\.php)$ fcgi://192.168.100.54:9000/usr/local/apache/htdocs/$1

相关阅读

关键词不能为空
极力推荐

电脑蓝屏_电脑怎么了_win7问题_win10问题_设置问题_文件问题_上犹电脑信息网

关于我们