PHP-FPM 调优:使用“pm static”获得最佳性能
文章的未经编辑版本最初发布在 HaydenJames.io,并在获得作者许可的情况下在此处重新发布。
让我们快速了解一下如何最好地设置 PHP-FPM 以实现高吞吐量、低延迟以及更稳定地使用 CPU 和内存。 默认情况下,大多数设置都将 PHP-FPM 的 PM(进程管理器)字符串设置为动态,并且还有一些常见的建议可以使用 ondemand
如果您遇到可用内存问题。 但是,让我们根据 php.net 的文档比较这两个管理选项,并比较我最喜欢的高流量设置 — 静态 pm:
pm = dynamic:子进程的数量是根据以下指令动态设置的: pm.max_children
, pm.start_servers
, pm.min_spare_servers
, pm.max_spare_servers
.
pm = ondemand:进程在请求时按需产生,而不是动态的,其中 pm.start_servers
在服务启动时启动。
pm = static:子进程的数量是固定的 pm.max_children
.
查看全球的完整列表 php-fpm.conf
指令以获取更多详细信息。
PHP-FPM Process Manager (PM) 与 CPUFreq Governor 的相似之处
现在,这似乎有点偏离主题,但我希望将它与我们的 PHP-FPM 调优主题联系起来。 好吧,无论是笔记本电脑、虚拟机还是专用服务器,我们都曾在某个时候遇到过 CPU 速度慢的问题。 还记得 CPU 频率缩放吗? (CPUFreq 调控器。)这些设置在 *nix 和 Windows 上都可用,可以通过将 CPU 调控器设置从按需更改为性能来提高性能和系统响应能力。 这一次,让我们比较描述并寻找相似之处:
Governor = ondemand:根据当前负载动态调整 CPU 频率。 跳到最高频率,然后随着空闲时间的增加而降低。
Governor = conservative:根据当前负载动态调整频率。 比按需更逐渐地调整频率。
Governor = 性能:始终以最大频率运行 CPU。
有关详细信息,请参阅 CPUFreq 调控器选项的完整列表。
注意到相似之处了吗? 我想首先使用这个比较,目的是找到最好的方法来写一篇文章,推荐使用 pm static for PHP-FPM 作为你的首选。
使用 CPU 调控器,性能设置是一个非常安全的性能提升,因为它几乎完全取决于服务器 CPU 的限制。 唯一的其他因素是热量、电池寿命(笔记本电脑)和将 CPU 频率永久设置为 100% 的其他副作用。 一旦设置为性能,它确实是您的 CPU 最快的设置。 例如,阅读有关 Raspberry Pi 上的“force_turbo”设置的信息,该设置会强制您的 RPi 板使用性能调节器,在这种情况下,由于 CPU 时钟速度较低,性能改进更为明显。
使用“pm static”来实现服务器的最大性能
PHP-FPM pm static 设置在很大程度上取决于您的服务器有多少可用内存。 基本上,如果您的服务器内存不足,那么 pm ondemand 或 dynamic 可能是更好的选择。 另一方面,如果您有可用内存,则可以通过将 pm static 设置为服务器的最大容量来避免大部分 PHP 进程管理器 (PM) 开销。 换句话说,当你做数学题时, pm.static
应该设置为在不产生内存可用性或缓存压力问题的情况下可以运行的最大 PHP-FPM 进程数。 此外,不要高到让 CPU 不堪重负并且有一堆待处理的 PHP-FPM 操作。
在上面的截图中,这个服务器有 pm = static
和 pm.max_children = 100
它最多使用已安装的 32GB 中的大约 10GB。 注意不言自明的突出显示的列。 在该屏幕截图中,Google Analytics 中大约有 200 个“活跃用户”(过去 60 秒)。 在那个级别,大约 70% 的 PHP-FPM 孩子仍然处于闲置状态。 这意味着无论当前流量如何,PHP-FPM 始终设置为服务器资源的最大容量。 空闲进程保持在线,等待流量高峰并立即响应,而不是必须等待下午生成子进程,然后在之后将其杀死 x pm.process_idle_timeout
到期。 我有 pm.max_requests
设置非常高,因为这是一个没有 PHP 内存泄漏的生产服务器。 您可以使用 pm.max_requests = 0
和 static
如果您对当前和未来的 PHP 脚本有 110% 的信心。 但是,建议随着时间的推移重新启动脚本。 将请求数设置为较大的数字,因为这是为了避免 pm 开销。 所以例如至少 pm.max_requests = 1000
取决于你的数量 pm.max_children
和每秒请求数。
屏幕截图使用 Linux top filtered by ‘u’(用户)选项和 PHP-FPM 用户的名称。 显示的进程数仅为“前”50 个左右(未计算在内),但基本上顶部显示适合您的终端窗口的前统计数据——在本例中,按 %CPU 排序。 要查看所有 100 个 PHP-FPM 进程,您可以使用类似的东西:
top -bn1 | grep php-fpm
何时使用 pm ondemand 和 dynamic
使用 pm dynamic
您可能已经注意到类似以下的错误:
WARNING: [pool xxxx] seems busy (you may need to increase pm.start_servers, or pm.min/max_spare_servers), spawning 32 children, there are 4 idle, and 59 total children
您可能会尝试增加/调整设置,但仍然会看到与此 Serverfault 帖子中某人描述的相同的错误。 在这种情况下, pm.min
太低了,并且因为网络流量随着下降和尖峰而波动很大,使用 pm dynamic
可能很难正确调整。 常见的建议是使用 pm ondemand。 然而,这更糟糕,因为当流量很少或没有流量时,ondemand 会将空闲进程关闭到 0,然后你最终会遇到与流量波动一样多的开销问题——当然,除非你设置了空闲超时非常高……在这种情况下你应该只使用 pm.static
+ 高 pm.max_requests
.
但是,当您有多个 PHP-FPM 池时,PM 动态尤其是按需可以节省您的时间。 例如,在不同池下托管多个 cPanel 帐户或多个网站。 例如,我有一个服务器,有 100 多个 cPanel 帐户和大约 200 多个域,pm.static 甚至 dynamic 都不可能表现良好。 只有 ondemand 表现良好,因为超过三分之二的网站几乎没有流量。 而对于 ondemand,这意味着所有的孩子都将被关闭,从而节省了大量的服务器内存! 值得庆幸的是,cPanel 开发人员解决了这个问题,现在它默认为 ondemand。 以前默认使用动态,这使得 PHP-FPM 在繁忙的共享服务器上不是一个选项。 许多人会使用 suPHP,因为即使在空闲的 cPanel PHP-FPM 池/帐户上,pm 动态也会消耗内存。 很有可能,如果您收到良好的流量,您将不会托管在具有大量 PHP-FPM 池(共享托管)的服务器上。
结论
对于 PHP-FPM,一旦开始处理大量流量,PHP-FPM 的按需和动态流程管理器可能会因为固有的开销而限制吞吐量。 了解您的系统并设置您的 PHP-FPM 进程以匹配您服务器的最大容量。 从…开始 pm.max_children
根据 pm dynamic 或 ondemand 的最大使用率设置,然后增加到内存和 CPU 可以处理而不会不堪重负的程度。 您会注意到,使用 pm static,因为您将所有内容都保存在内存中,随着时间的推移,流量峰值会减少 CPU 峰值,并且您的服务器负载和 CPU 平均值会更平滑。 您的 PHP-FPM 进程的平均大小会因需要手动调整的 Web 服务器而异,因此更自动化的开销进程管理器(动态和按需)是更受欢迎的建议。 希望这是一篇有用的文章。
更新:添加了 A/B 基准比较图。 让 PHP-FPM 进程驻留在内存中有助于提高性能,但要以增加内存使用量为代价让它们处于等待状态。 找到您的设置最佳点。