php-fpm 和 nginx 出现奇怪的性能波动

php-fpm 和 nginx 出现奇怪的性能波动

我正在对 Web 服务进行负载测试。这是一个在 php-fpm 和 nginx 上运行的 php 应用程序,带有 fastcgi。有一个仅用于小读取的 MySQL 后端。

我总是看到一种奇怪的模式:性能稳定,并且随着流量的增加而可预测地增加,但在峰值时变得不稳定:CPU 使用率不断波动。

以下是我看到的性能模式(以 可视化nmon):

在此处输入图片描述

下降总是与我的负载测试工具 - locust.io - 在完成达到我为测试设置的峰值水平时的短暂停顿相吻合。

我的假设:在这短暂的一瞬间,php-fpm主进程认为负载已经消失并开始杀死工作者进程;当流量在片刻之后再次全面恢复时,它无法足够快速地做出反应。

我不太明白为什么它永远无法重新回到正轨:我看到这种波动在负载均衡器后面的所有 4 个应用程序服务器上无限期地存在。

这是我的 php-fpm 池配置:

[www]
user = www-data
group = www-data
listen = /var/run/php5-fpm.sock
listen.group = www-data
listen.mode = 0660
pm = dynamic
pm.max_children = 100
pm.start_servers = 40
pm.min_spare_servers = 40
pm.max_spare_servers = 100
pm.max_requests = 10000

我已经确认这不是数据库的问题——在 MySQL 读取从属服务器的数量增加一倍后,我看到了完全相同的行为。

是什么原因造成的?我该如何阻止它?

编辑:

下面是一张图表,展示了我所看到的情况。请注意,失败率通常会在 user_count 达到峰值时达到峰值,然后逐渐回落。

用户计数与失败率

答案1

您的内存管理怎么样?最近几周我做了一些类似的测试,并将一台服务器的内存发挥到了极限。我看到内存发生了很大变化。在我的例子中,大量数据被带入交换区而不是 RAM 来处理负载。经过一次测试后,我得到了一个非常奇怪的结果,不再使用 RAM,所有内容都转移到了交换区。也许这就是以下请求变慢的原因。

这是负载测试后我的交换的示例图像 在此处输入图片描述

答案2

磁盘 IO 和锁定发生了什么?假设您的进程受 CPU 限制,直到这种情况发生变化,则说明其他进程很忙,最有可能是您的磁盘。

您是否达到了导致您开始交换的内存限制?您的 PHP 进程使用了​​多少 RAM(RSS)?您有多少可用 RAM?如果您减少 PHP 进程的数量,是否会出现类似的性能波动?波动出现在什么水平?

请注意,该值pm.max_children = 100可能太高了。除非您正在处理长时间运行的请求(如大下载),否则最好将其大大降低。我犹豫是否要在不知道系统正在做什么的情况下指定一个数字,但 5-40 范围内的值可能会更好。pm.max_requests 也可能太高了。如果该值超过 100 左右,您可能会发现您获得的好处很少,而且更可能会出现严重的性能下降,并且如果 php 运行的内容变化很大且消耗内存,或者您有内存泄漏,那么您最好将其进一步降低。如果您真的不知道什么有效,请从每个设置(大约 30)开始进行实验。

PHP 会生成会话吗?它们是如何存储的?如果它们在文件系统上,那是什么类型的文件系统?在某些情况下,锁定它们所在的目录会造成瓶颈。使用散列目录结构或使用 memcached 等可以帮助解决这个问题。

strace 针对 PHP 进程报告运行了哪些操作,哪些操作占用了时间?您可以使用以下复合命令查看:

(ps wwaux | grep '^www-data.*php' |  awk '{print $2}' \
  | xargs -n 1 -P 32 strace -r -p ) 2>&1 
  | perl -ne '($n) = /^ *(\d*\.\d*)/; print "$n\t$_" if ((defined $n) and ($n > 0.01))'

相关内容