我们每天都在写php代码,然后往服务器上一丢,你就发现php文件就运行了,嘿,是不是很神奇,但是有没有想过,php是如何被解释执行的呢?要知道apache,nginx都是不能解析.php文件的;所以想和大家探讨下原理;
首先,安装过lnmp的同学都知道,在安装nginx部署站点的时候,nginx总会带着以下代码
location ~ \.php$ { include fastcgi_params; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name; include fastcgi_params; }
估计菜鸟也能看出来,这句话的意思就是,如果我nginx遇到了.php文件,我就不处理,我就交给php的解释器去处理,所以这就引出了fast-cgi这个东西,你看代码中配置了吧
CGI
再说fast-cgi之前,需要先说cgi,其实cgi就是一个协议,就是语言(php)和服务器(nginx)之间的一个桥梁,就是说,只要nginx处理不了的.php我都通过cgi交给php处理,php处理后把结果给nginx,然后nginx返回给浏览器;
但是cgi有个弊端,就是每次请求都会创建一个cgi进程,然后php解释器会加载php.ini,初始化环境,处理.php,然后请求结束后杀死这个cgi进程,这样效率就极低,所以产生了fast-cgi
Fast-CGI
fast-cgi其实就是cgi的改进,就是常驻进程,每次请求不杀死进程也不创建进程,这样性能上就高了很多(这里需要批评下很多文章博客人云亦云,fastcgi是协议协议协议!!!)
下面图片可以点击放大
百度百科:
wiki:
wiki大致意思,说fast-cgi是一个通用网关的变体,改善cgi的性能问题(高负载下频繁的进程创建销毁),重用了资源,提升了服务器和cgi下程序关联的效率
php-FPM
是一个实现了fast-cgi协议的程序,并且可以实现进程管理 , 每个子进程都会嵌入php的解释器,去解释php代码,一般会有两种进程master和worker,master进程只有一个,负责监听端口,接收来自nginx的请求(一直监听9000端口),work进程则一般有多个,每个进程内部都嵌入一个php解释器,负责解释php代码;看下图
[root@web ~]# ps -ef|grep php-fpm www 2009 13180 0 Aug06 ? 00:00:10 php-fpm: pool www //子进程,负责解释php www 2010 13180 0 Aug06 ? 00:00:10 php-fpm: pool www root 4110 4079 0 12:52 pts/0 00:00:00 grep --color=auto php-fpm root 13180 1 0 Jul25 ? 00:00:24 php-fpm: master process (/usr/local/php/etc/php-fpm.conf) //主进程,负责管理子进程,监听9000端口 www 28694 13180 0 Aug02 ? 00:00:22 php-fpm: pool www
说到这里应该明白了,cgi和fast-cgi是协议和语言无关,php-fpm是实现了fast-cgi的程序,并且监听9000端口
当浏览器请求时,nginx通过location指令(这里有人说是nginx的fast-cgi模块),将所有以php为后缀的文件都交给 127.0.0.1:9000 来处理,也就是php-fpm 的master进程 ,master进程选择并连接到一个子进程去处理php文件,然后返回给nginx,nginx返回给浏览器;这样才算完成了一次请求,注意,这里的子进程数量是由woker_process配置的,一般是auto;
这样我们就把浏览器-nginx-php的流程缕了一遍