PHP-FPM模式下可怕的 MongoDB-PHP-Driver 链接池无节制链接问题

@郑昀汇总 建立日期:2013/1
 
问题发生环境:
  • Nginx
  • PHP 5.3.10 as php-fpm extension to nginx
  • mongodb-php-driver 1.2.12
  • MongoDB 2.2
此问题是 MongoDB PHP Driver 1.2.x 的官方特性致使的,描述请看  PHP-202 和   PHP-347 。简单地说,PHP-FPM模式下,每个 PHP Worker 进程都有本身独立的 mongodb 链接池,从而致使链接数极易超标,内存数也随之倍增。
 
一,PHP服务背景:
某个 Web 应用是经过   Nginx+factcgi  运行的 PHP 程序提供服务的。
PHP-FPM的最大子进程数,是经过 php-fpm.conf 的  max_children  参数设置的(或pm=dynamic时由 spare_servers+start_servers 参数综合决定)。这个值曾被设置为 512
 
二,MongoDB服务背景:
mongodb 实例的最大链接数限制能够经过启动参数中的   maxConns  设置:
  • maxConns:默认值取决于系统的限制(如 ulimit 和 file descriptor)。若是没设置这个参数, mongodb 本身不会限制链接数。但,你不能设置超过 20,000 。
通常不刻意设置 maxConns 参数。
 
三,MongoDB PHP Driver 的可怕链接池特性(BUG?)
MongoDB 官方提供的   mongodb-php-driver  在 1.3.0 如下版本(1.2.0~1.2.1x),拥有一个可怕的链接池实现方案,在执行任何查询时,都会从链接池中请求一个链接,完成以后再归还给链接池。这里的完成是指持有该链接的变量离开了它的做用域。
 
PHP-FPM模式下,一个 PHP Web 应用能对 MongoDB instance 创建的并发链接数计算方式以下:
  • 进程数:max-children = 512 ,那么是 512 个进程
  • 一个MongoDB实例对应一个链接池:主站配置了165和166两个副本集实例;
  • 链接池中的链接数:mongodb-php-driver 对此不作任何限制,能够无限增长直到句柄耗尽为止。
—————— 郑昀:此计算方式出自  mongo.connecting.pools ——————
根据 mongodb 官方文档说明, 虽然链接数无限增加理论上是有可能的,但实际观测发现,一个 Web Server 与一个 mongodb 实例的链接数一般会稳定在一个值上,不会有太大的起伏
那么,假设 一个 PHP Web 应用向 mongodb-165 发起的链接数为
750 个,
该 MongoDB 实例为此须要维护的内存数至少为:
750 × 默认10MB =   7.5 GB
 
五,解决办法
迅速升级到 mongodb-php driver 1.3.2。
 
参考文档:
1)2012-12-9,Connection Handling with the MongoDB PHP driver,英文稿中文翻译稿
2)李丹的测试结果:
“再测试一下驱动升级到1.3.2稳定版后的ab结果,发现close效果很明显,很快的链接数就降低到测试以前的数量了。虽然在峰值上大于老的驱动,可是应该能够解决现有线上的高链接持续的问题。”
4)mongodb-java-driver 定义了一个应用与 mongodb 实例能创建的最大链接数,即 (connectionsPerHost × threadsAllowedToBlockForConnectionMultiplier)个链接:
  • mongo.options.connectionsPerHost:每一个Application与 MongoDB 实例能创建的最大物理链接数,默认是10;
  • mongo.options.threadsAllowedToBlockForConnectionMultiplier:能够等待池中有链接可用的最大线程数,默认是5。
5)crazyshell,2012,MongoDB maxConns参数
赠图几枚:
http://ww4.sinaimg.cn/large/61b889f5jw1e0noudfng5j.jpg
相关文章
相关标签/搜索