「这是我参与11月更文挑战的第10天,活动详情查看:2021最后一次更文挑战」
前面我们说了PHP和web server之间是通过FastCGI协议实现通信的,文章地址
今天我们说一下具体的细节。
Nginx工作方式
当请求到Nginx时,就会根据配置在vhost/*.conf文件中的地址进行处理。
既然Nginx和PHP之间通过FastCGI进行通信,所以Nginx中也实现了FastCGI协议,具体实现就是ngx_http_fastcgi_module模块。ngx_http_fastcgi_module把HTTP 或者 HTTPS 请求数据根据FastCGI协议处理转发给PHP。
location ~ .*\.php
include fastcgi.conf;
fastcgi_pass 127.0.0.1:9000; #监听9000端口
fastcgi_index index.php;
}
然后根据上面fastcgi_pass参数配置的地址,把相关数据转发给PHP。
Nginx通过ngx_http_fastcgi_module模块转发请求有两种方式。一种是通过TCP,采用IP加端口的方式。一种是通过UNIX Socket,不通过网络,但是需要Nginx和PHP在一个服务器中,属于进程间的通信,这种方式比TCP链接的方式要快速,因为不需要验证等操作,但是请求较多时,不太稳定。
方式一实现
php-fpm.conf: listen = 127.0.0.1:9000
nginx.conf: fastcgi_pass 127.0.0.1:9000;
方式二实现
php-fpm.conf: listen = /tmp/php-fpm.sock
nginx.conf: fastcgi_pass unix:/tmp/php-fpm.sock;
PHP工作方式
PHP使用PHP-FPM实现FastCGI协议。PHP—FPM启动时,会创建一个master进程,然后在master进程中创建并监听端口为9000(根据上面所述端口为9000,master可以监听其他的端口,也可以同时监听不同端口)的Socket。然后根据配置的进程管理方式fork出worker子进程等待处理请求。
- PHP-FPM选择并连接到一个worker子进程。处理由Web server传递的环境变量和标准输入。
- worker子进程完成处理后将标准输出和错误信息从同一连接返回Web Server。当worker子进程关闭连接时,请求便处理完成。
- worker子进程接着等待并处理来自web server的下一个连接。
大家都知道PHP有一个全局变量$_SERVER,里面包含了许多服务器的信息,那么这些信息那里来的呢?
Nginx的配置文件中有好多fastcgi参数,其中还包含了一个fastcgi.conf的文件。Nginx转发数据的时候,就会把这些信息发送给PHP,所以PHP能获取$_SERVER中的信息。
大家都知道PHP—FPM是FastCGI进程管理器,在进程管理方面PHP-FPM有三种方式。
- static: 静态管理,在启动时master按照
pm.max_children配置fork出相应数量的worker进程,即worker进程数是固定不变的。 - dynamic: 动态进程管理,首先在PHP-FPM启动时按照
pm.start_servers初始化一定数量的worker,运行期间如果master发现空闲worker数低于pm.min_spare_servers配置数(表示请求比较多,worker处理不过来了)则会fork worker进程,但总的worker数不能超过pm.max_children,如果master发现空闲worker数超过了pm.max_spare_servers(表示闲着的worker太多了)则会杀掉一些worker,避免占用过多资源,master通过这4个值来控制worker数 - ondemand: 在启动时不分配worker进程,等到有请求了后再通知master进程fork worker进程,总的worker数不超过
pm.max_children,处理完成后worker进程不会立即退出,当空闲时间超过pm.process_idle_timeout后再退出
动态进程管理适用于内存空间比较小,或者同时有其他占用内存的需要,这种模式可以合理的利用内存。但是由于链接请求数不定,导致会不断的创建worker进程,或者销毁worker进程。
静态管理的方式适用于内存空间比较大的,根据每个进程使用的内存大小,然后配置固定的进程数量,这种方式最简单,同时性能也最好。
ondemand 模式目前很少使用,因为当请求过来时,创建worker进程时需要时间的,请求数量很大时,会影响性能。
以上是我理解的PHP和Nginx的交互流程。