为什么PyMongo 3会出现ServerSelectionTimeoutError错误?

73

我正在使用:

  • Python 3.4.2
  • PyMongo 3.0.2
  • 运行 mongod 2.6.9 的 mongolab
  • uWSGI 2.0.10
  • CherryPy 3.7.0
  • nginx 1.6.2

uWSGI 启动参数:

--socket 127.0.0.1:8081 --daemonize --enable-threads --threads 2 --processes 2

我只设置了一次MongoClient:

self.mongo_client = MongoClient('mongodb://user:pw@host.mongolab.com:port/mydb')
self.db = self.mongo_client['mydb']

我尝试将一个JSON字典保存到MongoDB:

result = self.db.jobs.insert_one(job_dict)

它通过执行同一个代码路径到mongodb的单元测试来工作。然而,当我使用HTTP POST通过CherryPy和uWSGI执行时,我得到了这个:

pymongo.errors.ServerSelectionTimeoutError: No servers found yet

为什么在通过CherryPy和uWSGI运行时会出现这种行为?这也许是PyMongo 3中的新线程模型吗?
更新:
如果我使用CherryPy内置服务器而不是uWSGI和nginx运行,则insert_one()可以正常工作。
更新1/25 4:53 pm EST:
在PyMongo中添加了一些调试后,看起来topology._update_servers()知道server 'myserver-a.mongolab.com'的server_type = 2。但是,server_description.known_servers()对于server 'myserver.mongolab.com'具有server_type = 0
这导致以下堆栈跟踪:
result = self.db.jobs.insert_one(job_dict)
File "/usr/local/lib/python3.4/site-packages/pymongo/collection.py", line 466, in insert_one
with self._socket_for_writes() as sock_info:
File "/usr/local/lib/python3.4/contextlib.py", line 59, in __enter__
return next(self.gen)
File "/usr/local/lib/python3.4/site-packages/pymongo/mongo_client.py", line 663, in _get_socket
server = self._get_topology().select_server(selector)
File "/usr/local/lib/python3.4/site-packages/pymongo/topology.py", line 121, in select_server
address))
File "/usr/local/lib/python3.4/site-packages/pymongo/topology.py", line 97, in select_servers
self._error_message(selector))
pymongo.errors.ServerSelectionTimeoutError: No servers found yet

2
我在类似的设置中也遇到了这个问题。你有找到答案吗? - Greg
还没有...还没开始调试。 - drfence
1
需要我开始悬赏吗?你能回答后续的问题吗?我自己完全卡住了。 - Greg
这有用吗?http://blog.fejes.ca/?p=2496 我不确定它如何适用于uwsgi? - Greg
赏金会很棒。我尝试在MongoDB谷歌群组中发布,但我的问题从未被发布。 - drfence
显示剩余4条评论
30个回答

75
我们正在调查这个问题,它被跟踪在PYTHON-961中。您可以通过在创建MongoClient实例时传递connect=False来解决该问题。这会延迟背景连接直到尝试第一个数据库操作,避免我怀疑是MongoClient监视线程的启动和多进程分叉之间的竞争条件。

11
这可能是一个愚蠢的问题,但具体来说这是如何完成的? - SARose
4
如果我们在mongodb中使用身份验证,那么这个解决方案就会失败。是否有其他解决方案? - Arun K
3
这对我没有用 - 在Ubuntu 18.04下使用Python 3.6.7的pymongo 3.7.2 - 可以连接并执行获取操作,但在尝试进行简单插入时会出现ServerSelectionTimeoutError异常。调试器显示在连接资源的所有三个阶段中都使用相同的SSL certfile引用。 - user302761
4
@SARose,mongo = MongoClient(MONGO_CONNECTION_STRING, connect=False) - WebSpence
@MichealShallop,你最终解决了这个问题吗?我也遇到了同样的问题。 - keynesiancross

30

如此提到:https://dev59.com/LLDma4cB1Zd3GeqPDu7A#54314615

我在连接字符串中添加了?ssl=true&ssl_cert_reqs=CERT_NONE,这解决了问题。

因此,不再是:

connection_string = "mongodb+srv://<USER>:<PASSWORD>@<CLUSTER>/<COLLECTION>"

我写道:

connection_string = "mongodb+srv://<USER>:<PASSWORD>@<CLUSTER>/<COLLECTION>?ssl=true&ssl_cert_reqs=CERT_NONE"

(请注意,如果您的连接字符串中有其他参数,则需要将?更改为&


2
使用 pymongo==3.11.3 解决了我的问题。 - MartinKondor
使用Flask-Pymongo 2.3.0,为我解决了这个问题。 - Arindam
3
我的问题也解决了。pymongo==3.12.3 - abdadeel

17

我不确定您是否正在使用与AWS云服务相配合的MongoDB。但是如果您正在使用,我发现您必须指定要访问MongoDB的IP地址。

所以您需要做的是添加主机服务器的IP地址以允许访问。

在MongoAtlas中,可以在此页面完成此操作 enter image description here

我知道已经有解决相同问题的方案,但我没有找到帮助我情况的解决方案,所以想发布这篇文章,以便其他人在面临与我相同问题时能够受益。


1
不是完全使用AWS,但我遇到了IP地址的问题。谢谢! - ShivCK

14

我通过将 pymongo 从 3.0 降级到 2.8 来解决了这个问题。不知道发生了什么。

   flask/bin/pip uninstall pymongo
   flask/bin/pip install pymongo==2.8

9
使用以下命令安装 pymongo 版本为 2.8 并升级:pip install pymongo==2.8 --upgrade - drgarcia1986
1
截至2016年11月22日,在Debian Jessie上(即pymongo 3.3.x和最新的mongodb-org,例如3.2),即使使用connect=False标志,也会出现相同的错误。 将pymongo降级为2.8可以解决这个问题。 - comte
1
我使用了 pymongo==3.7.2,然后卸载了它并安装了 pymongo==2.8。但是这对我没有起作用。 - Sashini Hettiarachchi

7

我曾经遇到过Pymongo 3.5的同样问题。结果发现,将localhost替换为127.0.0.1或mongodb实例对应的IP地址可以解决这个问题。


也适用于我的情况(pymongo==3.6,motor) - Bruno Gelb

5
我通过安装dnspython解决了这个问题(pip install dnspython)。问题是:“必须安装“dnspython”模块才能使用mongodb+srv:// URI”。

4

前往Atlas控制台>网络访问,然后添加客户端IP地址, 例如0.0.0.0/00 (注意:所有客户端IP都可以访问您的数据库)

网络访问页面


3

在我的情况下

  • 我使用的是Mongo Atlas
  • 路由器重启后,我获得了另一个IP地址

因此,我必须通过在Mongo Atlas设置中 将该IP地址添加到白名单

MongoAtlas website -> Network Access -> IP Whitelist -> Add IP Address -> Add Current IP Address

然后等待IP地址的状态更改为“活动”,然后尝试再次运行应用程序。

如果您正在使用repl.it服务器进行托管,只需添加您用于配置服务器的主机IP地址,对我来说是0.0.0.0,这是最常见的IP地址。


2

今天我遇到了同样的异常。在我的情况下,代理设置可能会阻止连接,因为我可以通过更改我的wifi来建立与mongodb的成功连接。即使这个问题已经被标记为解决了,它仍然有望为其他人缩小问题范围。


1

pymongo 3在实例化客户端时不会告诉您连接是否失败。您可能没有连接。

https://api.mongodb.com/python/3.5.1/api/pymongo/mongo_client.html

现在,如果连接不可用,它不再引发ConnectionFailure异常... 您可以通过以下方式检查服务器是否可用:

from pymongo.errors import ConnectionFailure
client = MongoClient()
try:
    # The ismaster command is cheap and does not require auth.
    client.admin.command('ismaster')
except ConnectionFailure:
    print("Server not available")

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接