You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python经堡垒机连接远程MongoDB集群遇ServerSelectionTimeoutError求助

解决Python通过SSH堡垒机连接MongoDB副本集的ServerSelectionTimeoutError问题

1. 修正SSH隧道的私钥密码参数

你的代码中错误地将私钥的passphrase传给了ssh_password参数,该参数用于密码登录堡垒机,而加密私钥的密码需要使用ssh_private_key_password参数:

server = SSHTunnelForwarder(
    ssh_address_or_host=(bastion_adress, 22),
    ssh_username=username,
    ssh_pkey=r'\private_key_adress.pem',
    # 替换ssh_password为ssh_private_key_password
    ssh_private_key_password=pp_pkey,
    remote_bind_address=('mongo_db_server_adress', 27017),
    local_bind_address=('127.0.0.1', 27018)
)

2. 处理MongoDB副本集的节点访问问题

你使用Compass的srv连接字符串能成功,说明目标是MongoDB副本集。副本集的特性是:客户端连接后,MongoDB会返回所有副本集节点的私有网络地址,客户端会直接尝试连接这些地址,但本地无法访问私有网络,这是导致超时的核心原因。

方案A:强制直连单个节点(快速临时解决)

在MongoClient中添加directConnection=True参数,强制只连接隧道转发的节点,适合临时测试:

db = pymongo.MongoClient(
    connection_str,
    username=username,
    password=pp_mongouser,
    tls=True,
    # 强制直连指定节点
    directConnection=True,
    # 若使用自签名证书,需添加该参数(根据实际情况调整)
    tlsAllowInvalidCertificates=True
)["db_name"]

方案B:完整支持副本集(推荐)

要完整支持副本集的故障转移,需让本地能访问所有副本集节点:

  1. 通过Compass连接后查看副本集配置,获取所有节点的域名/IP
  2. 在本地hosts文件中,将每个副本集节点的域名映射到127.0.0.1
  3. 为每个节点创建独立的SSH隧道,转发到本地不同端口:
    # 示例:假设副本集有3个节点
    servers = []
    # 节点1隧道
    servers.append(SSHTunnelForwarder(
        (bastion_adress, 22),
        ssh_username=username,
        ssh_pkey=r'\private_key_adress.pem',
        ssh_private_key_password=pp_pkey,
        remote_bind_address=('mongo-node1.example.com', 27017),
        local_bind_address=('127.0.0.1', 27018)
    ))
    # 节点2隧道
    servers.append(SSHTunnelForwarder(
        (bastion_adress, 22),
        ssh_username=username,
        ssh_pkey=r'\private_key_adress.pem',
        ssh_private_key_password=pp_pkey,
        remote_bind_address=('mongo-node2.example.com', 27017),
        local_bind_address=('127.0.0.1', 27019)
    ))
    # 节点3隧道
    servers.append(SSHTunnelForwarder(
        (bastion_adress, 22),
        ssh_username=username,
        ssh_pkey=r'\private_key_adress.pem',
        ssh_private_key_password=pp_pkey,
        remote_bind_address=('mongo-node3.example.com', 27017),
        local_bind_address=('127.0.0.1', 27020)
    ))
    # 启动所有隧道
    for s in servers:
        s.start()
    
  4. 构造包含所有本地转发地址的连接字符串,并指定副本集名称:
    connection_str = 'mongodb://127.0.0.1:27018,127.0.0.1:27019,127.0.0.1:27020'
    db = pymongo.MongoClient(
        connection_str,
        username=username,
        password=pp_mongouser,
        tls=True,
        replicaSet='replicaset',  # 替换为你的副本集名称
        # 自签名证书需添加
        tlsAllowInvalidCertificates=True
    )["db_name"]
    
  5. 操作完成后停止所有隧道:
    for s in servers:
        s.stop()
    

3. 其他排查点

  • 确认堡垒机私钥路径正确(Windows路径需用\\或原始字符串r'C:\path\to\key.pem')
  • 用telnet 127.0.0.1 27018测试本地端口是否正常连通
  • 检查MongoDB用户权限:确保用户拥有listCollections权限
  • 若使用MongoDB Atlas,需确认堡垒机IP已加入Atlas的IP白名单

内容的提问来源于stack exchange,提问作者Baptiste Bortot

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 05:23:13