Pymongo 连接到 DocumentDB 集群

问题描述 投票:0回答:4

为了在本地环境中以编程方式将 python 连接到我们的 AWS DocumentDB(AWS 版本的 MongoDB)实例,我遇到了一些问题。我们尝试了以下步骤:

  1. 为了开始我们的实验,我们使用推荐的 AWS 教程来创建 python 连接:https://docs.aws.amazon.com/documentdb/latest/developerguide/connect_programmatically.html.

  2. 由于我们希望最初在本地进行设置,因此我们使用以下命令与集群建立 SSH 连接: ssh -i "example.pem" -L 27019:docdb.cluster-XXXXXXX.region.docdb.amazonaws.com:27017 [电子邮件受保护] -N -v 该命令运行良好,我们能够创建隧道并将本地端口 27019 连接到我们的集群。关于这一点的一个重要注意事项是,为了到达集群,我们必须激活 VPN 网络。

  3. 我们调整了代码以连接到本地端口:

    from pymongo import MongoClient,ReadPreference
    import urllib
    import ssl
    
    username=urllib.parse.quote_plus("username")
    password=urllib.parse.quote_plus("password")
    port=27019
    host="localhost"
    dbName="general"
    
    
    dbUri = f'mongodb://{username}:{password}@{host}:{port}/?tls=true&tlsCAFile=./rds-combined-ca-bundle.pem&retryWrites=false'
    print(dbUri)
    
    client = MongoClient(dbUri)
    print(client.list_database_names())

运行上面的示例,我们得到错误:

pymongo.errors.ServerSelectionTimeoutError: hostname '127.0.0.1' doesn't match either of 'docdb.XXXXXXX.region.docdb.amazonaws.com', 'docdb.cluster-XXXXXXX.region.docdb.amazonaws.com', 'docdb.cluster-ro-XXXXXXX.region.docdb.amazonaws.com', Timeout: 30s, Topology Description: <TopologyDescription id: 61e7f8c811a815088e97e5a7, topology_type: Unknown, servers: [<ServerDescription ('127.0.0.1', 27019) server_type: Unknown, rtt: None, error=CertificateError("hostname '127.0.0.1' doesn't match either of 'docdb.XXXXXXX.region.docdb.amazonaws.com', 'docdb.cluster-XXXXXXX.region.docdb.amazonaws.com', 'docdb.cluster-ro-XXXXXXX.region.docdb.amazonaws.com'",)>]>
2022-01-19 11:41:27,120| ERROR   | Could not establish connection from local ('127.0.0.1', 27019) to remote ('ai-docdb-dev.cluster-cq8mixmxuhvt.eu-west-1.docdb.amazonaws.com', 27017) side of the tunnel: open new channel error:

这表明两件事:首先,我们的代码正确使用 .pem 证书,并且能够获取我们的集群名称。其次,代码无法理解 localhost 是一个地址并检查本地端口 27019 是否到达集群。

为了尝试解决这个问题,我们还尝试将代码变量主机替换为 127.0.01,但结果是相同的。我们还尝试调整 pymongo 函数 MongoClient https://pymongo.readthedocs.io/en/stable/api/pymongo/mongo_client.html#pymongo.mongo_client.MongoClient 的几个参数,但结果仍然相同。

谢谢

python mongodb amazon-web-services pymongo aws-documentdb
4个回答
5
投票

经过多次不成功的尝试,我们终于找到了解决方案!

使用 pymongo 3.X.X,我们能够通过将参数

tlsInsecure=true
添加到原始 URI(传递给我们的
MongoClient
函数)来连接到我们的 documentDb 实例。

对于 pymongo 4.X.X,我们必须添加一个额外的参数

directConnection=true
才能正常工作。

host
变量可以设置为
localhost
127.0.0.1
username
password
可以用urlib或不加密。


1
投票

看起来证书检查正在验证您正在使用的主机名,因此我们可以通过使用实际的主机名并将其在主机文件中映射到

127.0.0.1
来欺骗它。

将每个

docdb.XXXXXXX.region.docdb.amazonaws.com
添加到您的呼叫系统的 hosts 文件,例如

127.0.0.1 docdb.XXXXXXX-1.region.docdb.amazonaws.com
127.0.0.1 docdb.XXXXXXX-2.region.docdb.amazonaws.com
127.0.0.1 docdb.XXXXXXX-3.region.docdb.amazonaws.com

然后更改宿主变量:

host=f"docdb.XXXXXXX-1.region.docdb.amazonaws.com:{port},docdb.XXXXXXX-2.region.docdb.amazonaws.com:{port},docdb.XXXXXXX-3.region.docdb.amazonaws.com:{port}"

然后更改 URI 以删除端口,因为它现在位于主机变量中:

dbUri = f'mongodb://{username}:{password}@{host}/?tls=true&tlsCAFile=./rds-combined-ca-bundle.pem&retryWrites=false'

0
投票

将 &tlsAllowInvalidHostnames=true 添加到 URI 以跳过主机名检查。


0
投票

这个连接字符串对我有用:

mongodb://mongodbuser:{username}:{password}@{host}:27017/?tls=true&tlsCAFile=./rds-combined-ca-bundle.pem&replicaSet=rs0&readPreference=secondaryPreferred&retryWrites=false&tlsAllowInvalidHostnames=true&directConnection=true

还有 directConnection - 对于 aws 必须为 false,对于本地为 true(例如使用隧道时)

© www.soinside.com 2019 - 2024. All rights reserved.