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

问答 半醒的狐狸 ⋅ 于 2017-11-05 16:02:52 ⋅ 最后回复由 johnlui 2017-11-07 11:09:56 ⋅ 575 阅读

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


问题

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 于 1周前 加精
回复数量: 7
  • 半醒的狐狸
    2017-11-06 09:42:24

    有没有大神帮忙看下?

  • Summer MOD A Life-long learner.
    2017-11-06 15:53:46

    友情帮顶~

  • 半醒的狐狸
    2017-11-06 15:57:43

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

  • KinyouXY
    2017-11-06 22:58:54

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

    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
  • 半醒的狐狸
    2017-11-07 09:29:01

    @KinyouXY 感谢兄弟。

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

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

    仍然非常感谢你!

  • LDL1023
    2017-11-07 11:07:36

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

    1. 新开一台 ECS
    2. https://oneinstack.com/ 这个安装包装一个环境
    3. 同样的代码,同样的操作,在新环境确定一下有没有问题
      如果没问题的话,就对比一下配置~
      PS:不是给 oneinstack 打广告~
  • johnlui
    2017-11-07 11:09:56

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

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

暂无评论~~
  • 请注意单词拼写,以及中英文排版,参考此页
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`, 更多语法请见这里 Markdown 语法
  • 支持表情,使用方法请见 Emoji 自动补全来咯,可用的 Emoji 请见 :metal: :point_right: Emoji 列表 :star: :sparkles:
  • 上传图片, 支持拖拽和剪切板黏贴上传, 格式限制 - jpg, png, gif
  • 发布框支持本地存储功能,会在内容变更时保存,「提交」按钮点击时清空
  请勿发布不友善或者负能量的内容。与人为善,比聪明更重要!
Ctrl+Enter