V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
whatever93
V2EX  ›  问与答

[求助] 求定位问题点: ThinkPHP 5 环境, PHP -fpm: pool 不释放数据库连接

  •  
  •   whatever93 · 2018-08-01 08:51:18 +08:00 · 4013 次点击
    这是一个创建于 2341 天前的主题,其中的信息可能已经有所发展或是发生改变。
    是这样,我们用的是 nginx+php-fpm,我最近发现服务器上的 php-fpm 连接数据库的数量随时间而增长,一直是 ESTABLISHED 状态,查了 fpm 的 slowlog 没有信息。框架开发同学说用的 ThinkPHP 5 版本,说由框架来控制数据库释放,求大家给点思路……多谢多谢……
    18 条回复    2018-08-01 13:39:18 +08:00
    whatever93
        1
    whatever93  
    OP
       2018-08-01 09:00:42 +08:00
    过不了两天就从 20 多编程 100 多……前几天到了 500 个 ESTABLISHED。。。最后只能重启 php-fpm。但这不是最终方法啊……
    whatever93
        2
    whatever93  
    OP
       2018-08-01 09:03:08 +08:00
    是不是 php 和数据库建立的长连接?
    byteli
        3
    byteli  
       2018-08-01 09:03:11 +08:00 via Android
    pconnect 的原因?
    tomczhen
        4
    tomczhen  
       2018-08-01 09:06:22 +08:00
    数据库这边应该是有闲置释放的时间配置的。
    whatever93
        5
    whatever93  
    OP
       2018-08-01 09:15:00 +08:00
    数据库是 MongoDB
    whatever93
        6
    whatever93  
    OP
       2018-08-01 09:15:10 +08:00
    @tomczhen 数据库是 MongoDB
    torbrowserbridge
        7
    torbrowserbridge  
       2018-08-01 09:19:06 +08:00
    persistent connection
    dawniii
        8
    dawniii  
       2018-08-01 09:21:57 +08:00 via Android
    我记得 php7 的 mongodb 扩展只支持长连接,没有短连接的配置。很无语。。。
    ftpgxm
        9
    ftpgxm  
       2018-08-01 09:34:33 +08:00 via iPhone
    PHPFPM 模式下 MongoDB 连接不会随着请求结束而关闭,可以考虑建立连接池来处理
    whatever93
        10
    whatever93  
    OP
       2018-08-01 09:35:33 +08:00
    @dawniii 用的是 php5,刚查询了一下 php7 连接会自动释放 而 php5 不会
    jsjscool
        11
    jsjscool  
       2018-08-01 09:35:39 +08:00
    php-fpm 的进程管理器改为 static 就行了
    whatever93
        12
    whatever93  
    OP
       2018-08-01 09:53:39 +08:00
    @byteli 是通过 mongodb 驱动连接的
    whatever93
        13
    whatever93  
    OP
       2018-08-01 09:58:54 +08:00
    @jsjscool 超过了连接限制 nginx 那边不会 502 么……
    onion83
        14
    onion83  
       2018-08-01 10:01:35 +08:00   ❤️ 1
    这个不是框架的问题,MongoDB 的驱动 MongoClient 默认建立的就是长连接 persistent connection 且不能直接关闭(而且官方也不推荐你关闭,close 之后可能没啥效果)。

    为什么不能关闭是有原因的,因为 mongodb 的架构了单独实例 (Standalone) 之外,还有副本集架构( ReplicaSet ),这意味着每个 php-fpm 都要每个非隐含节点建立通讯关系,为什么要建立通讯关系,这是因为 Mongodb 有复杂的读策略(read Preference)、读关注(Read Concern),这意味着一开始你往数据库写完数据之后,很可能马上去重数据库读,如果这个时候再去建立连接的话,效率就会非常低,还有如果诸如 Tags、session、事务(4.0) 等特性,每次都要找对应的节点,还有做验活、延时选择等操作,你会发现驱动做的东西简直是太重了,活脱脱就是一个数据库中间件要干得活儿。

    遗憾的是,php-fpm 这种模式下,每个 worker 的连接( m )都是不共享的,这意味着每个 worker 都会 db 创建一个长连接,如果是副本集架构( n ),每个 web 的机器创建的连接数更为高 m*n,驱动干那么重的活儿,还不如一开始建立好长连接,省得每次都折腾。所以不需要太在意,也不要可以可以去关闭它。

    但是,在集群环境下,这个连接数的问题就需要注意了,虽然 mongod 默认支持 100w 连接,但是很可能 linux 系统本身本身没调优过,系统对程序已经做出限制了。例如每个机器开 1024 个 php-fpm,一共 50 台机器,每个 mongod 就要接收 51200 个连接,此时很可能系统已经直接把 mongod 杀了。

    在 30 台以下机器,不需要太关注连接数问题,如果更多,就要考虑在 php-fpm 外再做一层连接池了(遗憾的是,目前还没找到很好的解决方案)。终极的解决办法,可能是直接上分片架构( Sharding ),把 mongos 和 php-fpm 部署在同一机器上,充当连接池。
    whatever93
        15
    whatever93  
    OP
       2018-08-01 10:12:37 +08:00
    @onion83 感谢。。google 了下也没有其它方法了……而没上分片,用的副本集,暂时的解决方法只能是通过 zabbix 监控连接数得到阈值后触发脚本了
    另外,给以后遇到的人一个三方驱动的思路吧……
    https://bbs.csdn.net/topics/392258373
    https://github.com/yuri0229/mongodb-php-driver-dpc
    jsjscool
        16
    jsjscool  
       2018-08-01 10:18:52 +08:00
    @whatever93 static 下的连接数根据自己的 CPU 和内存评估。比如 400, 理论上最多有 400 个 mongod 长连接。生产环境 php-fpm 的 pm 参数建议使用 static。和 nginx 没有任何关系。
    whatever93
        17
    whatever93  
    OP
       2018-08-01 10:26:33 +08:00
    @jsjscool 我试试 多谢
    lolizeppelin
        18
    lolizeppelin  
       2018-08-01 13:39:18 +08:00 via Android
    坑在 f CGI 233
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2554 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 04:23 · PVG 12:23 · LAX 20:23 · JFK 23:23
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.