连接问题 - Amazon DocumentDB

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

连接问题

连接遇到问题? 以下是一些常见场景及如何解决。

主题

无法连接到 Amazon DocumentDB 端点

当您尝试连接到 Amazon DocumentDB 时,以下错误消息是您可能收到的最常见的错误消息之一。

connecting to: mongodb://docdb-2018-11-08-21-47-27.cluster-ccuszbx3pn5e.us-east- 1.docdb.amazonaws.com:27017/ 2018-11-14T14:33:46.451-0800 W NETWORK [thread1] Failed to connect to 172.31.91.193:27017 after 5000ms milliseconds, giving up. 2018-11-14T14:33:46.452-0800 E QUERY [thread1] Error: couldn't connect to server docdb-2018-11-08-21-47-27.cluster-ccuszbx3pn5e.us-east-1.docdb.amazonaws.com:27017, connection attempt failed : connect@src/mongo/shell/mongo.js:237:13 @(connect):1:6 exception: connect failed

此错误消息通常意味着您的客户端(此示例中为 mongo shell)无法访问 Amazon DocumentDB 端点。以下几个原因可能会导致出现此情况:

从公有端点连接

您正在尝试直接通过笔记本电脑或本地开发计算机连接到 Amazon DocumentDB 集群。

从公有端点(例如,您的笔记本电脑或本地开发机)直接连接到 Amazon DocumentDB 集群的尝试会失败。Amazon DocumentDB 仅面向虚拟私有云(VPC),并且当前不支持公共端点。因此,您无法从笔记本电脑或 VPC 外部的本地开发环境直接连接到 Amazon DocumentDB 集群。

要从 Amazon VPC 外部连接到 Amazon DocumentDB 集群,您可使用 SSH 隧道。有关更多信息,请参阅 从 Amazon VPC 外部连接到 Amazon DocumentDB 集群。此外,如果您的开发环境位于不同的 Amazon VPC 中,您还可以使用 VPC 对等,并从同一区域或不同区域中的另一个 Amazon VPC 连接到您的 Amazon DocumentDB 集群。

跨区域连接

您正在尝试连接到另一个区域中的 Amazon DocumentDB 集群。

如果您尝试从集群区域以外某区域的 Amazon EC2 实例连接到 Amazon DocumentDB 集群,例如,尝试从美国西部(俄勒冈州)区域 (us-west-2) 连接到美国东部(弗吉尼亚州北部)区域 (us-east-1) 中的集群,连接将失败。

要验证您的 Amazon DocumentDB 集群的区域,请运行以下命令。区域位于终端节点中。

aws docdb describe-db-clusters \ --db-cluster-identifier sample-cluster \ --query 'DBClusters[*].Endpoint'

此操作的输出将类似于下文。

[ "sample-cluster.node.us-east-1.docdb.amazonaws.com" ]

要验证您的 EC2 实例的区域,请运行以下命令。

aws ec2 describe-instances \ --query 'Reservations[*].Instances[*].Placement.AvailabilityZone'

此操作的输出将类似于下文。

[ [ "us-east-1a" ] ]

从不同的 Amazon VPC 连接

您正在尝试通过一个 VPC(不同于您的集群部署到的 Amazon VPC)连接到 Amazon DocumentDB 集群。

如果您的亚马逊 DocumentDB 集群和 Amazon EC2 实例位于相同 AWS 区域但不在同一个亚马逊 VPC 中,则除非在两个 Amazon VPC 之间启用 VPC 对等,否则您无法直接连接到您的亚马逊文档数据库集群。

要验证 Amazon DocumentDB 实例的 Amazon VPC,请运行以下命令。

aws docdb describe-db-instances \ --db-instance-identifier sample-instance \ --query 'DBInstances[*].DBSubnetGroup.VpcId'

要验证您的 Amazon EC2 实例的 Amazon VPC,请运行以下命令。

aws ec2 describe-instances \ --query 'Reservations[*].Instances[*].VpcId'

安全组阻止入站连接

您正在尝试连接到 Amazon DocumentDB 集群,并且该集群的安全组不允许集群端口(默认端口:27017)上的入站连接。

假设您的 Amazon DocumentDB 集群和 Amazon EC2 实例位于同一区域和 Amazon VPC 中,并且使用相同的 Amazon VPC 安全组。如果您无法连接到您的 Amazon DocumentDB 集群,这可能是因为您的集群的安全组(即防火墙)不允许您为 Amazon DocumentDB 集群选择的端口(默认端口为 27017)上的入站连接。

要验证您的 Amazon DocumentDB 集群的端口,请运行以下命令。

aws docdb describe-db-clusters \ --db-cluster-identifier sample-cluster \ --query 'DBClusters[*].[DBClusterIdentifier,Port]'

要获取您的集群的 Amazon DocumentDB 安全组,请运行以下命令。

aws docdb describe-db-clusters \ --db-cluster-identifier sample-cluster \ --query 'DBClusters[*].[VpcSecurityGroups[*],VpcSecurityGroupId]'

要检查您的安全组的入站规则,请参阅 Amazon EC2 文档中的以下主题:

Java Mongo 驱动程序读取首选项问题

客户端读取首选项未被接受,并且除非重启,某些客户端无法在失效转移后写入 Amazon DocumentDB。

这个问题最初在 Java Mongo Driver 3.7.x 中发现,当客户端使用 MongoClientSettings 与 Amazon DocumentDB 建立连接时,尤其链接 applyToClusterSettings 方法时,会发生。可以使用几种不同的方法来定义 MongoClient 集群设置,例如hosts()requiredReplicaSetName()、和mode()

