使用PyMongo连接Azure Cosmos MongoDB无服务器数据库超时求助
问题:无法用pymongo连接Azure Cosmos DB(MongoDB引擎无服务器分片)
问题详情
创建了采用MongoDB引擎的Azure Cosmos DB(RU无服务器分片),尝试通过Python的pymongo库连接查询,但始终无法成功:
- 已测试MongoDB Server兼容版本3.6和7.0
- 排除防火墙问题(多网络环境测试)
- 使用
azure-cosmos库可正常连接,但该库不适用于MongoDB引擎场景 - 尝试过多个pymongo版本,均出现
ServerSelectionTimeoutError超时错误
使用的连接字符串格式:
mongodb://{user_name}:{primary_key}@{service_name}.mongo.cosmos.azure.com:10255/?ssl=true&replicaSet=globaldb&retrywrites=false&maxIdleTimeMS=120000&appName=@{service_name}@
测试代码:
import pymongo CONN_STRING = "mongodb://etc...." # 替换为实际连接字符串 client = pymongo.MongoClient(CONN_STRING) client.list_database_names()
报错信息:
{ "name": "ServerSelectionTimeoutError", "message": "{service_name}.mongo.cosmos.azure.com:10255: timed out, Timeout: 30s, Topology Description: <TopologyDescription id: 6734b32d878003e1a30f46fb, topology_type: Single, servers: [<ServerDescription ('{service_name}.mongo.cosmos.azure.com', 10255) server_type: Unknown, rtt: None, error=NetworkTimeout('{service_name}.mongo.cosmos.azure.com:10255: timed out')>]>", "stack": "--------------------------------------------------------------------------- ServerSelectionTimeoutError Traceback (most recent call last) Cell In[17], line 1 ----> 1 client.list_database_names() File ...\\Lib\\site-packages\\pymongo\\mongo_client.py:1918, in MongoClient.list_database_names(self, session) 1908 def list_database_names(self, session=None): 1909 \"\"\"Get a list of the names of all databases on the connected server. 1910 1911 :Parameters: (...) 1915 .. versionadded:: 3.6 1916 \"\"\" 1917 return [doc[\"name\"] -> 1918 for doc in self.list_databases(session, nameOnly=True)] File ...\\Lib\\site-packages\\pymongo\\mongo_client.py:1899, in MongoClient.list_databases(self, session, **kwargs) 1897 cmd.update(kwargs) 1898 admin = self._database_default_options(\"admin\") -> 1899 res = admin._retryable_read_command(cmd, session=session) 1900 # listDatabases doesn't return a cursor (yet). Fake one. 1901 cursor = { 1902 \"id\": 0, 1903 \"firstBatch\": res[\"databases\"], 1904 \"ns\": \"admin.$cmd\", 1905 } File ...\\Lib\\site-packages\\pymongo\\database.py:755, in Database._retryable_read_command(self, command, value, check, allowable_errors, read_preference, codec_options, session, **kwargs) 750 def _cmd(session, server, sock_info, slave_ok): 751 return self._command(sock_info, command, slave_ok, value, 752 check, allowable_errors, read_preference, 753 codec_options, session=session, **kwargs) --> 755 return self.__client._retryable_read( 756 _cmd, read_preference, session) File ...\\Lib\\site-packages\\pymongo\\mongo_client.py:1460, in MongoClient._retryable_read(self, func, read_pref, session, address, retryable, exhaust) 1458 while True: 1459 try: -> 1460 server = self._select_server( 1461 read_pref, session, address=address) 1462 if not server.description.retryable_reads_supported: 1463 retryable = False File ...\\Lib\\site-packages\\pymongo\\mongo_client.py:1278, in MongoClient._select_server(self, server_selector, session, address) 1275 raise AutoReconnect('server %s:%d no longer available' 1276 % address) 1277 else: -> 1278 server = topology.select_server(server_selector) 1279 # Pin this session to the selected server if it's performing a 1280 # sharded transaction. 1281 if server.description.mongos and (session and 1282 session.in_transaction): File ...\\Lib\\site-packages\\pymongo\\topology.py:241, in Topology.select_server(self, selector, server_selection_timeout, address) 236 def select_server(self, 237 selector, 238 server_selection_timeout=None, 239 address=None): 240 \"\"\"Like select_servers, but choose a random server if several match.\"\"\" --> 241 return random.choice(self.select_servers(selector, 242 server_selection_timeout, 243 address)) File ...\\Lib\\site-packages\\pymongo\\topology.py:199, in Topology.select_servers(self, selector, server_selection_timeout, address) 196 server_timeout = server_selection_timeout 198 with self._lock: --> 199 server_descriptions = self._select_servers_loop( 200 selector, server_timeout, address) 202 return [self.get_server_by_address(sd.address) 203 for sd in server_descriptions] File ...\\Lib\\site-packages\\pymongo\\topology.py:215, in Topology._select_servers_loop(self, selector, timeout, address) 212 while not server_descriptions: 213 # No suitable servers. 214 if timeout == 0 or now > end_time: --> 215 raise ServerSelectionTimeoutError( 216 \"%s, Timeout: %ss, Topology Description: %r\" % 217 (self._error_message(selector), timeout, self.description)) 219 self._ensure_opened() 220 self._request_check_all() ServerSelectionTimeoutError: {service_name}.mongo.cosmos.azure.com:10255: timed out, Timeout: 30s, Topology Description: <TopologyDescription id: 6734b32d878003e1a30f46fb, topology_type: Single, servers: [<ServerDescription ('{service_name}.mongo.cosmos.azure.com', 10255) server_type: Unknown, rtt: None, error=NetworkTimeout('{service_name}.mongo.cosmos.azure.com:10255: timed out')>]>" }
解决方案
针对Azure Cosmos DB MongoDB引擎的无服务器分片实例,调整连接参数和代码即可解决超时问题:
1. 修改连接字符串参数
无服务器实例不需要replicaSet=globaldb参数,且需要添加directConnection=true强制直连,调整后的连接字符串格式:
mongodb://{user_name}:{primary_key}@{service_name}.mongo.cosmos.azure.com:10255/?ssl=true&directConnection=true&retrywrites=false&maxIdleTimeMS=120000&appName=@{service_name}@
注意:如果主键包含特殊字符(如
+、/、=),需进行URL编码,比如+替换为%2B,/替换为%2F,=替换为%3D
2. 匹配pymongo版本与MongoDB兼容版本
- 若使用MongoDB 7.0兼容版本,需使用pymongo 4.6.0及以上版本
- 若使用MongoDB 3.6兼容版本,可使用pymongo 3.6~4.0系列版本
3. 调整连接超时参数(可选)
在创建MongoClient时显式设置更长的超时时间,避免因无服务器实例冷启动导致的超时:
import pymongo CONN_STRING = "调整后的连接字符串" client = pymongo.MongoClient( CONN_STRING, serverSelectionTimeoutMS=60000, # 设置为60秒 connectTimeoutMS=30000 ) # 验证连接 try: client.admin.command('ping') print("连接成功") print("数据库列表:", client.list_database_names()) except Exception as e: print(f"连接失败: {e}")
4. 检查Cosmos DB实例配置
确认Azure Cosmos DB实例的网络访问控制设置为允许当前客户端IP,或者开启“允许从所有网络访问”(测试环境可临时开启验证)
内容的提问来源于stack exchange,提问作者ilVacca
相关产品推荐
相关产品推荐

