php-fpm 占用 CPU 过高

王 茂南 2023年6月3日07:59:52
评论
4090字阅读13分38秒
摘要本文主要介绍 php-fpm 的配置,从而尝试解决 CPU 占用过高的问题。同时也会包含 php 服务在 Ubuntu 下如何启动等。

简介

最近发现服务器的 CPU 占用过高,甚至到了100%,导致所有的页面都无法打开。于是使用 htop 命令查看,发现 php-fpm 占用 CPU 过高。于是对 php-fpm 的配置进行了一些修改。后面发现是有同一个 IP 对网站进行了爬取,然后禁用了相关的 IP。这里进行简单的记录,分别从(1)问题排查;(2)问题解决,这两个方面进行解决。

参考资料

 

问题排查

php slowlog 的查看

因为之前是发现发现 php-fpm 占用 CPU 过高,导致网站卡顿,所以就想着找 php 慢的原因。如果想要查看 php 慢的原因,可以查看 slowlog,可以进行如下的设置:

  1. request_slowlog_timeout = 3      # 脚本超时秒数
  2. slowlog = /var/log/php.log.slow  # 记录慢日志路径

这样可以查看 php.log.slow  来查看是哪些任务导致的。这个通常是来查看哪些代码存在问题。对于我这次的问题来说,并没有从这个 slowlog 上找到原因。

 

进程跟踪

当时除了查看 slowlog 之外,还进行了进程跟踪。也就是找到 CPU 使用率较高的进程。可以使用下面的方法来跟踪进程:

  1. htop # 找出 CPU 使用率高的 PID
  2. strace -p PID # 跟踪进程
  3. ll /proc/PID/fd # 查看该进程处理哪些文件

但是同样的,也是没有找到问题在哪里。同时也是去调整了 php-fpm 的相关设置,还是一直会出现 CPU 占用 100% 的问题。

 

查看网站 Nginx 日志

在前面我也是尝试了各种方法,但是一直没有解决。于是我看了一下 Nginx 的日志文件。这一看终于是找到了问题的所在。(Nginx 的日志文件通常在 wwwlogs 文件夹下面)。

通过日志我发现,大部分的访问 IP 都来自同一个,相当于这个 IP 占用了服务器的大量资源。那找到了问题终于可以开始解决问题了,只需要禁止指定 IP 的访问即可。

 

Nginx 的设置

Nginx 配置文件禁用 IP

前面说道,通过查看 Nginx 的日志文件,我们发现出现 CPU 负载过高的原因是某个 IP 频繁的进行访问。于是我们就通过修改 Nginx 的配置文件,从而禁用某些 IP

Nginx 的配置文件路径通常在一下的位置:

  1. /usr/local/nginx/conf/vhost/xxx.conf

我们对其进行编辑,分别使用 allowdeny 来允许或是禁止相关的 IP

  1. #白名单设置,allow后面为可访问IP
  2. location / {
  3.      allow 123.13.123.12;
  4.      allow 23.53.32.1/100;
  5.      deny  all;
  6. }
  7. #黑名单设置,deny后面接限制的IP,为什么不加allow all? 因为这个默认是开启的
  8. location / {
  9.      deny 123.13.123.12;
  10. }
  11. #白名单,特定目录访问限制
  12. location /tree/list {
  13.      allow 123.13.123.12;
  14.      deny  all;
  15. }

其中关于单个和多个 IP 的设置如下:

  • 允许/禁止单个 IP:allow 192.168.0.104; 或是 deny 192.168.0.1;
  • 允许/禁止 IP 段:allow 192.168.0.104/24; 或是 deny 192.168.0.104/24;

后面的 24 表示子网掩码,下面展示了详细的对照表(子网掩码/CIDR值):

  1. 255.0.0.0/8
  2. 255.128.0./9
  3. 255.192.0./10
  4. 255.224.0./11
  5. 255.240.0./12
  6. 255.248.0./13
  7. 255.252.0./14
  8. 255.254.0./15
  9. 255.255.0./16
  10. 255.255.128/17
  11. 255.255.192/18
  12. 255.255.224/19
  13. 255.255.240/20
  14. 255.255.248/21
  15. 255.255.252/22
  16. 255.255.254/23
  17. 255.255.255/24
  18. 255.255.255.128/25
  19. 255.255.255.192/26
  20. 255.255.255.224/27
  21. 255.255.255.240/28
  22. 255.255.255.248/29
  23. 255.255.255.252/30

