PHP-fpm MongoDB 连接数爆了问题

问题

一天运维报告说,MongoDB连接数报警了,个人比较郁闷,因为我们业务并发不大,平时并发请求才10个不到,而MongoDB连接数有400个,服务有10个。按照常理说连接数不超过100才对噻。

我们的服务架构:nginx+php-fpm。php版本是7.1.16
php-fpm配置采用了pm = dynamic配置

后来运维给出MongoDB连接数客户端分布,发现确实是php占用了大量的连接,一个服务高达40左右。现在可以确定是确实是php占用了大量连接。只有排查原因。

原因

最后在一位公司同事阅读了php7相关源码才发现,php7MongoDB扩展中,php客户端是长连接(及时请求结束,只要php-fpm进程没有杀掉,连接就一直保持,目的是下次请求时减少连接带来的性能消耗),并且没有关闭连接的函数。

解决办法

而我们php-fpm配置中,pm.min_spare_servers = 100pm.max_spare_servers = 200,空闲进程是至少开了100,所以大量空闲连接占用了MongoDB连接。

然后我们根据实际情况,配置改为pm.min_spare_servers = 5pm.max_spare_servers = 10。重新部署后解决问题。连接数降了下了,没有超过100.

总结

在PHP7中,MongoDB 是长连接,一个请求完,对应得php-fpm进程没有被kill掉化,这个连接不会断开,会一直保持。所以要减少连接个数,需要合理设置php-fpm空闲进程数

jiangjun
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
讨论数量: 5

阅读php7源码,牛逼格拉斯

6天前 评论
wanghan

好帖!!!!!!!!!!!!!!!

6天前 评论

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开辟进程连接池 优化这块的功能

5天前 评论
00x00 5天前

感觉这个扩展这样做不太符合大部分 php 应用,因为大部分 php 都不是内存常驻,长连接就是负优化了.
没用过 MongoDB扩展,我也不敢下定论.

5天前 评论
lufeijun1234

阅读源码,确实牛逼格拉斯

5天前 评论

请勿发布不友善或者负能量的内容。与人为善,比聪明更重要!