当客户端在 hosts() 方法中仅指定一台主机时,模式将设置为 ClusterConnectionMode.SINGLE 而非 ClusterConnectionMode.MULTIPLE。这导致客户端忽略读取首选项而仅连接到按 hosts() 配置的服务器。因此,即使客户端设置如下所示初始化,所有读取仍将转至主服务器而不是辅助服务器。

final ServerAddress serverAddress0 = new ServerAddress("cluster-endpoint", 27317)); final MongoCredential credential = MongoCredential.createCredential("xxx", "admin", "xxxx".toCharArray()); final MongoClientSettings settings = MongoClientSettings.builder() .credential(credential) .readPreference(ReadPreference.secondaryPreferred()) .retryWrites(false) .applyToSslSettings(builder -> builder .enabled(false)) .applyToClusterSettings(builder -> builder.hosts( Arrays.asList(serverAddress0 )) .requiredReplicaSetName("rs0")) .build(); MongoClient mongoClient = MongoClients.create(settings);

失效转移案例

使用上述的客户端连接设置,如果集群写入器端点存在失效转移和延迟的 DNS 记录更新,则客户端仍尝试向旧写入器(失效转移后现在是读取器)发出写入请求。这导致 Java 驱动程序未恰当处理的服务器端错误(不是主错误)(这仍在调查中)。因此,可能听任客户端处于不良状态,例如直到应用程序服务器重新启动为止。

对此有两种应变方法:

  • 通过连接字符串连接到 Amazon DocumentDB 的客户端将不会出现这个问题,因为设置读取首选项时ClusterConnectionMode 会设置成 MULTIPLE

    MongoClientURI mongoClientURI = new MongoClientURI("mongodb://usr:pass:cluster-endpoint:27317/test?ssl=false&replicaSet=rs0&readpreference=secondaryPreferred"); MongoClient mongoClient = MongoClients.create(mongoClientURI.getURI());

    或者配合 applyConnectionString 方法使用 MongoClientSettings 生成器。

    final MongoClientSettings settings = MongoClientSettings.builder() .credential(credential) .applyConnectionString(new ConnectionString("usr:pass:cluster-endpoint:27317/test?ssl=false&replicaSet=rs0&readpreference=secondaryPreferred")) .retryWrites(false) .applyToSslSettings(builder → builder .enabled(false)) .build(); MongoClient mongoClient = MongoClients.create(settings);
  • ClusterConnectionMode 明确设置成 MULTIPLE。只有使用 applyToClusterSettingshosts().size() == 1 时才需要这样做。

    final ServerAddress serverAddress0 = new ServerAddress("cluster-endpoint", 27317)); final MongoCredential credential = MongoCredential.createCredential("xxx","admin", "xxxx".toCharArray()); final MongoClientSettings settings = MongoClientSettings.builder() .credential(credential) .readPreference(ReadPreference.secondaryPreferred()) .retryWrites(false) .applyToSslSettings(builder → builder .enabled(false)) .applyToClusterSettings(builder → builder .hosts(Arrays.asList(serverAddress0)) .requiredReplicaSetName("rs0")) .mode(ClusterConnectionMode.MULTIPLE)) .build(); MongoClient mongoClient = MongoClients.create(settings);

测试与 Amazon DocumentDB 实例的连接

您可以使用常见的 Linux 或 Windows 工具测试与集群的连接。

从 Linux 或 Unix 终端测试此连接,方法为输入以下命令(将 cluster-endpoint 替换为终端节点并将 port 替换为实例的端口)。

nc -zv cluster-endpoint port

以下是示例操作和返回值的示例:

nc -zv docdbTest.d4c7nm7stsfc0.us-west-2.docdb.amazonaws.com 27017 Connection to docdbTest.d4c7nm7stsfc0.us-west-2.docdb.amazonaws.com 27017 port [tcp/*] succeeded!

连接到无效终端节点

在连接到 Amazon DocumentDB 集群并且使用的是无效的集群端点时,将出现与以下内容类似的错误。

mongo --ssl \ --host sample-cluster.node.us-east-1.docdb.amazonaws.com:27017 \ --sslCAFile global-bundle.pem \ --username <user-name> \ --password <password>

该输出类似于以下示例:

MongoDB shell version v3.6 connecting to: mongodb://sample-cluster.node.us-east-1.docdb.amazonaws.com:27017/ 2018-11-14T17:21:18.516-0800 I NETWORK [thread1] getaddrinfo("sample-cluster.node.us-east-1.docdb.amazonaws.com") failed: nodename nor servname provided, or not known 2018-11-14T17:21:18.537-0800 E QUERY [thread1] Error: couldn't initialize connection to host sample-cluster.node.us-east-1.docdb.amazonaws.com, address is invalid : connect@src/mongo/shell/mongo.js:237:13@(connect):1:6 exception: connect failed

要获取集群的有效终端节点,请运行以下命令:

aws docdb describe-db-clusters \ --db-cluster-identifier sample-cluster \ --query 'DBClusters[*].[Endpoint,Port]'

要获取实例的有效终端节点,请运行以下命令:

aws docdb describe-db-instances \ --db-instance-identifier sample-instance \ --query 'DBInstances[*].[Endpoint.Address,Endpoint.Port]'

有关更多信息,请参阅 了解 Amazon DocumentDB 端点

驱动程序配置会影响连接数

使用客户端驱动程序连接到 Amazon DocumentDB 集群时,请务必考虑maxPoolSize配置参数。该maxPoolSize设置决定了客户端驱动程序将在其连接池中保持的最大连接数。