关于nginx fastcgi_pass php-fpm fastcgi cgi 之间的一些关联

我们知道,nginx作为webserver,本身只能处理静态资源文件;
对于动态的PHP请求,需要调用相应的PHP解释器来执行;
因此需要配置fastcgi_pass,以实现nginx与php-fpm进程间的通信。

nginx与php-fpm进程间的通信有两种方式:

  • 1、TCP
    就是IP加端口;
    优点是可以跨服务器;缺点是相比下面的方法要慢;
    配置示例:
    php-fpm.conf: listen = 127.0.0.1:9000
    nginx.conf: fastcgi_pass = 127.0.0.1:9000
  • 2、UDS
    UDS 就是 UNIX Domain Socket 协议的缩写;
    优点是速度相比TCP要快,因为它不经过传输层(5层网络模型之一);
    缺点是只适用于nginx和php-fpm在同一服务器的场景。
    配置示例:
    php-fpm.cnf: listen = /run/php/php-fpm.sock
    nginx.conf: listen = unix:/run/php/php-fpm.sock

那么,为什么UDS比TCP要快?
一般而言,socket编程,是建立在传输层基础上的,就是上面的第一种通信方式,但在Unix系统上,存在一种特殊的socket,这种socket无需使用传统的IP地址+端口方式,而是直接使用文件来进行程序间的数据交互;

在Unix操作系统中,一切都可以看做是文件,自然包括程序运行的一些信息。因而,可以直接借助于这些程序运行时产生的文件来进行不同程序之间的数据交互,这就是UDS方式(此种socket只能在unix系统上使用)。

UDS方式,对于程序本身来说,只需读取和写入共享的socket文件即可(又分为【StreamSocket-流套接字】和【DatagramSocket-数据包套接字】),可用在两个没有关联关系的进程之间,直接通过socket文件进行数据交互;
时下大火的一种容器技术,docker,和实体机进行数据传输和信息交换使用的也正是UDS。

其特点如下:

  • 1) 传输不经过网络协议栈(也就是那5层网络模型),不需要打包拆包,只是数据间的拷贝;
  • 2) 由于是在本机通过内核通信,不会丢包也不会出现发送包的次序和接收包的次序不一致的问题;
  • 基于以上特点,其传输速度更快,有文章称是TCP的两倍,没有深入了解,不予置评。
    但UDS作为目前比较广泛使用的IPC机制,传输速度更快是肯定的,毕竟网络协议是为不可靠通讯设计的,而IPC机制本质上是可靠通讯,免去了这些繁琐的可靠校验步骤。

UDS与TCP连接方式简单示意

UDS方式
nginx <=> socket <=> php-fpm
TCP本机方式
nginx <=> socket <=> TCP/IP <=> socket <=> php-fpm
TCP跨服务器方式
nginx <=> socket <=> TCP/IP <=> 物理层 <=> 路由器 <=> 物理层 <=> TCP/IP <=> socket <=> php-fpm

nginx使用UDS与php-fpm进程间通信的好处
这种通信方式发生在系统内核里,不会在网络中传播,它不会走到TCP的那一层,直接以stream-socket文件形式通信;
从而避免了频繁创建TCP短链接而导致的 TIME_WAIT 连接过多的问题。

当然了,UDS不能跨服务器也是最明显的缺点之一,至于如何选择,需各位看官自己斟酌。

谈谈php-fpm、fastcgi、cgi之间的关系

CGI (Common Gateway Interface):是一种通用的 Web 服务器和外部应用程序之间进行数据交互的标准协议,它定义了 Web 服务器和外部应用程序之间传递数据的格式和规范。在 CGI 模式下,PHP 程序每次请求都需要启动一个新的进程来处理请求,包括ini,加载扩展配置等,并在请求处理完毕后结束进程,因此效率较低;
FastCGI(Fast Common Gateway Interface):是对 CGI 的一种改进,它可以在进程池中维护多个 PHP 进程,并与 Web 服务器保持长连接,以提高性能。在 FastCGI 模式下,PHP 进程只在启动时创建一次,并保持运行状态,不需要每次请求都重新启动进程;
php-fpm (PHP FastCGI Process Manager):是一个独立的 PHP 进程管理器,可以管理 FastCGI 模式下的 PHP 进程池,并提供进程调度、进程监控、请求处理等功能。php-fpm 可以独立于 Web 服务器运行,也可以与 Nginx、Apache 等 Web 服务器配合使用。

结合括号中的英文全拼就比较容易理解了,简单来说:
CGI 和 FastCGI 是两个协议,或者叫行业规范,FastCGI 又是 CGI 的升级款方案
任何语言编写的程序都可以通过 FastCGI/CGI 协议来提供 Web 服务,不是专属于PHP的,这样理解就很清晰了。

php-fpm是对 FastCGI 这种规范的实现,也就是成品(SAPI)
它会启一个master主进程,初始化执行环境;根据需要(配置文件)fork出多个worker子进程处理请求,这样就避免了重复劳动,效率自然高;
当worker不够用时,master可以根据配置预先启动几个worker等着;当空闲worker太多时,会干掉一些,这样就节约了资源;
当更新配置文件(php.ini)时,新的worker用新的配置,正在处理请求的worker处理完手上的活就下岗,也就实现了平滑重启;

对了,还有个比较迷惑人的 php-cgi,这里也一并说下:
php-cgi 是同时实现了 CGI 和 FastCGI 两种规范协议的成品,它和php-fpm的角色一样。
CGI 和 FastCGI 都是设计方案,php-cgi 和 php-fpm 都是根据方案制作的成品。
并且,php-cgi是亲生的(PHP官方自带),但它不太好用,比如不能平滑重启,修改 php.ini 后需 kiil 掉原来的进程才能生效;
php-fpm虽然好用,怎奈不是亲生,需要用户手动安装,俗称打补丁;
后来佛祖(PHP官方)发现这妖猴有想法,敢打师傅,后面搞不好是个劲敌,索性就收了封个斗战胜佛吧,于是在v5.3.2版本之后继承了进去。

你可能感兴趣的:(nginxphpphp-fpm)