PHP-FPM CPU 负载高(Laravel、Nginx、PHP 8.2)

PHP-FPM CPU 负载高(Laravel、Nginx、PHP 8.2)

我运行的服务器有 4 个 vCPU、14GB RAM 和 250GB 存储空间。一个工作日(7 小时)内,我每分钟平均收到 400-500 个请求。

我已将 php-fpm 设置增加到最大子服务器数 40、启动服务器数 10、最小备用服务器数 10 和最大备用服务器数 30。然后将其配置为按需配置。

使用时atop -C我可以看到大多数php-fpm进程消耗 1-2% 的 CPU。大多数时候 2/3 的进程开始消耗 66-89% 的 CPU(相当持续)。

当这个变成 4/5+ 个进程时,CPU 会达到 350%^,并且每分钟仅承受大约 400-500 个请求的压力。

有没有办法可以确定是什么原因导致 php-fpm 进程消耗如此高的 CPU?我正在使用它pgbouncer来池化 SQL 连接。这是一个 Laravel 项目,由于它使用 Active Record 设计模式,因此 SQL 查询不是最好的,但在多个进程上使用超过 80% 的 CPU(非常频繁)告诉我有些东西严重未优化或错误,但从 nginx 访问日志中,我看不到在 CPU 峰值期间应该导致它的任何原因 - 看起来像是临时请求,没有导出等。

下面是我看到的一个例子,至少有 3 个进程通常一直占用超过 60% 的 CPU,捕获的这段时间内请求指标约为 200,因此低于平均水平!Nginx 访问日志没有显示任何异常。

完整流程列表示例

任何帮助或关于如何进一步调试的想法都将不胜感激。我正在等待将 App Insights 功能投入生产,以尝试使用 Azure App Insights 隔离问题。

这些php进程很可能是由supervisorctl服务产生的,因为有 5 个线程为队列工作者运行。

我正在使用文件系统进行会话,经过更多研究后,我可以在 nginx 错误日志中看到与 SO 问题相同的内容:https://stackoverflow.com/questions/35891537/laravel-maximum-execution-time-of-30-seconds-exceeded-in-vendor-symfony-finder

vmstat -w 5接近2分钟的输出:

--procs-- -----------------------memory---------------------- ---swap-- -----io---- -system-- --------cpu--------
   r    b         swpd         free         buff        cache   si   so    bi    bo   in   cs  us  sy  id  wa  st
   3    1        60868       302760      1291416      8474048    0    0     3    94    3    2   7   9  83   1   0
   3    0        60868       305652      1291420      8474100    0    0     0   184 3032 11293  22  40  37   0   0
   6    0        60868       307456      1291420      8474152    0    0     0   102 3043 12776  26  40  33   0   0
   1    0        60868       309116      1291420      8474436    0    0     0   235 2904 13905  26  39  34   1   0
   2    0        60868       301588      1291428      8476964    0    0     0  1245 2935 15069  30  40  29   1   0
   3    1        60868       281128      1291432      8490560    0    0     0   196 2627 13892  31  40  29   1   0
   2    0        60868       303012      1291432      8484872    0    0     0   159 3759 13004  21  37  40   2   0
   9    0        60868       301080      1291436      8479384    0    0     0   151 3281 12728  24  41  35   0   0
   5    0        60868       313884      1291436      8478624    0    0     0    94 2999 13096  27  39  33   0   0
   2    0        60868       310636      1291444      8477260    0    0     0    70 3204 11980  24  36  40   0   0
   2    0        60868       309108      1291448      8477488    0    0     0  1542 2982 11453  20  29  50   0   0
   1    0        60868       305752      1291448      8477648    0    0     0    78 3036 9900  18  28  54   0   0
   2    0        60868       303772      1291448      8477816    0    0     0   133 2408 8044  14  18  67   0   0
   3    0        60868       295540      1291448      8477884    0    0     0   158 2482 8559  16  22  61   0   0
   1    0        60868       295684      1291452      8477888    0    0     0   105 2985 10358  20  28  52   0   0
   0    0        60868       295620      1291460      8477884    0    0     0    42 2352 7613  13  17  69   0   0
   1    0        60868       296772      1291464      8478040    0    0     0   134 2751 10899  14  19  67   0   0
   1    0        60868       279304      1291468      8495716    0    0     0   534 2801 9469  15  20  63   2   0
   3    0        60868       304536      1291472      8485952    0    0     0    59 3420 11658  17  22  59   2   0
   1    0        60868       297360      1291476      8480584    2    0     2    97 3079 11568  22  30  48   0   0
   1    0        60868       327652      1291476      8479708    0    0     0   220 2777 8600  16  27  56   1   0

我不确定这些是否准确,因为 ASP 在 Azure 中使用“虚拟磁盘”(因为它是一个 docker 容器)。

答案1

编辑:看来您使用的是 postgres,上面建议的命令等效于这个:

postgres=# select * from pg_stat_activity;

如果您怀疑 SQL 过载且未优化的请求耗时过长,您可能能够以 root 身份在 myqsl 上使用此查询来查看它:

SHOW FULL PROCESSLIST;

通过查看时间列,您可以识别长请求甚至是挂起的请求。

答案2

如果“top”显示 php-fpm 使用了最多的 CPU,那么来自 DBMS 的负载可能很小(后续评论也证实了这是在其他地方)。

查看这里的统计数据(虽然我不熟悉你使用的 top 版本)似乎有非常尽管页面交换不多,但内存使用率很高。您确实需要减少内存使用率。“每分钟大约 400-500 个请求”并不是一个很大的数量 - 特别是考虑到此服务器的大小,但容量问题(这会导致性能问题,然后进入反馈循环)与一次处理的请求数有关(到达率 x 响应时间)。

接下来要检查的是 opcache 的配置和大小是否正确。

如果这些方法不能解决您的问题,那么您将需要开始分析代码。运行分析器的数据捕获需要付出代价。建议您将一小部分流量分离到第二台主机,然后只在那里运行分析器。

相关内容