

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

# 与亚马逊 DocumentDB 的连接问题
<a name="performance-connection-issues"></a>

## 识别-发现问题
<a name="connection-identification"></a>

**常见原因**

连接问题通常源于三个主要方面：

当应用程序达到允许与 Amazon DocumentDB 的最大连接数时，连接池就会耗尽，无论是通过客户端连接池限制还是服务器端实例限制。这种情况会导致应用程序性能降低、超时以及可能出现故障，因为新的连接请求要么排队，要么被拒绝。

当 Amazon DocumentDB 遇到过多的并发身份验证请求时，就会出现身份验证过载，尤其是在短时间内处理超过 1,000 个新连接时。在身份验证维护期间，Amazon DocumentDB 在会话地图上保持独占锁，导致后续的身份验证尝试排队直到维护完成。

Amazon DocumentDB 中的配置问题通常源于网络、安全和客户端设置的错误配置。这包括安全组设置不正确、VPC 配置不正确或 SSL/TLS 证书问题等问题。了解正确的配置对于维护数据库访问的安全性和可靠性至关重要。

## 诊断-查找根本原因
<a name="connection-diagnose"></a>

**连接池**

创建 MongoClient 实例时，连接池会初始化。每个池都基于两个关键参数维护连接：

minPoolSize -保持的最低连接数

maxPoolSize -允许的最大连接数

当请求需要连接时：

1. 池检查可用的空闲连接

1. 如果不存在且池大小为 < maxPoolSize，则会创建新连接

1. 如果为 maxPoolSize，则请求进入等待队列

1. 如果队列已满或已达到超时，则会抛出 MongoWaitQueueFullException

等待队列的行为通过以下参数处理：

waitQueueTimeoutMS-连接的最长等待时间

waitQueueSize -最大排队请求数

以下是连接到 Amazon DocumentDB 时出现问题的方法示例，在这种方法中，每次都会创建一个新池：

```
for(Request request : requests) {
    MongoClient client = MongoClients.create(settings);
    // Process request
    client.close();
}
```

要监控的关键 CloudWatch 指标有：
+ `DatabaseConnections`-以 1 分钟为频率拍摄的实例上打开的连接数（活动和空闲）。
+ `DatabaseConnectionsMax`-1 分钟内实例上打开的数据库连接（活动和空闲）的最大数量。
+ `DatabaseConnectionsLimit`-在任何给定时间，实例上允许的最大并发数据库连接（活动和空闲）数。
+ `LowMemNumOperationsThrottled`-1 分钟内由于可用内存不足而受到限制的请求数。

