PHP-fpm MongoDB 连接数爆了问题
问题
一天运维报告说,MongoDB
连接数报警了,个人比较郁闷,因为我们业务并发不大,平时并发请求才10个不到,而MongoDB
连接数有400个,服务有10个。按照常理说连接数不超过100才对噻。
我们的服务架构:nginx+php-fpm
。php版本是7.1.16php-fpm
配置采用了pm = dynamic
配置
后来运维给出MongoDB
连接数客户端分布,发现确实是php占用了大量的连接,一个服务高达40左右。现在可以确定是确实是php占用了大量连接。只有排查原因。
原因
最后在一位公司同事阅读了php7
相关源码才发现,php7
的MongoDB
扩展中,php客户端是长连接(及时请求结束,只要php-fpm进程没有杀掉,连接就一直保持,目的是下次请求时减少连接带来的性能消耗),并且没有关闭连接的函数。
解决办法
而我们php-fpm配置中,pm.min_spare_servers = 100
,pm.max_spare_servers = 200
,空闲进程是至少开了100,所以大量空闲连接占用了MongoDB
连接。
然后我们根据实际情况,配置改为pm.min_spare_servers = 5
,pm.max_spare_servers = 10
。重新部署后解决问题。连接数降了下了,没有超过100.
总结
在PHP7中,MongoDB
是长连接,一个请求完,对应得php-fpm
进程没有被kill掉化,这个连接不会断开,会一直保持。所以要减少连接个数,需要合理设置php-fpm
空闲进程数
本作品采用《CC 协议》,转载必须注明作者和本文链接
阅读php7源码,牛逼格拉斯
好帖!!!!!!!!!!!!!!!
php7之前 采用的mongo扩展 而该扩展的1.2版本 就默认是持久连接了 请参考手册
MongoClient::__construct
更新日志 1.2版本之前 由于不是持久连接 所有连接会在作用域结束时关闭 1.2版本之后 可以调用扩展封装了close
方法关闭连接php7之后 采用mongodb扩展 这个扩展内置的API没有关闭连接的方法 所以只能通过fpm进程来控制了 实际连接数是由
pm.max_children
控制的 有多少fpm进程就会有多少连接pm.min_spare_servers & pm.min_spare_servers
控制空闲进程数 减少连接占用如果是高负载服务器
pm.max_children & pm.min_spare_servers & pm.min_spare_servers
这几项值又不会设置太低 而持久连接对于高并发来说可以减少IO开销 但是mongodb连接池是由fpm进程维护 这样持久连接数会很高 不知道以后会不会专门为mongodb开辟进程连接池 优化这块的功能感觉这个扩展这样做不太符合大部分 php 应用,因为大部分 php 都不是内存常驻,长连接就是负优化了.
没用过 MongoDB扩展,我也不敢下定论.
阅读源码,确实牛逼格拉斯
在下认为 ,应该在单个请求结束的时候,主动关闭mongoDB连接,而不是修改php-fpm的进程数量, fpm进程的进程数量是结合业务Api的QPS与机器的CPU核数和物理内存来决定的 fpm模式下,没有数据库连接池, 开启长连接又导致连接不释放出现 连接数不够用的问题.
我也遇上了同样的问题,因为服务器的请求有些大,给PHP-FPM设置的是静态运行模式,max_children=300,但是通过命令查询php-fpm进程的时候 进程数随着运行时间在不增加,导致mongoDB的连接数也在不断增加,最终因为mongodb的可连接数不够用,出现链接失败。
我现在有个疑问就是max_children=300,为啥php-fpm的运行进程数有 3380,而且还会随着时间不断增加
在不修改php配置的情况下,怎么优化解决这种问题