下面再看一个例子:

  1. deny 123.0.0.0/8;    // 封 123.0.0.1~123.255.255.254 这个段的ip
  2. deny 123.123.0.0/16;   // 封 123.123.0.1~123.123.255.254 这个段的ip
  3. deny 123.123.123.0/24;   // 封 123.123.123.1~123.123.123.254 这个段的ip
  4. deny all;  // 封所有ip

 

Nginx 服务重启

对 IP 进行禁用之后,对 Nginx 进行重启即可。

  1. /etc/init.d/nginx restart # 重启 nginx

 

php-fpm 设置

php-fpm 参数意思

这里介绍 php-fpm 中一些重要的参数的含义:

  • pm = dynamic,对于专用服务器,pm可以设置为static。这个配置表示如何控制子进程,选项有static和dynamic。
    • 如果选择static,则由pm.max_children指定固定的子进程数。
    • 如果选择dynamic,则由pm.max_children、pm.start_servers、pm.min_spare_servers、pm.max_spare_servers 参数决定
  • pm.max_children,在同一时间最大的进程数。一般每个 php-cgi 所耗费的内存为20M左右,4G内存服务器可以设置成 200。这个设置过小网站也容易出现 502 的问题。
  • pm.start_servers,php-fpm 启动时开启的等待请求到来的进程数,默认值为:min_spare_servers + (max_spare_servers - min_spare_servers) / 2。
  • pm.min_spare_servers,在空闲状态下,运行的最小进程数,如果小于此值,会创建新的进程
  • pm.max_spare_servers,在空闲状态下,运行的最大进程数,如果大于此值,会kill部分进程
  • pm.process_idle_timeout,空闲多少秒之后进程会被 kill,默认为10s
  • pm.max_requests,每个进程处理多少个请求之后自动终止,可以有效防止内存溢出,如果为 0 则不会自动终止。设置过小网站容易出现 502 的问题。
  • pm.request_terminate_timeout,单个请求的超时中止时间,超时后会终止进程,nginx发现信号断了,就会给客户端返回502错误。

 

php-fpm 参数设置

找到 php-fpm.conf 的配置文件,例如下面的位置:

  1. /usr/local/php/etc/php-fpm.conf

主要对以下的设置进行修改。这里因为我设置了 pm = dynamic,因此主要对下面的参数进行了修改(可以将 max_children 调整的小一些):

  1. pm = dynamic
  2. pm.max_children = 20
  3. pm.start_servers = 10
  4. pm.min_spare_servers = 10
  5. pm.max_spare_servers = 20
  6. pm.max_requests = 500
  7. pm.process_idle_timeout = 10s
  8. request_terminate_timeout = 120
  9. request_slowlog_timeout = 0

但是如果 max_children 设置的较小,比如 5-10 个,那么 php-cgi 就会很累,处理速度也很慢,等待的时间也较长,占用的 CPU 也很高。

 

解决网站 502 错误

出现 502 的原因是连接超时,我们向服务器发送请求,由于服务器当前链接太多,导致服务器方面无法给于正常的响应,产生此类报错。我们通过调节 max_requests 来解决 502 报错。

在大量处理请求下,如果该值设置过小会导致 children 频繁的自杀和建立而浪费大量时间,若所有的 children 差不多都在这个时候自杀,则重建前将没有 children 响应请求,于是出现 502。因此为了解决 502 的问题,我们可以将这个值设置的大一些。

 

Ubuntu 重启 php 服务

使用以下命令查看 PHP 服务的状态:

  1. sudo systemctl status php.service

如果该服务已经运行,则会显示“active (running)”字样。如果未运行,则会显示“inactive (dead)”字样。

如果 PHP 服务已经运行,你可以使用以下命令重启该服务

  1. sudo systemctl restart php.service

这将会重新启动 PHP 服务并加载任何新的配置更改。将 restart 更换为 stop 可以停止服务,更换为 start 则为开始服务。如果你希望在系统启动时自动启动 PHP 服务,可以使用以下命令将该服务添加到系统启动项中(替换为 enable):

  1. sudo systemctl enable php.service

我们也可以使用下面的命令重启 php-fpm 服务:

  1. sudo service php-fpm restart

  • 微信公众号
  • 关注微信公众号
  • weinxin
  • QQ群
  • 我们的QQ群号
  • weinxin
王 茂南
  • 本文由 发表于 2023年6月3日07:59:52
  • 转载请务必保留本文链接:https://mathpretty.com/15966.html
匿名

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: