多线程下pymongo连接数过多的问题处理
背景
项目中有个应用,用到了多线程,线程中会有对MongoDB的操作。一般涉及到这种场景,都会小心MongoDB的连接的数量控制。
实现这个应用的时候必然已经考虑这点了,但实际碰到的情况是:多线程的程序运行起来,MongoDB连接数比预期多。
涉及的环境:
- Linux
- Python 2.6.5
- MongoDB 2.0.0
- MongoDB的驱动是pymongo。本文涉及的版本有4个:1.1.1、2.0.1、2.1.1,以及最新的2.2rc1。
过程
简化的代码
先用一段简化的代码来说明下这个问题。
#-*- encoding:UTF-8 -*-import threading import time import pymongo single_conn = pymongo.Connection('mongodb://127.0.0.1', max_pool_size=1)classSimpleExampleThread(threading.Thread):def run(self):print single_conn['fvck'].damnit.count(),self.getName() time.sleep(10)for i in range(100):SimpleExampleThread().start()
代码的大致意思是创建1个MongoDB连接,然后生成100个线程,在线程中会有对MongoDB的操作
具体使用方式如下:
- 编辑上述代码,保存为test_pymongo.py
- 启动MongoDB,确保可以用127.0.0.1访问
- 运行MongoDB自带的命令行工具mongostat,关注conn这一列,这个时候应该数量是1
- 执行测试程序,python test_pymongo.py
- 观察mongostat的conn这一列,猜是多少?2?这是预想的,实际竟然是101
- 确认pymongo版本是2.0.1
怀疑pymongo版本太旧
- 升级到最新的正式版本2.1.1
- sudo pip install pymongo==2.1.1 --upgrade
- 执行测试程序结果一样,已然有连接数过多的问题
确认自己程序
- 确认没问题。上面程序只是个实际程序的简化的代码。
意外确认问题
- 这个这个时候一般会去查看下pymongo的源代码,分析下实现原理
- 偷个懒。刚好停下来没事,随便瞎逛了下MongoDB的缺陷跟踪系统。想可能是不是pymongo的缺陷,刚好搜到了这个缺陷, https://jira.mongodb.org/browse/PYTHON-287
- 这个issues大致意思是每个线程还是会创建一个MongoDB的连接,希望能支持线程间共享1个MongoDB连接
- pymongo预计解决的版本是2.2,一看,竟然刚好是发现改问题的当天发布该版本。果然,当天发布了2.2rc1这个版本
更新到2.2rc1
- 因为不是正式版本,所以单独下载安装
wget https://github.com/mongodb/mongo-python-driver/tarball/2.2rc1 tar xzvf 2.2rc1 cd mongodb-mongo-python-driver-4c7edfc/ sudo python setup.py install python test_pymongo.py
- 但失败了,和2.0.1和2.1.1的表现一样
RTFM
- 查看文档: http://api.mongodb.org/python/2.2rc1/examples/requests.html
- 发现是程序写法不对,修改的代码如下:
#-*- encoding:UTF-8 -*-import datetime import threading import time import pymongo conn = pymongo.Connection('mongodb://127.0.0.1', auto_start_request=False)classMyThread(threading.Thread):def run(self):print conn['fvck'].damnit.count(), datetime.datetime.now(),self.getName() time.sleep(10)with conn.start_request():for i in range(100):MyThread().start()
- 运行程序,连接数符合预期数量是2
- 关键参数是:auto_start_request=False,这个参数看源码历史,貌似从pymongo1.1.1开始移除了,在2.2rc1这个版本又恢复了,但应该有新的用处了吧。
最后
- 问题至此,从项目角度,算是告一段落,如果从纯技术研究角度,还可以继续深入
- 比如:至于pymongo如何处理连接数,谁有兴趣,可以深入下pymongo的源码,貌似可以从这3个py入手,估计可以另起一篇文章来讲解:
- pymongo/connection.py
- pymongo/database.py
- pymongo/pool.py
参考
- https://jira.mongodb.org/browse/PYTHON-287
- http://api.mongodb.org/python/2.2rc1/examples/requests.html
原文地址:http://blog.knownsec.com/2012/04/pymongo-with-threading/
浙公网安备 33010602011771号