PHP与Nginx的交互

283 阅读7分钟

现在php与nginx基本上是通过php-fpm来实现的,Nginx ("engine x") 是一个高性能的HTTP和反向代理服务器,也是一个IMAP/POP3/SMTP服务器。那php-fpm又是什么?我们先了解几个词汇:cgi,fastcgi协议

1.cgi是什么

早期的webserver只处理html等静态文件,但是随着技术的发展,出现了像php等动态语言。

webserver处理不了了,怎么办呢?那就交给php解释器来处理吧!
交给php解释器处理很好,但是,php解释器如何与webserver进行通信呢?

为了解决不同的语言解释器(如php、python解释器)与webserver的通信,于是出现了cgi协议。只要你按照cgi协议去编写程序,就能实现语言解释器与webwerver的通信。如php-cgi程序。

fast-cgi的改进

有了cgi协议,解决了php解释器与webserver通信的问题,webserver终于可以处理动态语言了。
但是,webserver每收到一个请求,都会去fork一个cgi进程,请求结束再kill掉这个进程。这样有10000个请求,就需要fork、kill php-cgi进程10000次。

于是,出现了cgi的改良版本,fast-cgi。fast-cgi每次处理完请求后,不会kill掉这个进程,而是保留这个进程,使这个进程可以一次处理多个请求。这样每次就不用重新fork一个进程了,大大提高了效率。

2.php-fpm是什么

php-fpm即php-Fastcgi Process Manager.
php-fpm是 FastCGI 的实现,并提供了进程管理的功能。
进程包含 master 进程和 worker 进程两种进程。
master 进程只有一个,负责监听端口,接收来自 Web Server 的请求,而 worker 进程则一般有多个(具体数量根据实际需要配置),每个进程内部都嵌入了一个 PHP 解释器,是 PHP 代码真正执行的地方。

3.nginx和php-fpm是如何结合

要搞清楚nginx和php-fpm是如何结合的,首先要搞清楚他们是怎么配置在一起的,主要有个配置文件:

(1)nginx的虚拟主机配置

server {
    listen       80; #监听80端口,接收http请求
    server_name  www.example.com; #就是网站地址
    root /usr/local/etc/nginx/www # 准备存放代码工程的路径
    #路由到网站根目录www.example.com时候的处理
    location / {
        index index.php; #跳转到www.example.com/index.php
        autoindex on;
    }   
 
    #当请求网站下php文件的时候,反向代理到php-fpm
    location ~ \.php$ {
        include  fastcgi_params; #加载nginx的fastcgi模块
        fastcgi_pass unix:/var/run/php/php7.1-fpm.sock; #nginx 转发请求到php-fpm
    }
 }

我们知道nginx没有解析php的能力,所以他通过实现fastcgi协议,通过fastcgi_pass的配置把请求给php-fpm

完整流程:

php-cgi进程解释器

php-cgi是php的cgi协议进程解释器,每次启动时,需要经历加载php.ini文件->初始化执行环境->处理请求->返回内容给webserver->php-cgi进程退出的流程。

fastcgi协议:

fastcgi协议是对cgi协议效率提升的补充,主要是针对每次请求过来时都需要启动一个cgi解释器进程的优化,不再需要cgi解释器进程每次收到webserver请求后都需要重新加载php.ini文件和初始化执行环境。

也有的文章说的是:php-cgi是早期php官方出品的fastcgi管理器,不支持平滑重启,改了php.ini就要kill掉原来的php-cgi再重新启动才能生效;不支持动态worker调度,只能一开始指定要起几个worker。

php-fpm是从5.3.3才加入的fastcgi进程管理器,加入了动态调度功能,可以根据请求来访压力变化动态增减worker进程数量;支持reload指令,让worker进程在完成当前请求后重启,并应用php.ini新配置。php-fpm和php-cgi都链接了php解释器,彼此没有相互依赖。PHP里把解释器分解成许多模块,php、php-cgi、php-fpm只是入口。PHP-FPM内置PHP解释器,不需要也不会去调用PHP-CGI。PHP-FPM和PHP-CGI是完全独立的两个东西,谁也不会去调用谁.