有关每个实例类别的[限制，请参阅配额和](limits.md#limits.instance)限制。

应用程序级别连接池问题的常见警告信号包括：
+ 增加连接获取时间
+ 等待队列大小不断增加
+ 超时异常数量增加

**身份验证过载**

连接亚马逊 DocumentDB 的流程如下所示：

连接请求 → SSL 握手 → 身份验证 → 会话创建 → 连接就绪

当处理超过 1,000 个新连接时，在完成 SSL 握手后，其他连接请求将进入身份验证队列。在这些过载事件期间，您的应用程序的平均连接时间将增加。

要监控的关键 CloudWatch 指标有：
+ `DatabaseConnections`-以 1 分钟为频率拍摄的实例上打开的连接数（活动和空闲）。
+ `DatabaseConnectionsMax`-1 分钟内实例上打开的数据库连接（活动和空闲）的最大数量。
+ `DatabaseConnectionsLimit`-在任何给定时间，实例上允许的最大并发数据库连接（活动和空闲）数。

**配置问题**

最常见的配置问题是在尝试从无法访问私有网络环境的环境中连接私有 Amazon DocumentDB 集群终端节点时引起的。Amazon DocumentDB 仅面向虚拟私有云（VPC），并且当前不支持公共端点。您无法从笔记本电脑或 VPC 之外的本地开发环境直接连接到您的 Amazon DocumentDB 集群。

这将在错误中表现出来，如下所示：

```
Error: couldn't connect to server...
Failed to connect to...
exception: connect failed
connection attempt failed
```

不正确的安全组配置也可能导致连接失败。默认情况下，Amazon DocumentDB 集群监听 TCP 端口 27017 上的连接。如果尝试连接到与集群部署时使用的端口不同的端口，或者如果该应用程序未包含在集群的入口安全组配置中，则您的应用程序将失败。

不正确的证书管理也可能导致连接问题。默认情况下，为新创建的 Amazon DocumentDB 集群启用传输中加密。启用传输中加密后，需要使用 TLS 进行安全连接才能使用 global-bundle.pem 证书连接到集群。如果您尝试使用不正确的证书，则会收到错误消息，例如：

```
unable to get local issuer certificate
```

如果在未指定 TLS 参数的情况下尝试连接到启用了 TLS 的集群，则会收到如下错误：

```
Server selection timed out after 30000 ms
```

## 解决-修复问题
<a name="connection-resolve"></a>

**连接池**：通过实施或调整池大小来审查连接池以满足工作负载要求。最佳池配置取决于您的工作负载和要求。你应该保持核心连接准备就绪并可用，并且足够 maxWaitTime 短，以便在池用尽时快速失败。 minPoolSize 

以下是如何在不每次都创建新池的情况下重复使用单个池的示例：

```
MongoClient client = MongoClients.create(settings); 
    for(Request request : requests) { 
    // Process request
}
```

**身份验证过载**：通过逐步增加连接并将新连接限制为 1,000 个来管理身份验证。使用连接池可以有效地重复使用经过身份验证的连接。为避免连接过载 Amazon DocumentDB 集群，请实施连接提升策略。

```
public class ConnectionManager {
    private static final int BATCH_SIZE = 100;
    private static final int DELAY_MS = 1000;
    
    public void establishConnections(int totalRequired) {
        int established = 0;
        while (established < totalRequired) {
            int batch = Math.min(BATCH_SIZE, totalRequired - established);
            createConnections(batch);
            Thread.sleep(DELAY_MS);
            established += batch;
        }
    }
}
```

您也可以配置连接池设置以限制允许的连接总数。

```
MongoClientSettings settings = MongoClientSettings.builder()
    .applyToConnectionPoolSettings(builder -> {
        builder.maxSize(500)                     // Limit total connections
               .minSize(10)                      // Maintain base connections
               .maxConnectionLifeTime(3600000)   // Rotate connections hourly
    })
    .applyToServerSettings(builder -> {
        builder.heartbeatFrequency(10000)        // Regular server checks
    })
    .build();
```

**配置问题**：确保您的应用程序可以访问您的 Amazon DocumentDB 资源所在的私有 VPC 和子网。如果使用 VPC 对等连接，请查看开发者指南 VPC 对等连接疑难解答以了解更多信息。您也可以查看知识中心文章[如何解决从互联网到我的 VPC 内的 Amazon EC2 实例的连接问题？](https://repost.aws/knowledge-center/instance-vpc-troubleshoot) 。

要配置安全组，您必须在 Amazon DocumentDB 安全组中包含一条入口规则，以允许来自您的应用程序的连接。

```
{
  "SecurityGroupIngress": [
    {
      "IpProtocol": "tcp",
      "FromPort": 27017,
      "ToPort": 27017,
      "SourceSecurityGroupId": "<application-security-group>",
      "Description": "DocumentDB access from application tier"
    }
  ],
  "SecurityGroupEgress": [
    {
      "IpProtocol": "-1",
      "FromPort": -1,
      "ToPort": -1,
      "CidrIp": "0.0.0.0/0"
    }
  ]
}
```

如果集群配置了 TLS 加密，请下载名为 global-bundle.pem 的亚马逊 Amazon DocumentDB 的 TLS 证书，并在连接到集群时使用该证书。

```
wget https://truststore.pki.rds.amazonaws.com/global/global-bundle.pem
```

**长期解决方案**

可能需要通过升级到更大的实例类或添加只读副本来分散连接负载来扩展实例。适当的负载平衡实施可确保整个群集的最佳资源利用率。

应用程序变更应侧重于实现强大的连接处理、全面监控和遵守连接池最佳实践。这包括适当的错误处理和连接生命周期管理。

架构改进可能包括为可变工作负载采用 Amazon DocumentDB Serverless、实现复杂的重试逻辑以及容错设计。考虑重组应用程序架构，以更好地处理连接管理。

## 最佳实践
<a name="connection-best-practices"></a>

**连接池**

通过适当的连接池管理和监控，应用程序可以保持稳定的数据库连接，同时防止可能影响系统可靠性和性能的耗尽情况。根据工作负载的特性配置适当的超时时间并调整池的大小。

连接池设置示例

```
MongoClientSettings settings = MongoClientSettings.builder()
    .applyToConnectionPoolSettings(builder ->
        builder.maxSize(10))
    .applyToConnectionPoolSettings(builder ->
        builder.maxWaitQueueSize(2))
    .applyToConnectionPoolSettings(builder ->
        builder.maxConnectionIdleTime(10, TimeUnit.MINUTES))
    .build();
```

有关更多信息，请参阅：[https://aws.amazon.com/blogs/database/--compatibility-part-1-client-configuration/ building-resilient-applications-with amazon-documentdb-with-mongodb](https://aws.amazon.com/blogs/database/building-resilient-applications-with-amazon-documentdb-with-mongodb-compatibility-part-1-client-configuration/)

**身份验证过载**

始终根据您的工作负载使用适当的参数值来实现连接池。尽可能使用渐进式连接建立技术并保持持久连接。实施适当的连接清理，确保不会浪费闲置资源。

**配置问题**

确保您已经配置了从应用程序到 Amazon DocumentDB 资源的适当路由。使用 TLS 对传输过程进行加密并实现最低权限访问。验证您的亚马逊 DocumentDB 凭证并验证连接字符串值。