背景

朋友公司的一台服务器,阿里云ecs,2核4G,centos7.5。 上面运行了一个企业站, 一套erp系统,企业站和erp是找外包团队开发的,环境都是 nginx + php, 对应mysql两个库,和一个redis库。

这台机器我之前也登入进去过,当时是朋友直接跟我说账号密码,目的明确的解决某项问题,之后就没咋关注了。

发现问题

某天(25日晚)朋友跟我讲他的erp系统变得很卡,加载一个列表需要好几秒才出来,让我看看是不是数据变多了, 是不是要升级系统。

然后我就root直接登入了。
用 ps aux 命令,看到了占用CPU和内存较高的任务

[root@localhost ~]# ps -aux --sort -pcpu | head -n 5
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root     19614  101  0.1 2957748 5012 ?        Sl   Sep24 3337:04 ./sysupdate
root     23241 85.8  1.4 808840 56436 ?        Sl   Sep24 2788:44 /etc/networkservice
root     23246 11.7  1.4 855720 56260 ?        SNl  Sep24 382:42 ./networkservice 15
root      9002  0.4  0.9 164616 38248 ?        S<sl Sep03 140:13 /usr/local/aegis/aegis_client/aegis_10_85/AliYunDun
[root@localhost ~]# ps -aux --sort -pmem | head -n 5
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
mysql    21420  0.0  2.6 1516944 101324 ?      Sl   Aug04  30:31 /usr/libexec/mysqld --basedir=/usr --datadir=/var/lib/mysql --plugin-dir=/usr/lib64/mysql/plugin --user=mysql --log-error=/var/log/mariadb/mariadb.log --pid-file=/var/run/mariadb/mariadb.pid --socket=/var/lib/mysql/mysql.sock
root     23241 85.8  1.4 808840 56436 ?        Sl   Sep24 2788:54 /etc/networkservice
root     23246 11.7  1.4 855720 56260 ?        SNl  Sep24 382:44 ./networkservice 15
nobody   16686  0.0  1.0 1276400 39428 ?       S    Aug31   2:11 php-fpm: pool www

sysupdate 和 networkservice 不知道啥玩意,确实是最近起的, 就问了下朋友是不是最近给账号给别人用过, 加了啥服务, 得到回答没有。

- 阅读剩余部分 -

Configuration

首先需要确定影响 php-fpm 子进程数的几个配置项。

# 设置进程管理器如何管理子进程。可用值:static,ondemand,dynamic。必须设置。
# static - 子进程的数量是固定的(pm.max_children)。
# ondemand - 进程在有需求时才产生(当请求时才启动。与 dynamic 相反,在服务启动时 pm.start_servers 就启动了。
# dynamic - 子进程的数量在下面配置的基础上动态设置:pm.max_children,pm.start_servers,pm.min_spare_servers,pm.max_spare_servers。
pm string

# pm 设置为 static 时表示创建的子进程的数量,pm 设置为 dynamic 时表示最大可创建的子进程的数量。必须设置。
pm.max_children int

# 设置启动时创建的子进程数目。仅在 pm 设置为 dynamic 时使用。默认值:min_spare_servers + (max_spare_servers - min_spare_servers) / 2。
pm.start_servers int

# 设置空闲服务进程的最低数目。仅在 pm 设置为 dynamic 时使用。必须设置。
pm.min_spare_servers int

#设置空闲服务进程的最大数目。仅在 pm 设置为 dynamic 时使用。必须设置。
pm.max_spare_servers int

#秒数,多久之后结束空闲进程。 仅当设置 pm 为 ondemand。 可用单位:s(秒),m(分),h(小时)或者 d(天)。默认单位:10s。
pm.process_idle_timeout mixed

#设置每个子进程重生之前服务的请求数。对于可能存在内存泄漏的第三方模块来说是非常有用的。如果设置为 '0' 则一直接受请求,等同于 PHP_FCGI_MAX_REQUESTS 环境变量。默认值:0。
pm.max_requests int

- 阅读剩余部分 -

Keep-Alive 模式

在 Content-Length 和 Transfer Encoding 之前,先要理解 Keep-Alive 模式,这就要提到http1.0协议的缺点。

http1.0协议的主要缺点就是,每个TCP连接只能发一个请求, 每次数据发送完毕,连接就关闭。 如果还要请求其他资源,就必须新建连接。

因为三次握手、慢启动等,TCP连接新建的成本很高。 随着web的发展,需要请求的资源越来越多,这个问题就越来越突出。

在http1.0时代,为了解决这个问题, 有些浏览器在请求时会在请求头里加上一个自定义字段:

Connection: keep-alive

这个字段就是告诉服务器不要关闭TCP连接,以便其他请求复用,但是,这还不是标准字段。

1997年1月, http1.1版本发布,引入了持久连接,即默认情况下TCP连接不关闭,可以被复用,也就是默认 keep-alive 。同时,支持通过 Connection:close 来通知关闭TCP连接。

所以实际上,http1.0协议下客户端和服务端可以通过 Connection: keep-alive 告知对方发送完数据后不要关闭TCP连接,而http1.1协议下默认就是 Connection: keep-alive 持久连接。

示例:

- 阅读剩余部分 -