PHP-FPM运行原理以及相关配置

PHP-FPM运行原理以及相关配置
一.PHP-FPM运行原理
CGI 是 Web Server 与后台语言交互的协议,有了这个协议,开发者可以使用任何语言处理 Web Server 发来的请求,动态的生成内容。但 CGI 有一个致命的缺点,那就是每处理一个请求都需要 fork 一个全新的进程,随着 Web 的兴起,高并发越来越成为常态,这样低效的方式明显不能满足需求。就这样,FastCGI 诞生了,CGI 很快就退出了历史的舞台。FastCGI,顾名思义为更快的 CGI,它允许在一个进程内处理多个请求,而不是一个请求处理完毕就直接结束进程,性能上有了很大的提高
至于 FPM (FastCGI Process Manager),它是 FastCGI 的实现,任何实现了 FastCGI 协议的 Web Server 都能够与之通信。FPM 之于标准的 FastCGI,也提供了一些增强功能,具体可以参考官方文档:PHP: FPM Installation。
FPM 是一个 PHP 进程管理器,包含 master 进程和 worker 进程两种进程:master 进程只有一个,负责监听端口,接收来自 Web Server 的请求,而 worker 进程则一般有多个 (具体数量根据实际需要配置),每个进程内部都嵌入了一个 PHP 解释器,是 PHP 代码真正执行的地方
从 FPM 接收到请求,到处理完毕,其具体的流程如下:

FPM 的 master 进程接收到请求
master 进程根据配置指派特定的 worker 进程进行请求处理,如果没有可用进程,返回错误,这也是我们配合 Nginx 遇到502错误比较多的原因。
worker 进程处理请求,如果超时,返回504错误
请求处理结束,返回结果
FPM 从接收到处理请求的流程就是这样了,那么 Nginx 又是如何发送请求给 fpm 的呢?这就需要从 Nginx 层面来说明了。

我们知道,Nginx 不仅仅是一个 Web 服务器,也是一个功能强大的 Proxy 服务器,除了进行 http 请求的代理,也可以进行许多其他协议请求的代理,包括本文与 fpm 相关的 fastcgi 协议。为了能够使 Nginx 理解 fastcgi 协议,Nginx 提供了 fastcgi 模块来将 http 请求映射为对应的 fastcgi 请求。

Nginx 的 fastcgi 模块提供了 fastcgi_param 指令来主要处理这些映射关系,下面 Ubuntu 下 Nginx 的一个配置文件,其主要完成的工作是将 Nginx 中的变量翻译成 PHP 中能够理解的变量

除此之外,非常重要的就是 fastcgi_pass 指令了,这个指令用于指定 fpm 进程监听的地址,Nginx 会把所有的 php 请求翻译成 fastcgi 请求之后再发送到这个地址

二.PHP-FPM进程管理
php-fpm进程管理配置为pm参数,可以设置为静态(static)和动态(dynamic)两种。
详细的配置参数有:
pm.max_children:静态方式下开启的php-fpm进程数量。
pm.start_servers:动态方式下的起始php-fpm进程数量。
pm.min_spare_servers:动态方式下的最小php-fpm进程数量。
pm.max_spare_servers:动态方式下的最大php-fpm进程数量

  1. 静态(static)
    进程数自始至终都是pm.max_children指定的数量,pm.start_servers,pm.min_spare_servers,pm.max_spare_servers配置将没有作用。
    对于内存比较吃紧,同时并发量不是很大的应用,可以考虑采用static的方式,这样可以很好的控制php-fpm的所消耗的总内存数,让系统更加 平稳运行。另外由于并发量很小,可以适当的把设置pm.max_requests小一些,以便让php-fpm进程有机会重启,从而释放其占用的内存
  2. 动态(dynamic)
    进程数是动态的,最开始是pm.start_servers指定的数量,如果请求较多,则会自动增加,但不超过 pm.max_children指定的数量,同时保证空闲的进程数不小于pm.min_spare_servers,如果进程数较多,也会进行相应清理, 保证多余的进程数不多于pm.max_spare_servers。

那么,对于我们的服务器,选择哪种执行方式比较好呢?事实上,跟Apache一样,运行的PHP程序在执行完成后,或多或少会有内存泄露的问题。这也是为什么开始的时候一个php-fpm进程只占用3M左右内存,运行一段时间后就会上升到20-30M的原因了。

对于内存大的服务器(比如8G以上)来说,指定静态的max_children实际上更为妥当,因为这样不需要进行额外的进程数目控制,会提高效率。因为频繁开关php-fpm进程也会有时滞,所以内存够大的情况下开静态效果会更好。数量也可以根据 内存/30M 得到,比如8GB内存可以设置为100,那么php-fpm耗费的内存就能控制在 2G-3G的样子。如果内存稍微小点,比如1G,那么指定静态的进程数量更加有利于服务器的稳定。这样可以保证php-fpm只获取够用的内存,将不多的内存分配给其他应用去使用,会使系统的运行更加畅通。

对于小内存的服务器来说,比如256M内存的VPS,即使按照一个20M的内存量来算,10个php-cgi进程就将耗掉200M内存,那系统的崩溃就应该很正常了。因此应该尽量地控制php-fpm进程的数量,大体明确其他应用占用的内存后,给它指定一个静态的小数量,会让系统更加平稳一些。或者使用动态方式,因为动态方式会结束掉多余的进程,可以回收释放一些内存,所以推荐在内存较少的服务器或VPS上使用。具体最大数量根据 内存/20M 得到。比如说512M的VPS,建议pm.max_spare_servers设置为20。至于pm.min_spare_servers,则建议根据服务器的负载情况来设置,比较合适的值在5~10之间。

你可能感兴趣的:(PHP)