PHP-FPM 是怎么影响 PHP 连接数据库的速度的?


问题解决了!感谢大家的热情帮助。等我理清这几天纠结的问题再把原因和过程发出来。


最终解决问题是这样的:
根据阿里云的ecs性能指标,我最后看到了每次重启之后,内存占用率是很低的,但当访问了几次之后,内存开始飙高,同时速度也开始变慢。
这个和我的fpm配置有关,我的fmp子进程是静态分配的,于是每一次进程打开,始终占用着内存。
最近太忙,一拖拖了两个月,实在sorry。
file
就是这样,大致原因就是fpm子进程处理请求得到内存资源后,没有重载。我设置了每执行一次就重载,问题就解决了。

问题

PHP-FPM是怎么影响PHP连接数据库的速度的?

引发原因

PHP脚本连接Mysql耗时非常不稳定,最快10ms,最慢1s+。

环境

  • linux是阿里云的ecs,4核/8G/4Mbps/华东1/centOs7
  • Lnmp1.4集成环境包
  • Mysql是阿里云RDS,4核/8G/Mysql5.6/华东1,与ecs内网连接
  • PHP 版本 7.1.5,用PDO_MYSQL扩展,无Mysql扩展

脚本

 <?php 
 // 取毫秒函数
 function getMillisecond() {
     list($t1, $t2) = explode(' ', microtime());
     return (float)sprintf('%.0f',(floatval($t1)+floatval($t2))*1000);
 }
 // 开始时间
 $a = getMillisecond();

 $db = new pdo($dsn,$name,$password); // 连接数据库
 $db = null; // 销毁

 // 耗时
 $b = getMillisecond() - $a;
 echo '<br>'.$b.'ms';
 exit;

尝试

1.排除法

借朋友香港ecs运行同一个脚本,快的时候没有我华东ecs快,但却一直稳定在30-60ms之间,最慢也只要200ms以下,始终稳定。
由此排除数据库和脚本问题,定位问题在服务器上面。

2.php.ini

香港ecs是php5.6,我的是php7.1.5,都用PDO,排除是连接驱动的问题
一一对比两个配置文件,只有一些版本差异,关键参数大致一样,连接驱动也都允许持久连接,排除是配置文件的问题

3.找规律

重启lnmp后,发现访问数据库的速度变快了,我在浏览器疯狂刷新,发现大概到了300左右时,就开始变慢,从原本的50ms以下,涨到700ms+
再次重启服务,反复尝试,的确都在刷新300次左右。

4.fpm

300这个数字,让我想起我的fpm配置,是静态分配子进程300个,即php-fpm有300个进程是长时间运行着的。我把它改成10,重启服务后,发现刷新10次,就开始变慢。
看来这就是规律所在了。
除此之外,我还发现另外一个规律。
当我刷新10次后,访问数据库变慢,但我按慢的速度再访问10次左右,速度又变快了,快了将近20次,然后又变慢,又10次,变快,又20次,变慢……再往后就时快时慢,很难找出规律了。
猜测可能是进程被释放了还是咋滴(但还有一点不明白,如果进程会根据时间释放,我也尝试过半小时候再来刷新,讲道理进程总该释放了吧?但还是慢的。只有重启lnmp服务,才会重新变快。

5.对比

再接着,我虽然不明白原理,但马上去找了香港ecs的fpm配置,发现它对于子进程的配置是动态的,由于服务器配置不同,数字互相是不一样的,我就先按自己的服务器配置计算后分配。

pm = dynamic
pm.max_children = 450 // 允许最大进程数
pm.start_servers = 50 // 服务启动时预先就绪的进程数
pm.min_spare_servers = 5 // 最小空闲进程数
pm.max_spare_servers = 320 // 最大空闲进程数

讲道理,配置上文件和香港ecs已经一样了,重启服务后,却发现,依旧不是想要的结果。
快慢的节奏变成了刷一次快,再刷一次慢,然后这样反复(和香港ecs完全稳定的节奏不一样)。

到这,我已经没有思路了,我在想我可能还有忽略掉php和fpm之间的某种规则,或者是我的整个逻辑存在纰漏。但我实在不知道这个问题该怎么解决了。

跪求走过路过的大神们好心帮个忙,这个问题实在困扰我很久了。

本帖已被设为精华帖!
本帖由 Summer 于 6年前 加精
半醒的狐狸
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 12

本人愚见: 有几个排查点希望能帮到你

  1. 一个php-fpm进程大概是占用内存大概在20-30M之间,所以 ps -ef | grep php-fpm | grep -v grep | wc -l
    然后用检测出来的数字乘以 20-30M之间的数字, 这样看看内存是否够用
  2. 用free -m 进一步判断内存的使用量
  3. 如果数据库和应用在同一台服务器上的话, 注意pdo链接的时候用localhost 地址 不要用 服务器的内网ip(我吃过这个亏)
  4. 最后一点就是如果上面的点都解决不了你的问题的话, 在你频繁链接mysql的时候用iostat看看系统io
6年前 评论

RDS 四核8G 太有钱了。。。。

目测还是 php-fpm 配置问题,可以仔细研究一下。以及,PDO_MYSQL 只是三种 API(mysql, mysqli)的一种,底层驱动有两种:mysql, mysqlnd,可以试试调整底层驱动。从现象看,是 php-fpm 和 mysql 服务器保持 tcp 长连接的问题。

6年前 评论
Summer

友情帮顶~

6年前 评论
LDL1023

我猜很大概率是环境配置的问题...
我的一个无脑思路:

  1. 新开一台 ECS
  2. https://oneinstack.com/ 这个安装包装一个环境
  3. 同样的代码,同样的操作,在新环境确定一下有没有问题
    如果没问题的话,就对比一下配置~
    PS:不是给 oneinstack 打广告~
6年前 评论
半醒的狐狸

有没有大神帮忙看下?

6年前 评论
半醒的狐狸

@Summer 哇,感谢!这个问题已经困扰我很久,跪求大神们帮忙解决下!

6年前 评论
半醒的狐狸

@KinyouXY 感谢兄弟。

我在排查过程中,有一直在查看fpm的进程数,基本就在我设置的那个数。

另外内存肯定是够用的,还有好多g是空的。

仍然非常感谢你!

6年前 评论
leung0826

找到原因说一声哈

6年前 评论

之前遇到一个问题,哪怕只是渲染一个简单静态html页面,刷几百次之后服务器就会挂掉,找了很久也没找到原因;
然后就换了一台服务器了

6年前 评论
php炎黄

大佬 如何实现重载的?

6年前 评论

pm.max_requests 设置的多少?

不会是1吧。。。。。。。。。。。。。。。。。。。

6年前 评论
青春不留白 1年前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!