文章目录(Table of Contents)
简介
最近发现服务器的 CPU
占用过高,甚至到了100%
,导致所有的页面都无法打开。于是使用 htop
命令查看,发现 php-fpm
占用 CPU
过高。于是对 php-fpm
的配置进行了一些修改。后面发现是有同一个 IP
对网站进行了爬取,然后禁用了相关的 IP
。这里进行简单的记录,分别从(1)问题排查;(2)问题解决,这两个方面进行解决。
参考资料
- Nginx 的设置
- 网站通过nginx设置黑/白名单IP限制、国家城市IP访问限制(Nginx 设置 IP 限制)
- Nginx限制或允许IP或IP段访问(单个 IP 或是 IP 段)
- nginx针对某个url限制ip访问,常用于后台访问限制(子网掩码对照表)
- Nginx禁止某IP(段)访问的两种方法(关于设置子网掩码)
- Php-fpm 的设置
问题排查
php slowlog 的查看
因为之前是发现发现 php-fpm
占用 CPU
过高,导致网站卡顿,所以就想着找 php
慢的原因。如果想要查看 php
慢的原因,可以查看 slowlog
,可以进行如下的设置:
- request_slowlog_timeout = 3 # 脚本超时秒数
- slowlog = /var/log/php.log.slow # 记录慢日志路径
这样可以查看 php.log.slow
来查看是哪些任务导致的。这个通常是来查看哪些代码存在问题。对于我这次的问题来说,并没有从这个 slowlog
上找到原因。
进程跟踪
当时除了查看 slowlog
之外,还进行了进程跟踪。也就是找到 CPU
使用率较高的进程。可以使用下面的方法来跟踪进程:
- htop # 找出 CPU 使用率高的 PID
- strace -p PID # 跟踪进程
- ll /proc/PID/fd # 查看该进程处理哪些文件
但是同样的,也是没有找到问题在哪里。同时也是去调整了 php-fpm
的相关设置,还是一直会出现 CPU
占用 100%
的问题。
查看网站 Nginx 日志
在前面我也是尝试了各种方法,但是一直没有解决。于是我看了一下 Nginx
的日志文件。这一看终于是找到了问题的所在。(Nginx
的日志文件通常在 wwwlogs
文件夹下面)。
通过日志我发现,大部分的访问 IP
都来自同一个,相当于这个 IP
占用了服务器的大量资源。那找到了问题终于可以开始解决问题了,只需要禁止指定 IP
的访问即可。
Nginx 的设置
Nginx 配置文件禁用 IP
前面说道,通过查看 Nginx
的日志文件,我们发现出现 CPU
负载过高的原因是某个 IP
频繁的进行访问。于是我们就通过修改 Nginx
的配置文件,从而禁用某些 IP
。
Nginx
的配置文件路径通常在一下的位置:
- /usr/local/nginx/conf/vhost/xxx.conf
我们对其进行编辑,分别使用 allow
和 deny
来允许或是禁止相关的 IP
。
- #白名单设置,allow后面为可访问IP
- location / {
- allow 123.13.123.12;
- allow 23.53.32.1/100;
- deny all;
- }
- #黑名单设置,deny后面接限制的IP,为什么不加allow all? 因为这个默认是开启的
- location / {
- deny 123.13.123.12;
- }
- #白名单,特定目录访问限制
- location /tree/list {
- allow 123.13.123.12;
- deny all;
- }
其中关于单个和多个 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值):
- 255.0.0.0/8
- 255.128.0./9
- 255.192.0./10
- 255.224.0./11
- 255.240.0./12
- 255.248.0./13
- 255.252.0./14
- 255.254.0./15
- 255.255.0./16
- 255.255.128/17
- 255.255.192/18
- 255.255.224/19
- 255.255.240/20
- 255.255.248/21
- 255.255.252/22
- 255.255.254/23
- 255.255.255/24
- 255.255.255.128/25
- 255.255.255.192/26
- 255.255.255.224/27
- 255.255.255.240/28
- 255.255.255.248/29
- 255.255.255.252/30
下面再看一个例子:
- deny 123.0.0.0/8; // 封 123.0.0.1~123.255.255.254 这个段的ip
- deny 123.123.0.0/16; // 封 123.123.0.1~123.123.255.254 这个段的ip
- deny 123.123.123.0/24; // 封 123.123.123.1~123.123.123.254 这个段的ip
- deny all; // 封所有ip
Nginx 服务重启
对 IP 进行禁用之后,对 Nginx
进行重启即可。
- /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
的配置文件,例如下面的位置:
- /usr/local/php/etc/php-fpm.conf
主要对以下的设置进行修改。这里因为我设置了 pm = dynamic
,因此主要对下面的参数进行了修改(可以将 max_children
调整的小一些):
- pm = dynamic
- pm.max_children = 20
- pm.start_servers = 10
- pm.min_spare_servers = 10
- pm.max_spare_servers = 20
- pm.max_requests = 500
- pm.process_idle_timeout = 10s
- request_terminate_timeout = 120
- request_slowlog_timeout = 0
但是如果 max_children
设置的较小,比如 5-10
个,那么 php-cgi
就会很累,处理速度也很慢,等待的时间也较长,占用的 CPU
也很高。
解决网站 502 错误
出现 502
的原因是连接超时,我们向服务器发送请求,由于服务器当前链接太多,导致服务器方面无法给于正常的响应,产生此类报错。我们通过调节 max_requests
来解决 502
报错。
在大量处理请求下,如果该值设置过小会导致 children 频繁的自杀和建立而浪费大量时间,若所有的 children
差不多都在这个时候自杀,则重建前将没有 children
响应请求,于是出现 502
。因此为了解决 502
的问题,我们可以将这个值设置的大一些。
Ubuntu 重启 php 服务
使用以下命令查看 PHP
服务的状态:
- sudo systemctl status php.service
如果该服务已经运行,则会显示“active (running)
”字样。如果未运行,则会显示“inactive (dead)
”字样。
如果 PHP 服务已经运行,你可以使用以下命令重启该服务:
- sudo systemctl restart php.service
这将会重新启动 PHP
服务并加载任何新的配置更改。将 restart
更换为 stop
可以停止服务,更换为 start
则为开始服务。如果你希望在系统启动时自动启动 PHP 服务,可以使用以下命令将该服务添加到系统启动项中(替换为 enable):
- sudo systemctl enable php.service
我们也可以使用下面的命令重启 php-fpm
服务:
- sudo service php-fpm restart
- 微信公众号
- 关注微信公众号
- QQ群
- 我们的QQ群号
评论