CGI FastCGI Nginx

守給你的承諾、 提交于 2020-03-12 13:40:28

CGI

什么是CGI

  • CGI全称通用网关接口,是一种让客户端(web浏览器)与web服务器(nginx等)程序进行通信(数据传输)的协议
  • 用来规范web服务器传输到php解释权中的数据类型以及数据格式,包括URL、查询字符串、post数据、http header等,也就是为了保证webserver传递过来的数据是标准格式的
  • CGI可以用任何一种具有标准输入、输出和环境变量的语言编写,如php、perl、tcl等。不同类型语言写的程序只要符合cgi标准,就能作为一个cgi程序与web服务器交互,早期的cgi大多都是c或c++编写的
  • 一般说的cgi指的是用各种语言编写的能实现该功能的程序

CGI程序的工作原理

  • 每次webserver收到index.php这种类型的动态请求后,会启动对应的CGI程序(php的 解析器)
  • php解析器会解析php.ini配置文件,初始化运行环境,然后处理请求,处理完成后将数据按照cgi规定的格式返回给webserver然后退出进行进程
  • 最后webserver再把结果返回给浏览器

CGI程序的特点

  • 高并发时性能较差
    • cgi程序的每一次web请求都会有启动和退出过程,也就是最为人诟病的fork-and-execute模式(每次HTTP服务器遇到动态请求时都需要重新启动脚本解析器来解析php.ini,重新载入全部dll扩展并初始化全部数据结构,然后把结果返回给http服务器)很明显,这样的接口方式会导致php的性能很差,在处理高并发访问时,几乎是不可用的
  • 传统的cgi接口方式安全性较差
  • cgi对php.ini的配置很敏感,在开发和调试的时候相当方便

CGI程序的应用领域

  • 因为CGI为每一次请求增加一个进程,效率很低,所以基本已经不再生产部署时采用。但由于CGI对php配置的敏感性,通常被用在开发和调试阶段。

FastCGI

什么是FastCGI

  • 通过cgi程序的工作原理可以看出:CGI程序性能较差,安全性较低,为了解决这些问题产生了fastcgi
  • fastcgi(快速通用网管接口),主要用来提高cgi程序性能,也是一种让交互程序与web服务器通信的协议
  • fastcgi致力于减少网页服务器与cgi程序之间互动的开销,从而使得服务器可以同时处理更多的网页请求(提高并发访问)
  • 同样的,一般说的fastcgi指的也是各种语言编写的能实现该功能的程序

FastCGI程序的工作原理

  • webserver启动同时,加载fastcgi进程管理器(nginx的php-fpm或者IIS的ISAPI或Apache的Module)
  • FastCGI进程管理器读取php.ini配置文件,对自身进行初始化,启动多个CGI解释器进程(php-cgi),等待来自webserver的连接
  • 当webserver接收到客户端请求时,fastcgi进程管理器选择并连接到一个cgi解释器。webserver会将相关环境变量和标准输入发送到fastcgi子进程php-cgi进行处理
  • fastcgi子进程完成处理后将数据按照cgi规定的格式返回给webserver,然后关闭fastcgi子进程或者等待下一次请求

FastCGI对进程的管理方式

  • Fastcgi会先启动一个master,解析配置文件,初始化执行环境,然后再启动多个worker。当请求过来时,master会传递给一个worker,然后立即可以接受下一个请求。这样就避免了重复的劳动,效率自然提高。而且当worker不够用时,master可以根据配置预先启动几个worker等着;当空闲worker太多时,也会停掉一些,这样就提高了性能,也节约了资源。

FastCGI的特点

  • Fastcgi程序的接口方式采用cs结构,,可以将web服务器和脚本解析服务器分开,独立于web服务器运行,提高web服务器的并发性能和安全性。
    • 提高性能:这种方式支持多个web分发服务器和多个脚本解析服务器的分布式架构,同时可以在脚本解析服务器上启动一个或者多个脚本解析守护进程来动态处理请求,可以让web服务器专一的处理静态请求或者将动态脚本服务器的结果返回给客户端,这在很大程度上提高了整个应用系统的性能。
    • 提高安全性:API方式把应用程序的代码与核心的web服务器连接在一起,这时一个错误的api应用程序可能会损坏其他应用程序或核心服务器,恶意的api应用程序代码甚至可以窃取另一个应用程序或核心服务器的密钥,采用这种方式可以在很大程度上避免这个问题
    • fastcgi的不依赖于任何web服务器的内部架构,因此即使服务器技术的变化,fastcgi依然稳定不变
    • fastcgi程序在修改php.ini配置时可以进行平滑重启加载新配置
      • 所有的配置加载都只在fastcgi进程启动时发生一次,每次修改php.ini配置文件,只需要重启fastcgi程序(php-fpm等)即可完成平滑加载新配置,已有的动态请求会继续处理,处理完成关闭进程,新来的请求使用新加载的配置和变量进行处理
    • fastcgi是较新的标准,架构上和cgi大为不同,是用一个驻留内存的服务进程向网站服务器提供脚本服务。像是一个常驻型的cgi,维护的是一个进程池,它可以一直执行着,只要激活后,不会每次花时间都要去fork一次
    • 不足:因为是在内存中同时运行多进程,所以会比cgi方式消耗更多的服务器内存,每个php-cgi进程消耗7-25兆内存,在进行优化配置php-cgi进程池的数量时要注意系统内存,防止过量