php5.3.3之前,php-fpm(第三方编译)是管理器,php-cgi是解释器

php5.3.3之后,php-fpm(官方自带),master 与 pool 模式。php-fpm 和 php-cgi 没有关系了。php-fpm又是解释器,又是管理器

这里简单的说一下php-cgi与php-fpm的关系:

1、Linux下安装好php,会有“php”和“php-cgi”这两个可执行程序(在win下是php.exe和php-cgi.exe),这两个程序其实基本上是一样的,都是“php解释器”(就是php的核心),就是能把你写的php代码进行解释最后输出代码的结果。

2、既然php与php-cgi的功能都是“php解释器”,那它们的不同点在哪?不同点就在于提供的接口不同,php属于cli接口(client客户端接口),只能用命令去调用,而php-cgi则提供了fastCGI接口,fastCGI接口是一种“网络接口”,你可以通过网络的方式去调用它,比如nginx调用php-cgi可以用“fastcgi_pass 127.0.0.1:9000;”这样调用,其中的“127.0.0.1”你完全可以换成非本机ip,比如你在B服务器(ip为23.45.67.78)的9000上运行了一个php-fpm,那么你A服务器的nginx可以用“fastcgi_pass 23.45.67.78:9000;”这样去调用B服务器的php-fpm。

3、解释了php与php-cgi的区别,再来说php-cgi与php-fpm的区别。简单来说,就是php-cgi有很多缺点(具体是什么很多人回答,我就不说了),有些大牛觉得完全可以改进它,于是就有人写出了php-fpm,最初php-fpm是需要调用php-cgi来解释php代码的,php-fpm只起到进程管理的作用,但是因为php-fpm这个民间第三方写的工具实在比php-cgi好太多了,php官方在php5.4时就把它集成到了php官方发布的包中,并且php-fpm不需要再依赖php-cgi,直接把php解释器的功能集成进php-fpm了。

4、所以现在的php-fpm跟php和php-cgi都能解释php代码,只不过,php(强调一下这是可执行文件,在win下叫php.exe)是cli模式调用,即用命令调用,而php-cgi和php-fpm可以通过“网络”来调用,而所使用的网络协议叫“fastCGI协议”,只不过php-fpm比php-cgi高级很多。(注意,有人说php-cgi不支持fastCGI协议,我这里必须再次强调,这个说法是错的,具体请看我这篇文章www.xiebruce.top/606.html中的两个实例证明)。需要强调一下:win不支持php-fpm,因为php-fpm是使用Linux的fork()来做的,所以win下面基本上还是使用php-cgi,当然有人用“Cygwin”这个软件可以在win下模拟Linux的fork(),但如果你是本地开发环境就没必要这么做了,用win10做开发的我建议你们考虑一下wsl

总结:php-fpm就是php-cgi的升级版(并非简单的在php-cgi的基础上升级,而且通过直接采用第三方代码的方式,实质上是用php-fpm“替换”了php-cgi,而不是简单的升级,但我们可以理解为升级),总之,现在在linux服务器上用php-fpm即可,当然也有人用apache,用apache的话,php可以作为apache的模块,当然也可以用php-fpm的方式,因为apache有支持fastCGI的模块,让它可以像nginx一样,把用户请求的php文件转交给php-fpm处理。

既然php-cgi和php-fpm都是php解释器,并且php-fpm还能作为进程管理器,那php-cgi存在的意义是什么呢,毕竟它也是存在php之中的。我觉得是因为windows要用吧,总之现在的公司对外提供服务的Linux服务器,肯定是用php-fpm而不是php-cgi的。

参考文章:

www.imooc.com/wenda/detai…

blog.csdn.net/zjuwangleic…

blog.csdn.net/weixin_4374…

www.zhihu.com/question/30…

www.cnblogs.com/itxiongwei/…

segmentfault.com/q/101000000…

www.zhihu.com/question/55…