关于cgi和fastcgi的总结

  • cgi和fastcgi都只是一种通信协议规范,不是一个实体,一般说的cgi指的是用各种语言编写的能实现该功能的程序
  • cgi程序和fastcgi程序是指实现这两个协议的程序,可以是任何语言实现这个协议的(php-cgi和php-fpm就是实现fastcgi的程序)
  • cgi程序和fastcgi程序的区别
    • 关于cgi程序
      • cgi使外部程序与web服务器之间交互成为可能。cgi程序运行在独立的进程中,并对每个web请求建立一个进程,这种方法非常容易实现,但效率很差,难以扩展,面对大量请求,进程的大量建立和消亡使得操作系统性能大大下降。此外,由于地址空间无法共享,也限制了资源重用。
    • 关于fastcgi程序
      • 与cgi程序为每个请求创建一个新的进程不同,fastcgi使用持续的进程(master)来处理一连串的请求。这些进程由fastcgi服务器管理,而不是web服务器。当进来一个请求时,web服务器把环境变量和这个页面请求通过一个socket或者tcp connection传递给fastcgi进程。
      • fast-cgi每次处理完请求后,不会kill掉这个进程,而是保留这个进程,使这个进程可以一次处理多个请求。这样每次就不用重新fork一个进程了,大大提高了效率。

php-cgi php-fpm spawn-fcgi

php-cgi是什么

  • php-cgi是使用php实现cgi协议的cgi程序,可以用来管理php解释器
  • php-cgi变更php.ini配置和需重启php-cgi才能让新的配置生效,不可以平滑重启
  • 直接杀死php-cgi进程php就不能运行了

php-fpm

  • php-fpm是使用php编写的php-fastcgi管理器,管理对象是php-cgi程序,不能说php-fpm是fastcgi进程的管理器,因为fastcgi是个协议
  • 修改php.ini之后,php-cgi进程的确是没办法平滑重启的。php-fpm对此的处理机制是新的worker用新的配置,已经存在的worker处理完手上的活就可以歇着了,通过这种机制来平滑过渡
  • php-fpm是对fastcgi协议的实现,是进程管理器,启动时包括master和worker进程两部分,master进程监听端口,接收来自webserver请求,worker进程一般具有多个,每个worker进程都有一个cgi进程解释器,用来执行php代码。
  • php-fpm有两种执行方式, 与Apache一样,它的进程数也是可以根据设置分为动态和静态的,一种是直接开启指定数量的php-fpm进程,不再增加或者减少;另一种则是开始的时候开启一定数量的php-fpm进程,当请求量变大的时候,动态的增加php-fpm进程数到上限,当空闲的时候自动释放空闲的进程数到一个下限。
  • php启动和工作原理
    • 启动phpfpm时,会启动master进程,加载php.ini文件,初始化执行环境,并启动多个worker进程。每次请求来时会将请求传递给worker进程进行处理
  • php平滑重启原理
    • 每次修改完php.ini配置并重启后,会启动新的worker进程加载新的配置,而之前已经存在的进程会在工作完成之后销毁,因此实现平滑重启

PHP运行模式

CGI模式

  • 使用CGI程序将浏览器,web服务器,php解释器连接起来进行数据交换的工具,目前主要用来做开发和调试
  • CGI方式在遇到连接请求(用户请求)先要创建cgi的子进程,激活一个cgi进程,然后处理请求,处理完后结束这个子进程。这就是fork-and-execute模式。所以用cgi方式的服务器有多少连接请求就会有多少cgi子进程,子进程反复加载是cgi性能低下的主要原因。当用户请求数量非常多时,会大量挤占系统的资源内存、cpu时间等,造成效能低下。

FASTCGI模式

  • 最主流的方式大量用于 分布式高并发的环境中
  • nginx+php-fpm

Nginx

server {
    listen       80; #监听80端口,接收http请求
    server_name  www.example.com; #一般存放网址,表示配置的哪个项目
    root /home/wwwroot/zensmall/public/; # 存放代码的根目录地址或代码启动入口
    index index.php index.html; #网站默认首页
    
    #当请求网站的url进行location的前缀匹配且最长匹配字符串是该配置项时,按顺序检查文件是否存在,并返回第一个找到的文件
    location / {
          #try_files,按顺序检查文件是否存在,返回第一个找到的文件
          #$uri代表不带请求参数的当前地址
          #$query_string代表请求携带的参数
          try_files   $uri $uri/ /index.php?$query_string; #按顺序检查$uri文件,$uri地址是否存在,如果存在,返回第一个找到的文件;如果都不存在,发起访问/index.php?$query_string的内部请求,该请求会重新匹配到下面的location请求
    }
    
     #当请求网站的php文件的时候,反向代理到php-fpm去处理
    location ~ \.php$ {
          include       fastcgi_params; #引入fastcgi的配置文件
          fastcgi_pass   127.0.0.1:9000; #设置php fastcgi进程监听的IP地址和端口
          fastcgi_index  index.php; #设置首页文件
          fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name; #设置脚本文件请求的路径
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!