

 适用于 Java 的 AWS SDK 1.x于2025年 end-of-support 12月31日达到。我们建议您迁移到 [AWS SDK for Java 2.x](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/home.html) 以继续获得新功能、可用性改进和安全更新。

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

# 使用 适用于 Java 的 AWS SDK
<a name="basics"></a>

本节提供有关使用编程的重要一般信息 适用于 Java 的 AWS SDK ，这些信息适用于您可能在 SDK 中使用的所有服务。

有关特定于服务的编程信息和示例（ Amazon EC2针对 Amazon S3、 Amazon SWF、等），请参阅[适用于 Java 的 AWS SDK 代码示例](prog-services.md)。

**Topics**
+ [AWS 开发的最佳实践 适用于 Java 的 AWS SDK](best-practices.md)
+ [创建服务客户端](creating-clients.md)
+ [提供临时凭证](credentials.md)
+ [AWS 区域 选择](java-dg-region-selection.md)
+ [异常处理](java-dg-exceptions.md)
+ [异步编程](basics-async.md)
+ [记录 适用于 Java 的 AWS SDK 通话](java-dg-logging.md)
+ [客户端配置](section-client-configuration.md)
+ [访问控制策略](java-dg-access-control.md)
+ [为 DNS 名称查找设置 JVM TTL](jvm-ttl-dns.md)
+ [为启用指标 适用于 Java 的 AWS SDK](generating-sdk-metrics.md)

# AWS 开发的最佳实践 适用于 Java 的 AWS SDK
<a name="best-practices"></a>

以下最佳做法可以帮助您在使用开发 AWS 应用程序时避免出现问题或麻烦 适用于 Java 的 AWS SDK。这些最佳实践已按服务分类整理。

## S3
<a name="s3"></a>

### 避免 ResetExceptions
<a name="s3-avoid-resetexception"></a>

当您使用流（通过`AmazonS3`客户端或`TransferManager`）将对象上传到 Amazon S3 时，可能会遇到网络连接或超时问题。默认情况下， 适用于 Java 的 AWS SDK 尝试重试传输失败的方法是在传输开始之前标记输入流，然后在重试之前对其进行重置。

如果直播不支持标记和重置，则当出现暂时性故障并启用重试[ResetException](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/ResetException.html)时，SDK 会抛出。

 **最佳实践** 

建议您使用支持标记和重置操作的流。

避免 a 的最可靠方法[ResetException](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/ResetException.html)是使用[文件](https://docs.oracle.com/javase/8/docs/api/index.html?java/io/File.html)或来提供数据 [FileInputStream](https://docs.oracle.com/javase/8/docs/api/index.html?java/io/FileInputStream.html)，它们 适用于 Java 的 AWS SDK 可以在不受标记和重置限制的限制的情况下处理这些数据。

如果直播不是，[FileInputStream](https://docs.oracle.com/javase/8/docs/api/index.html?java/io/FileInputStream.html)但支持标记和重置，则可以使用`setReadLimit`方法设置标记限制[RequestClientOptions](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/RequestClientOptions.html)。其默认值为 128KB。将读取限制值设置为*比流大小大一个字节*将可靠地避免 [ResetException](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/ResetException.html).

例如，如果流的最大预期大小为 100000 字节，则将读取限制设置为 100001 (100000 \$1 1) 字节。标记和重置操作将始终适用于 100000 字节或更少的字节。请注意，这可能会导致一些流将该数量的字节缓冲到内存中。

# 创建服务客户端
<a name="creating-clients"></a>

要向发出请求 Amazon Web Services，请先创建一个服务客户端对象。推荐的方法是使用服务客户端生成器。

每个都 AWS 服务 有一个服务接口，其中包含服务 API 中每个操作的方法。例如，DynamoDB 的服务接口名为。[AmazonDynamoDBClient](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/dynamodbv2/AmazonDynamoDBClient.html)每个服务接口都有对应的客户端生成器，可用于构建服务接口的实施。的客户端生成器类名 DynamoDB 为 [AmazonDynamoDBClientBuilder](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/services/dynamodbv2/AmazonDynamoDBClientBuilder.html)。

## 获取客户端生成器
<a name="obtaining-a-client-builder"></a>

要获取客户端生成器的实例，使用下例中所示的静态工厂方法 `standard`。

```
AmazonDynamoDBClientBuilder builder = AmazonDynamoDBClientBuilder.standard();
```

获得生成器以后，可以使用生成器 API 中的多个常用 setter 来自定义客户端的属性。例如，您可以按以下方法设置自定义区域和自定义凭证提供程序。

```
AmazonDynamoDB ddb = AmazonDynamoDBClientBuilder.standard()
                        .withRegion(Regions.US_WEST_2)
                        .withCredentials(new ProfileCredentialsProvider("myProfile"))
                        .build();
```

**注意**  
常用的 `withXXX` 方法会返回 `builder` 对象，由此可以将方法调用组合起来，这样不仅方便而且代码更加便于阅读。在配置需要的属性后，可以调用 `build` 方法创建客户端。创建的客户端不可更改，而且对 `setRegion` 或 `setEndpoint` 的所有调用都会失败。

生成器可以使用相同配置创建多个客户端。在编写应用程序时，请注意生成器可变而且是非线程安全的。

以下代码使用生成器作为客户端实例的工厂。

```
public class DynamoDBClientFactory {
    private final AmazonDynamoDBClientBuilder builder =
        AmazonDynamoDBClientBuilder.standard()
            .withRegion(Regions.US_WEST_2)
            .withCredentials(new ProfileCredentialsProvider("myProfile"));

    public AmazonDynamoDB createClient() {
        return builder.build();
    }
}
```

[该生成器还为[ClientConfiguration](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/ClientConfiguration.html)和提供了流畅的设置器 [RequestMetricCollector](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/metrics/RequestMetricCollector.html)，以及一个包含 2 的自定义列表。RequestHandler](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/handlers/RequestHandler2.html)

以下给出将覆盖所有可配置属性的完整示例。

```
AmazonDynamoDB ddb = AmazonDynamoDBClientBuilder.standard()
        .withRegion(Regions.US_WEST_2)
        .withCredentials(new ProfileCredentialsProvider("myProfile"))
        .withClientConfiguration(new ClientConfiguration().withRequestTimeout(5000))
        .withMetricsCollector(new MyCustomMetricsCollector())
        .withRequestHandlers(new MyCustomRequestHandler(), new MyOtherCustomRequestHandler)
        .build();
```

## 创建异步客户端
<a name="creating-async-clients"></a>

每个服务（除外） 适用于 Java 的 AWS SDK 都有异步（或异步 Amazon S3）客户端，每个服务都有相应的异步客户端生成器。

### 使用默认值创建异步 DynamoDB 客户端 ExecutorService
<a name="w3aab9c13b9b5"></a>

```
AmazonDynamoDBAsync ddbAsync = AmazonDynamoDBAsyncClientBuilder.standard()
        .withRegion(Regions.US_WEST_2)
        .withCredentials(new ProfileCredentialsProvider("myProfile"))
        .build();
```

除了同步（或同步）客户端生成器支持的配置选项外，异步客户端还允许您设置自定义[ExecutorFactory](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/client/builder/ExecutorFactory.html)以更改异步客户端`ExecutorService`使用的配置。 `ExecutorFactory`是一个函数式接口，因此它可以与 Java 8 lambda 表达式和方法引用互操作。

### 使用自定义执行程序创建异步客户端
<a name="w3aab9c13b9b9"></a>

```
AmazonDynamoDBAsync ddbAsync = AmazonDynamoDBAsyncClientBuilder.standard()
            .withExecutorFactory(() -> Executors.newFixedThreadPool(10))
            .build();
```

## 使用 DefaultClient
<a name="using-defaultclient"></a>

同步和异步客户端生成器都包含名为 `defaultClient` 的另一个工厂方法。该方法使用默认配置创建服务客户端，即，使用默认提供程序链加载凭证和 AWS 区域。如果不能根据运行应用程序的环境确定凭证或区域，则对 `defaultClient` 的调用失败。有关如何确定[AWS 凭证和区域的更多信息，请参阅使用](credentials.md)凭证和[AWS 区域 选择](java-dg-region-selection.md)。

### 创建默认服务客户端
<a name="w3aab9c13c11b5"></a>

```
AmazonDynamoDB ddb = AmazonDynamoDBClientBuilder.defaultClient();
```

## 客户端生命周期
<a name="client-lifecycle"></a>

开发工具包中的服务客户端是线程安全的，而且为了获得最佳性能，应该将其作为永久对象。每个客户端均有各自的连接池资源。将显式关闭不再需要的客户端，以避免资源泄漏。

要显式关闭客户端，请调用 `shutdown` 方法。在调用 `shutdown` 后，会释放所有客户端资源且客户端不可用。

### 关闭客户端
<a name="w3aab9c13c13b7"></a>

```
AmazonDynamoDB ddb = AmazonDynamoDBClientBuilder.defaultClient();
ddb.shutdown();
// Client is now unusable
```

# 向提供临时证书 适用于 Java 的 AWS SDK
<a name="credentials"></a>

要向发出请求 Amazon Web Services，您必须提供 AWS 临时证书， 适用于 Java 的 AWS SDK 以供其在调用服务时使用。您可以通过下列方式来执行此操作：
+ 使用默认凭证提供程序链*（推荐）*。
+ 使用特定的凭证提供程序或提供程序链（或创建您自己的）。
+ 在代码中自行提供临时凭证。

## 使用默认凭证提供程序链
<a name="credentials-default"></a>

[当您在不提供任何参数的情况下初始化新的服务客户端时，会 适用于 Java 的 AWS SDK 尝试使用 Default AWSCredentials ProviderChain 类实现的*默认凭证提供程序链*来查找临时证书。](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/auth/DefaultAWSCredentialsProviderChain.html)默认凭证提供程序链将按此顺序查找凭证：

1.  **环境变量**，`AWS_ACCESS_KEY_ID`、`AWS_SECRET_KEY` 或 `AWS_SECRET_ACCESS_KEY` 和 `AWS_SESSION_TOKEN`。 适用于 Java 的 AWS SDK 使用[EnvironmentVariableCredentialsProvider](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/auth/EnvironmentVariableCredentialsProvider.html)类来加载这些证书。

1.  **Java 系统属性**，`aws.accessKeyId`、`aws.secretKey`（而不是 `aws.secretAccessKey`）和 `aws.sessionToken`。 适用于 Java 的 AWS SDK 使用加载[SystemPropertiesCredentialsProvider](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/auth/SystemPropertiesCredentialsProvider.html)这些凭证。

1.  来自环境或容器的 **Web 身份令牌凭证**。

1.  **默认凭证配置文件** ——通常位于`~/.aws/credentials`（位置可能因平台而异），并由许多 AWS SDKs 和共享。 AWS CLI 适用于 Java 的 AWS SDK 使用加载[ProfileCredentialsProvider](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/auth/profile/ProfileCredentialsProvider.html)这些凭证。

   您可以使用提供的`aws configure`命令创建凭据文件 AWS CLI，也可以使用文本编辑器编辑该文件来创建凭证文件。有关凭证文件格式的信息，请参阅 [AWS 凭证文件格式](#credentials-file-format)。

1.  **Amazon ECS 容器凭证** – 如果设置了环境变量 `AWS_CONTAINER_CREDENTIALS_RELATIVE_URI`，则从 Amazon ECS 加载该凭证。 适用于 Java 的 AWS SDK 使用加载[ContainerCredentialsProvider](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/auth/ContainerCredentialsProvider.html)这些凭证。可以指定此值的 IP 地址。

1.  **实例配置文件证书**-用于 EC2 实例，并通过 Amazon EC2 元数据服务提供。 适用于 Java 的 AWS SDK 使用加载[InstanceProfileCredentialsProvider](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/auth/InstanceProfileCredentialsProvider.html)这些凭证。可以指定此值的 IP 地址。
**注意**  
仅在未设置 `AWS_CONTAINER_CREDENTIALS_RELATIVE_URI` 时使用实例配置文件凭证。请参阅[EC2ContainerCredentialsProviderWrapper](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/auth/EC2ContainerCredentialsProviderWrapper.html)了解更多信息。

### 设置临时凭证
<a name="setting-credentials"></a>

为了能够使用 AWS 临时证书，必须*至少在上述位置之一*进行设置。有关设置凭证的信息，请参阅以下主题：
+ 要在*环境* 或默认*凭证配置文件* 中指定凭证，请参阅[配置临时凭证](setup-credentials.md#setup-credentials-setting)。
+ 要设置 Java *系统属性*，请参阅官方 [Java 教程](http://docs.oracle.com/javase/tutorial/essential/environment/sysprop.html)网站中的*系统属性*教程。
+ 要在您的 EC2 *实例上设置和使用实例配置文件证书*，请参阅上的 “[使用 IAM 角色授予对 AWS 资源的访问权限” Amazon EC2](java-dg-roles.md)。

### 设置备用凭证配置文件
<a name="setting-an-alternate-credentials-profile"></a>

默认 适用于 Java 的 AWS SDK 使用*默认*配置文件，但也有一些方法可以自定义哪个配置文件来自凭据文件。

您可以使用 P AWS rofile 环境变量来更改 SDK 加载的配置文件。

例如，在 Linux、macOS 或 Unix 上，您可运行以下命令来将配置文件更改为 *myProfile*。

```
export AWS_PROFILE="myProfile"
```

在 Windows 上，您将使用以下配置文件。

```
set AWS_PROFILE="myProfile"
```

设置`AWS_PROFILE`环境变量会影响所有官方支持的工具 AWS SDKs 和工具（包括和 AWS Tools for Windows PowerShell）的 AWS CLI 凭证加载。如果只需要更改 Java 应用程序的配置文件，则可改用系统属性 `aws.profile`。

**注意**  
环境变量优先于系统属性。

### 设置备用凭证文件位置
<a name="setting-an-alternate-credentials-file-location"></a>

会自动从默认凭证文件位置 适用于 Java 的 AWS SDK 加载 AWS 临时证书。但是，您也可以通过在 `AWS_CREDENTIAL_PROFILES_FILE` 环境变量中设置凭证文件的完整路径来指定位置。

您可以使用此功能临时更改证书文件所在的位置（例如，通过使用命令行设置此变量）。 适用于 Java 的 AWS SDK 或者，您也可以在您的用户环境或系统环境中设置该环境变量，在用户范围或系统范围内对其进行更改。

#### 覆盖默认凭证文件位置
<a name="w3aab9c15b9c11b7b1"></a>
+ 将`AWS_CREDENTIAL_PROFILES_FILE`环境变量设置为 AWS 凭据文件的位置。
  + 在 Linux、macOS 或 Unix 上，请使用：

    ```
    export AWS_CREDENTIAL_PROFILES_FILE=path/to/credentials_file
    ```
  + 在 Windows 上，请使用：

    ```
    set AWS_CREDENTIAL_PROFILES_FILE=path/to/credentials_file
    ```

### `Credentials` 文件格式
<a name="credentials-file-format"></a>

根据本指南中的[基本设置说明](signup-create-iam-user.md#setup-temp-creds)，您的凭证文件应采用以下基本格式。

```
[default]
aws_access_key_id=<value from AWS access portal>
aws_secret_access_key=<value from AWS access portal>
aws_session_token=<value from AWS access portal>

[profile2]
aws_access_key_id=<value from AWS access portal>
aws_secret_access_key=<value from AWS access portal>
aws_session_token=<value from AWS access portal>
```

在方括号中指定配置文件名（例如：`[default]`），后跟该配置文件中的可配置字段作为键值对。您的 `credentials` 文件可包含多个配置文件，可使用 `aws configure --profile PROFILE_NAME ` 选择要配置的配置文件来添加或编辑这些配置文件。

您可以指定其他字段，例如 `metadata_service_timeout` 和 `metadata_service_num_attempts`。无法使用 CLI 配置这些文件 – 如果您想使用这些文件，则必须手动编辑它们。有关配置文件及其可用字段的更多信息，请参阅 AWS Command Line Interface 用户指南[AWS Command Line Interface中的配置](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html)。

### 加载凭证
<a name="loading-credentials"></a>

在设置临时凭证后，SDK 使用默认凭证提供程序链来加载这些凭证。

为此，您需要实例化 AWS 服务 客户端，而无需向生成器明确提供证书，如下所示。

```
AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
                       .withRegion(Regions.US_WEST_2)
                       .build();
```

## 指定凭证提供程序或提供程序链
<a name="credentials-specify-provider"></a>

您可以通过客户端生成器来指定一个不同于*默认*凭证提供程序链的凭证提供程序。

您可以向以提供者接口作为输入的客户端生成器提供凭证提供程序或[AWSCredentials提供程序](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/auth/AWSCredentialsProvider.html)链的实例。以下示例演示使用*环境* 凭证的具体情况。

```
AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
                       .withCredentials(new EnvironmentVariableCredentialsProvider())
                       .build();
```

[有关 适用于 Java 的 AWS SDK提供的凭证提供者和提供者链的完整列表，请参阅 Provider 中的**AWSCredentials所有已知实现类**。](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/auth/AWSCredentialsProvider.html)

**注意**  
您可以使用此技术来提供凭证提供程序或提供者链，这些证书提供程序或通过使用自己实现`AWSCredentialsProvider`接口的凭证提供程序或对类进行子类来创建。[AWSCredentialsProviderChain](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/auth/AWSCredentialsProviderChain.html)

## 明确指定临时凭证
<a name="credentials-explicit"></a>

如果默认凭证链和特定的或自定义的提供程序或提供程序链都不适用于您的代码，您可以通过自行提供来明确设置这些凭证。如果您使用检索了临时证书 AWS STS，请使用此方法指定 AWS 访问凭证。

1. 实例化该[BasicSessionCredentials](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/auth/BasicSessionCredentials.html)类，并为其提供 SDK 用于连接的 AWS 访问 AWS 密钥、密钥和会 AWS 话令牌。

1. [AWSStaticCredentialsProvider](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/auth/AWSStaticCredentialsProvider.html)用`AWSCredentials`对象创建。

1. 使用 `AWSStaticCredentialsProvider` 配置客户端生成器并构建客户端。

示例如下：

```
BasicSessionCredentials awsCreds = new BasicSessionCredentials("access_key_id", "secret_key_id", "session_token");
AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
                        .withCredentials(new AWSStaticCredentialsProvider(awsCreds))
                        .build();
```

## 更多信息
<a name="more-info"></a>
+  [注册 AWS 并创建 IAM 用户](signup-create-iam-user.md) 
+  [为开发设置 AWS 凭证和区域](setup-credentials.md) 
+  [使用 IAM 角色授予对 AWS 资源的访问权限 Amazon EC2](java-dg-roles.md) 

# AWS 区域 选择
<a name="java-dg-region-selection"></a>

区域使您能够访问实际位于特定地理区域的 AWS 服务。它可以用于保证冗余，并保证您的数据和应用程序接近您和用户访问它们的位置。

## 查看区域的服务可用性
<a name="region-selection-query-service"></a>

要查看某个地区是否有特定 AWS 服务 内容可用，请在要使用的区域上使用`isServiceSupported`方法。

```
Region.getRegion(Regions.US_WEST_2)
    .isServiceSupported(AmazonDynamoDB.ENDPOINT_PREFIX);
```

请参阅[区域](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/regions/Regions.html)类文档查看可以指定的区域，并使用服务的终端节点前缀进行查询。在服务接口中定义了各服务的终端节点前缀。例如， DynamoDB 终端节点前缀是在[AmazonDynamo数据库](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/services/dynamodbv2/AmazonDynamoDB.html)中定义的。

## 选择区域
<a name="region-selection-choose-region"></a>

从 1.4 版本开始 适用于 Java 的 AWS SDK，您可以指定区域名称，SDK 将自动为您选择合适的终端节点。要自行选择终端节点，请参阅[选择特定终端节点](#region-selection-choose-endpoint)。

要显式设置区域时，我们建议您使用 [Regions](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/regions/Regions.html) 枚举。这是所有公开可用区域的枚举。要使用枚举结果中的一个区域创建客户端，请使用以下代码。

```
AmazonEC2 ec2 = AmazonEC2ClientBuilder.standard()
                    .withRegion(Regions.US_WEST_2)
                    .build();
```

如果 `Regions` 枚举结果不包含要使用的某个区域，可使用代表该区域名称的*字符串*。

```
AmazonEC2 ec2 = AmazonEC2ClientBuilder.standard()
                    .withRegion("{region_api_default}")
                    .build();
```

**注意**  
使用生成器所构建的客户端*不可改变*，而且*不能更改*区域。如果您要 AWS 区域 为同一服务使用多个客户端，则应创建多个客户端，每个区域一个。

## 选择特定终端节点
<a name="region-selection-choose-endpoint"></a>

通过在创建 AWS 客户端时调用`withEndpointConfiguration`方法，可以将每个客户端配置为使用区域内的*特定终端节点*。

例如，要将 Amazon S3 客户端配置为使用欧洲（爱尔兰）区域，请使用以下代码。

```
AmazonS3 s3 = AmazonS3ClientBuilder.standard()
     .withEndpointConfiguration(new EndpointConfiguration(
          "https://s3.eu-west-1.amazonaws.com",
          "eu-west-1"))
     .withCredentials(CREDENTIALS_PROVIDER)
     .build();
```

有关所有 AWS 服务的[区域及其相应终端节点](https://docs.aws.amazon.com/general/latest/gr/rande.html)的当前列表，请参阅区域和终端节点。

## 根据环境自动确定区域
<a name="automatically-determine-the-aws-region-from-the-environment"></a>

**重要**  
本节仅在使用[客户端生成器](creating-clients.md)访问 AWS 服务时适用。 AWS 使用客户端构造函数创建的客户端不会自动从环境中确定区域，而是使用*默认*的 SDK 区域 (USEast1)。

在 Amazon EC2 或 Lambda 上运行时，您可能需要将客户端配置为使用与代码运行相同的区域。由此可以将代码从其运行的环境中脱离，更轻松地将应用程序部署到多个区域以减少延迟并保证冗余。

 *必须使用客户端生成器，使开发工具包可自动检测代码的运行区域。*

要使用默认 credential/region 提供程序链从环境中确定区域，请使用客户端生成器的`defaultClient`方法。

```
AmazonEC2 ec2 = AmazonEC2ClientBuilder.defaultClient();
```

这与使用 `standard` 再加上 `build` 相同。

```
AmazonEC2 ec2 = AmazonEC2ClientBuilder.standard()
                    .build();
```

如果您没有使用 `withRegion` 方法明确设置一个区域，开发工具包将参考默认区域提供程序链来尝试并确定要使用的区域。

### 默认区域提供程序链
<a name="default-region-provider-chain"></a>

 **区域查找过程如下：**

1. 通过生成器本身使用 `withRegion` 或 `setRegion` 明确设置的所有区域优先于其他所有区域。

1. 系统会检查 `AWS_REGION` 环境变量。如果已设置该变量，将使用对应区域配置客户端。
**注意**  
此环境变量由 Lambda 容器设置。

1. SDK 会检查 AWS 共享配置文件（通常位于`~/.aws/config`）。如果 *region* 属性存在，则 SDK 会使用该属性。
   + `AWS_CONFIG_FILE` 环境变量可用于自定义共享配置文件的位置。
   + 可以使用 `AWS_PROFILE` 环境变量或 `aws.profile` 系统属性，自定义 SDK 要加载的配置文件。

1. SDK 尝试使用 Amazon EC2 实例元数据服务来确定当前正在运行的 Amazon EC2 实例的区域。

1. 如果开发工具包此时仍不能确定区域，则客户端创建将失败并返回异常。

开发 AWS 应用程序时，常见的方法是使用*共享配置文件*（如[使用默认凭证提供程序链](credentials.md#credentials-default)中所述）来设置本地开发的区域，并在 AWS 基础设施上运行时依靠默认区域提供商链来确定区域。这可以明显简化客户端创建，并保证应用程序的便携性。

# 异常处理
<a name="java-dg-exceptions"></a>

了解 适用于 Java 的 AWS SDK 抛出异常的方式和时间对于使用 SDK 构建高质量的应用程序非常重要。接下来几节介绍开发工具包引发异常的几种不同情况，以及如何正确地处理这些异常。

## 为什么使用未选中的异常？
<a name="why-unchecked-exceptions"></a>

出于以下原因， 适用于 Java 的 AWS SDK 使用运行时（或未选中）异常而不是已检查的异常：
+ 使开发人员能够精细控制要处理哪些错误，而不是必须处理无关紧要的异常情况（这会导致代码极其冗长）
+ 避免大型应用程序因使用选中的异常而固有的可扩展性问题

一般来说，小型应用程序使用选中的异常是可以的，但随着应用程序的大小和复杂程度增加，这样做就会出现问题。

有关使用选中和未选中的异常的更多信息，请参阅：
+  [未选中的异常 - 争议](http://docs.oracle.com/javase/tutorial/essential/exceptions/runtime.html) 
+  [使用选中的异常时的问题](http://www.artima.com/intv/handcuffs2.html) 
+  [Java 中选中的异常是一个错误（下文会说明我要如何处理这些异常）](http://radio-weblogs.com/0122027/stories/2003/04/01/JavasCheckedExceptionsWereAMistake.html) 

## AmazonServiceException （和子类）
<a name="amazonserviceexception-and-subclasses"></a>

 [AmazonServiceException](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/AmazonServiceException.html)是您在使用时遇到的最常见的异常 适用于 Java 的 AWS SDK。该异常是指来自 AWS 服务的错误响应。例如，如果您尝试终止不存在的 Amazon EC2 实例，EC2 将返回错误响应，并且该错误响应的所有详细信息都将包含在抛出的错误响应中。`AmazonServiceException`在某些情况下，会引发 `AmazonServiceException` 的一个子类，使开发人员能够通过捕获模块精细控制如何处理错误情况。

遇到时`AmazonServiceException`，您就知道您的请求已成功发送到， AWS 服务 但无法成功处理。这可能是因为请求的参数中存在错误，或者是因为服务端的问题。

 `AmazonServiceException` 为您提供很多信息，例如：
+ 返回的 HTTP 状态代码
+ 返回的 AWS 错误码
+ 来自服务的详细错误消息
+  AWS 失败请求的请求 ID

 `AmazonServiceException`还包括有关失败的请求是调用者的错误（具有非法值的请求）还是调用 AWS 服务者的错误（内部服务错误）的信息。

## AmazonClientException
<a name="amazonclientexception"></a>

 [AmazonClientException](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/AmazonClientException.html)表示 Java 客户端代码内部出现问题，无论是在尝试向发送请求时 AWS 还是尝试解析来自 AWS的响应时。`AmazonClientException`通常比 a 更严重`AmazonServiceException`，表示存在阻止客户端向 AWS 服务发出服务调用的主要问题。例如，当您尝试在其中一个客户端上调用操作时，`AmazonClientException`如果没有可用的网络连接，则会 适用于 Java 的 AWS SDK 抛出。

# 异步编程
<a name="basics-async"></a>

您可以使用*同步*或*异步*方法来调用对 AWS 服务的操作。同步方法会阻止执行您的线程，直到客户端接收到服务的响应。异步方法会立即返回，并控制调用的线程，而不必等待响应。

由于异步方法在收到响应之前返回，所以需要通过某种方法在响应准备就绪时接收响应。 适用于 Java 的 AWS SDK 提供了两种方法：F *uture 对象*和*回调方法*。

## Java Futures
<a name="basics-async-future"></a>

中的异步方法 适用于 Java 的 AWS SDK 返回一个 F [ut](https://docs.oracle.com/javase/8/docs/api/index.html?java/util/concurrent/Future.html) ure 对象，该对象包含*将来异步操作的*结果。

调用 `Future` `isDone()` 方法，确定该服务是否已提供响应对象。当响应准备好时，可以通过调用 `Future` `get()` 方法来获取响应对象。在应用程序继续处理其他任务时，可使用该机制定期轮询异步操作的结果。

以下是一个异步操作的示例，该异步操作调用 Lambda 函数，接收`Future`可以容纳[InvokeResult](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/services/lambda/model/InvokeResult.html)对象的函数。`InvokeResult` 对象仅在 `isDone()` 为 `true` 时可检索到。

```
import com.amazonaws.services.lambda.AWSLambdaAsyncClient;
import com.amazonaws.services.lambda.model.InvokeRequest;
import com.amazonaws.services.lambda.model.InvokeResult;
import java.nio.ByteBuffer;
import java.util.concurrent.Future;
import java.util.concurrent.ExecutionException;

public class InvokeLambdaFunctionAsync
{
    public static void main(String[] args)
    {
        String function_name = "HelloFunction";
        String function_input = "{\"who\":\"SDK for Java\"}";

        AWSLambdaAsync lambda = AWSLambdaAsyncClientBuilder.defaultClient();
        InvokeRequest req = new InvokeRequest()
            .withFunctionName(function_name)
            .withPayload(ByteBuffer.wrap(function_input.getBytes()));

        Future<InvokeResult> future_res = lambda.invokeAsync(req);

        System.out.print("Waiting for future");
        while (future_res.isDone() == false) {
            System.out.print(".");
            try {
                Thread.sleep(1000);
            }
            catch (InterruptedException e) {
                System.err.println("\nThread.sleep() was interrupted!");
                System.exit(1);
            }
        }

        try {
            InvokeResult res = future_res.get();
            if (res.getStatusCode() == 200) {
                System.out.println("\nLambda function returned:");
                ByteBuffer response_payload = res.getPayload();
                System.out.println(new String(response_payload.array()));
            }
            else {
                System.out.format("Received a non-OK response from {AWS}: %d\n",
                        res.getStatusCode());
            }
        }
        catch (InterruptedException | ExecutionException e) {
            System.err.println(e.getMessage());
            System.exit(1);
        }

        System.exit(0);
    }
}
```

## 异步回调
<a name="basics-async-callback"></a>

除了使用 Java `Future` 对象监控异步请求的状态外，SDK 还允许您实现使用该[AsyncHandler](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/handlers/AsyncHandler.html)接口的类。 `AsyncHandler`提供了两种根据请求完成方式调用的方法：`onSuccess`和`onError`。

回调接口方法的主要优势是它让您无需轮询 `Future` 对象即可确定请求是否已完成。相反，您的代码能够立即开始其下一个活动，并由开发工具包在适当时调用处理程序。

```
import com.amazonaws.services.lambda.AWSLambdaAsync;
import com.amazonaws.services.lambda.AWSLambdaAsyncClientBuilder;
import com.amazonaws.services.lambda.model.InvokeRequest;
import com.amazonaws.services.lambda.model.InvokeResult;
import com.amazonaws.handlers.AsyncHandler;
import java.nio.ByteBuffer;
import java.util.concurrent.Future;

public class InvokeLambdaFunctionCallback
{
    private class AsyncLambdaHandler implements AsyncHandler<InvokeRequest, InvokeResult>
    {
        public void onSuccess(InvokeRequest req, InvokeResult res) {
            System.out.println("\nLambda function returned:");
            ByteBuffer response_payload = res.getPayload();
            System.out.println(new String(response_payload.array()));
            System.exit(0);
        }

        public void onError(Exception e) {
            System.out.println(e.getMessage());
            System.exit(1);
        }
    }

    public static void main(String[] args)
    {
        String function_name = "HelloFunction";
        String function_input = "{\"who\":\"SDK for Java\"}";

        AWSLambdaAsync lambda = AWSLambdaAsyncClientBuilder.defaultClient();
        InvokeRequest req = new InvokeRequest()
            .withFunctionName(function_name)
            .withPayload(ByteBuffer.wrap(function_input.getBytes()));

        Future<InvokeResult> future_res = lambda.invokeAsync(req, new AsyncLambdaHandler());

        System.out.print("Waiting for async callback");
        while (!future_res.isDone() && !future_res.isCancelled()) {
            // perform some other tasks...
            try {
                Thread.sleep(1000);
            }
            catch (InterruptedException e) {
                System.err.println("Thread.sleep() was interrupted!");
                System.exit(0);
            }
            System.out.print(".");
        }
    }
}
```

## 最佳实践
<a name="basics-async-tips"></a>

### 回调执行
<a name="callback-execution"></a>

`AsyncHandler` 的实施在异步客户端拥有的线程池内执行。简短、快速执行的代码在您的 `AsyncHandler` 实施内最适合。如果您的处理程序方法包含长时间运行的代码或阻码，会导致对异步客户端所使用线程池的争用，并阻止客户端执行请求。如果需要从回调开始一种长期运行的任务，请在新的线程或应用程序托管的线程池中让回调运行其任务。

### 线程池配置
<a name="thread-pool-configuration"></a>

中的异步客户端 适用于 Java 的 AWS SDK 提供了一个适用于大多数应用程序的默认线程池。您可以实现自定义[ExecutorService](https://docs.oracle.com/javase/8/docs/api/index.html?java/util/concurrent/ExecutorService.html)并将其传递给 适用于 Java 的 AWS SDK 异步客户端，以便更好地控制线程池的管理方式。

例如，您可以提供一个`ExecutorService`实现，该实现使用自定义[ThreadFactory](https://docs.oracle.com/javase/8/docs/api/index.html?java/util/concurrent/ThreadFactory.html)来控制池中线程的命名方式，或者记录有关线程使用情况的其他信息。

### 异步访问
<a name="s3-asynchronous-access"></a>

SDK 中的[TransferManager](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/services/s3/transfer/TransferManager.html)类为使用提供了异步支持 Amazon S3。 `TransferManager`管理异步上传和下载，提供详细的传输进度报告，并支持对不同事件的回调。

# 记录 适用于 Java 的 AWS SDK 通话
<a name="java-dg-logging"></a>

使用 [Apache Commons Log](http://commons.apache.org/proper/commons-logging/guide.html) ging 进行检测，Apache Commons Logging 是一个抽象层，允许在运行时使用多个日志系统中的任何一个。 适用于 Java 的 AWS SDK 

支持的日志记录系统包括 Java Logging Framework、Apache Log4j 和其他系统。本主题介绍如何使用 Log4j。无需对您的应用程序代码进行任何更改，就可以使用开发工具包的日志记录功能。

要了解有关 [Log4j](http://logging.apache.org/log4j/2.x/) 的更多信息，请参阅 [Apache 网站](http://www.apache.org/)。

**注意**  
本主题主要介绍 Log4j 1.x。Log4j2 不直接支持 Apache Commons Logging，但提供一个适配器，将日志记录调用定向到使用 Apache Commons Logging 界面的 Log 4j2。有关更多信息，请参阅 Log4j2 文档中的 [Commons Logging Bridge](https://logging.apache.org/log4j/2.x/log4j-jcl.html)。

## 下载 Log4J JAR
<a name="download-the-log4j-jar"></a>

要将 Log4j 与开发工具包一起使用，需要从 Apache 网站下载 Log4j JAR。该开发工具包不包括 JAR。将 JAR 文件复制到类路径中的位置。

Log4j 使用配置文件 log4j.properties。配置文件示例如下所示。将该配置文件复制到类路径中的目录中。Log4j JAR 和 log4j.properties 文件不需要在同一目录中。

log4j.properties 配置文件会指定[日志记录级别](http://logging.apache.org/log4j/2.x/manual/configuration.html#Loggers)、发送日志记录输出的位置（例如：[发送到文件或控制台](http://logging.apache.org/log4j/2.x/manual/appenders.html)）以及[输出格式](http://logging.apache.org/log4j/2.x/manual/layouts.html)等属性。日志级别是记录器生成输出的粒度。Log4j 支持多个日志记录*层次结构* 的概念。可以为每级层次结构单独设置日志记录级别。 适用于 Java 的 AWS SDK支持以下两个日志记录层次结构：
+ log4j.logger.com.amazonaws
+ log4j.logger.org.apache.http.wire

## 设置类路径
<a name="sdk-net-logging-classpath"></a>

Log4j JAR 和 log4j.properties 文件都必须位于类路径中。如果您使用 [Apache Ant](http://ant.apache.org/manual/)，则在 Ant 文件的 `path` 元素中设置类路径。以下示例显示 SDK 附带的 Amazon S3 [示例](https://github.com/aws/aws-sdk-java/blob/master/src/samples/AmazonS3/build.xml)中 Ant 文件的路径元素。

```
<path id="aws.java.sdk.classpath">
  <fileset dir="../../third-party" includes="**/*.jar"/>
  <fileset dir="../../lib" includes="**/*.jar"/>
  <pathelement location="."/>
</path>
```

如果您使用 Eclipse IDE，可以打开菜单并导航到 **Project (项目)** \$1 **Properties (属性)** \$1 **Java Build Path (Java 构建路径)** 来设置类路径。

## 特定服务的错误消息和警告
<a name="sdk-net-logging-service"></a>

我们建议您始终将“com.amazonaws”记录器层次结构设置为“WARN”，以保证不会错过来自客户端库的任何重要消息。例如，如果 Amazon S3 客户端检测到您的应用程序未正确关闭`InputStream`并可能泄漏资源，则 S3 客户端会通过警告消息将其报告到日志。另外，由此可确保客户端在处理请求或响应遇到任何问题时会记录相应消息。

以下 log4j.properties 文件将 `rootLogger` 设置为 WARN，也就是包含“com.amazonaws”层次结构中所有记录器发送的警告和错误消息。您也可以将 com.amazonaws 记录器明确设置为 WARN。

```
log4j.rootLogger=WARN, A1
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%d [%t] %-5p %c -  %m%n
# Or you can explicitly enable WARN and ERROR messages for the {AWS} Java clients
log4j.logger.com.amazonaws=WARN
```

## 请求/响应摘要日志记录
<a name="sdk-net-logging-request-response"></a>

对的每个请求都会 AWS 服务 生成一个唯一的 AWS 请求 ID，如果您在如何处理请求时遇到问题， AWS 服务 这会很有用。 AWS 对于任何失败的服务调用，都可以通过软件开发工具包中的异常对象以编程方式访问请求 IDs ，也可以通过 “com.amazonaws.request” 记录器中的调试日志级别报告请求。

以下 log4j.properties 文件支持请求和响应（包括请求）的摘要。 AWS IDs

```
log4j.rootLogger=WARN, A1
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%d [%t] %-5p %c -  %m%n
# Turn on DEBUG logging in com.amazonaws.request to log
# a summary of requests/responses with {AWS} request IDs
log4j.logger.com.amazonaws.request=DEBUG
```

以下是日志输出的示例。

```
2009-12-17 09:53:04,269 [main] DEBUG com.amazonaws.request - Sending
Request: POST https://rds.amazonaws.com / Parameters: (MaxRecords: 20,
Action: DescribeEngineDefaultParameters, SignatureMethod: HmacSHA256,
AWSAccessKeyId: ACCESSKEYID, Version: 2009-10-16, SignatureVersion: 2,
Engine: mysql5.1, Timestamp: 2009-12-17T17:53:04.267Z, Signature:
q963XH63Lcovl5Rr71APlzlye99rmWwT9DfuQaNznkD, ) 2009-12-17 09:53:04,464
[main] DEBUG com.amazonaws.request - Received successful response: 200, {AWS}
Request ID: 694d1242-cee0-c85e-f31f-5dab1ea18bc6 2009-12-17 09:53:04,469
[main] DEBUG com.amazonaws.request - Sending Request: POST
https://rds.amazonaws.com / Parameters: (ResetAllParameters: true, Action:
ResetDBParameterGroup, SignatureMethod: HmacSHA256, DBParameterGroupName:
java-integ-test-param-group-0000000000000, AWSAccessKeyId: ACCESSKEYID,
Version: 2009-10-16, SignatureVersion: 2, Timestamp:
2009-12-17T17:53:04.467Z, Signature:
9WcgfPwTobvLVcpyhbrdN7P7l3uH0oviYQ4yZ+TQjsQ=, )

2009-12-17 09:53:04,646 [main] DEBUG com.amazonaws.request - Received
successful response: 200, {AWS} Request ID:
694d1242-cee0-c85e-f31f-5dab1ea18bc6
```

## 详细线路日志记录
<a name="sdk-net-logging-verbose"></a>

在某些情况下，查看 适用于 Java 的 AWS SDK 发送和接收的确切请求和响应可能会很有用。您不应在生产系统中启用此日志记录，因为写出大型请求（例如，正在上传到的文件 Amazon S3）或响应可能会大大降低应用程序的速度。如果您确实需要访问这些信息，可以通过 Apache HttpClient 4 记录器暂时将其启用。如果在 `org.apache.http.wire` 记录器中启用 DEBUG 级别，会记录所有请求和响应数据。

以下 log4j.properties 文件在 Apache HttpClient 4 中开启了全线日志记录，只能暂时开启，因为它可能会对应用程序的性能产生重大影响。

```
log4j.rootLogger=WARN, A1
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%d [%t] %-5p %c -  %m%n
# Log all HTTP content (headers, parameters, content, etc)  for
# all requests and responses. Use caution with this since it can
# be very expensive to log such verbose data!
log4j.logger.org.apache.http.wire=DEBUG
```

## 延迟指标日志记录
<a name="sdk-latency-logging"></a>

如果您正在进行故障排除，并且希望查看诸如哪个进程占用了最多时间或者是服务器还是客户端具有更大延迟等指标，则延迟记录器可能会很有用。将 `com.amazonaws.latency` 记录器设置为 DEBUG 可启用此记录器。

**注意**  
此记录器仅在启用开发工具包指标时才可用。要了解更多有关 SDK 指标包的更多信息，请参阅[对 适用于 Java 的 AWS SDK启用指标](generating-sdk-metrics.md)。

```
log4j.rootLogger=WARN, A1
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%d [%t] %-5p %c -  %m%n
log4j.logger.com.amazonaws.latency=DEBUG
```

以下是日志输出的示例。

```
com.amazonaws.latency - ServiceName=[{S3}], StatusCode=[200],
ServiceEndpoint=[https://list-objects-integ-test-test.s3.amazonaws.com],
RequestType=[ListObjectsV2Request], AWSRequestID=[REQUESTID], HttpClientPoolPendingCount=0,
RetryCapacityConsumed=0, HttpClientPoolAvailableCount=0, RequestCount=1,
HttpClientPoolLeasedCount=0, ResponseProcessingTime=[52.154], ClientExecuteTime=[487.041],
HttpClientSendRequestTime=[192.931], HttpRequestTime=[431.652], RequestSigningTime=[0.357],
CredentialsRequestTime=[0.011, 0.001], HttpClientReceiveResponseTime=[146.272]
```

# 客户端配置
<a name="section-client-configuration"></a>

 适用于 Java 的 AWS SDK 允许您更改默认的客户机配置，这在您想要执行以下操作时很有用：
+ 通过代理连接到 Internet
+ 更改 HTTP 传输设置，例如连接超时和请求重试次数
+ 指定 TCP 套接字缓冲区大小提示

## 代理配置
<a name="proxy-configuration"></a>

在构造客户端对象时，您可以传入一个可选[ClientConfiguration](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/ClientConfiguration.html)对象来自定义客户端的配置。

如果您通过代理服务器连接到 Internet，则将需要通过 `ClientConfiguration` 对象配置代理服务器设置（代理主机、端口和用户名/密码）。

## HTTP 传输配置
<a name="http-transport-configuration"></a>

您可以使用[ClientConfiguration](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/ClientConfiguration.html)对象配置多个 HTTP 传输选项。偶尔会添加新选项；要查看您可以检索或设置的选项的完整列表，请参阅 适用于 Java 的 AWS SDK API 参考。

**注意**  
每个可配置的值都有一个由常量定义的默认值。有关常量值的列表`ClientConfiguration`，请参阅 适用于 Java 的 AWS SDK API 参考中的[常量字段值](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/constant-values.html)。

### 最大连接数
<a name="maximum-connections"></a>

您可以使用设置允许打开的 HTTP 连接的最大数量[ClientConfiguration。 setMaxConnections](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/ClientConfiguration.html#setMaxConnections-int-)方法。

**重要**  
将最大连接数设置为并发事务的数量可避免连接争用和性能不佳。有关默认的最大连接数值，请参阅 适用于 Java 的 AWS SDK API 参考中的[常量字段值](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/constant-values.html)。

### 超时和错误处理
<a name="timeouts-and-error-handling"></a>

可以设置与 HTTP 连接超时和处理错误相关的选项。
+  **Connection Timeout** 

  连接超时是指 HTTP 连接在放弃连接之前等待建立连接的时间长度 (用毫秒表示)。默认值为 10,000 毫秒。

  要自己设置此值，请使用[ClientConfiguration。 setConnectionTimeout](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/ClientConfiguration.html#setConnectionTimeout-int-)方法。
+  **Connection Time to Live (TTL)** 

  默认情况下，开发工具包将尝试尽可能长时间地重用 HTTP 连接。如果因建立连接的服务器已停止服务而失败，则将 TTL 设置为有限值可能会有助于恢复应用程序。例如，将 TTL 设置为 15 分钟可确保您将在 15 分钟内与新服务器重新建立连接，即使您已经与出现问题的服务器建立了连接也是如此。

  要设置 HTTP 连接 TTL，请使用 [ClientConfiguration.set](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/ClientConfiguration.html#setConnectionTTL-long-) ConnectionTTL 方法。
+  **Maximum Error Retries** 

  可重试的错误的默认最大重试次数为 3。您可以使用设置不同的值[ClientConfiguration。 setMaxError重试](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/ClientConfiguration.html#setMaxErrorRetry-int-)方法。

### 本地地址
<a name="local-address"></a>

要设置 HTTP 客户端将绑定的本地地址，请使用[ClientConfiguration。 setLocalAddress](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/ClientConfiguration.html#setLocalAddress-java.net.InetAddress-)。

## TCP 套接字缓冲区大小提示
<a name="tcp-socket-buffer-size-hints"></a>

想要调整低级 TCP 参数的高级用户还可以通过[ClientConfiguration](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/ClientConfiguration.html)对象设置 TCP 缓冲区大小提示。大多数用户永远不需要调整这些值，这些值是为高级用户提供的。

应用程序的最佳 TCP 缓冲区大小高度依赖网络和操作系统的配置和功能。例如，大多数现代操作系统都为 TCP 缓冲区大小提供了自动调整逻辑，对于需要长时间保持打开状态才能使自动调整功能优化缓冲区大小的 TCP 连接，自动调整逻辑会对连接性能产生很大的影响。

大型缓冲区大小 (例如，2 MB) 将允许操作系统在内存中缓冲更多的数据，而无需远程服务器确认收到该信息，因此，这在网络延迟时间很长时尤其有用。

这仅是一个*提示*，操作系统可以选择不遵守它。在使用此选项时，用户应当始终检查在操作系统中配置的限值和默认值。大多数操作系统都配置了最大 TCP 缓冲区大小限值，除非您明确提升了最大 TCP 缓冲区大小限值，否则操作系统将不允许您超出此限值。

可以使用许多资源来帮助配置 TCP 缓冲区大小和特定于操作系统的 TCP 设置，其中包括：
+  [主机调整](http://fasterdata.es.net/host-tuning/) 

# 访问控制策略
<a name="java-dg-access-control"></a>

 AWS *访问控制策略*使您能够对资源指定精细的访问控制。 AWS 访问控制策略包含一组*语句*，其形式如下：

 在*条件 D* 适用的情况下，*账户 A* 有权对*资源 C* 执行*操作 B*。

其中：
+  *A* 是*委托人* AWS 账户 ，即请求访问或修改您的某个 AWS 资源。
+  *B* 是*操作*-访问或修改 AWS 资源的方式，例如向 Amazon SQS 队列发送消息或将对象存储在存储 Amazon S3 桶中。
+  *C* 是*资源*-委托人想要访问的 AWS 实体，例如 Amazon SQS 队列或存储在中的对象 Amazon S3。
+  *D* 是*一组条件* – 指定何时允许或拒绝主体访问资源的可选约束。有许多富有表现力的条件，还有一些特定于每项服务的条件。例如，您可以使用日期条件以仅允许在特定时间之后或之前访问资源。

## Amazon S3 示例
<a name="s3-example"></a>

以下示例演示了一项策略，该策略允许任何人访问存储桶中的所有对象，但将向该存储桶上传对象的访问权限限制为两个特定 AWS 账户的（存储桶拥有者的账户除外）。

```
Statement allowPublicReadStatement = new Statement(Effect.Allow)
    .withPrincipals(Principal.AllUsers)
    .withActions(S3Actions.GetObject)
    .withResources(new S3ObjectResource(myBucketName, "*"));
Statement allowRestrictedWriteStatement = new Statement(Effect.Allow)
    .withPrincipals(new Principal("123456789"), new Principal("876543210"))
    .withActions(S3Actions.PutObject)
    .withResources(new S3ObjectResource(myBucketName, "*"));

Policy policy = new Policy()
    .withStatements(allowPublicReadStatement, allowRestrictedWriteStatement);

AmazonS3 s3 = AmazonS3ClientBuilder.defaultClient();
s3.setBucketPolicy(myBucketName, policy.toJson());
```

## Amazon SQS 示例
<a name="sqs-example"></a>

策略的一个常见用途是授权 Amazon SQS 队列接收来自 Amazon SNS 主题的消息。

```
Policy policy = new Policy().withStatements(
    new Statement(Effect.Allow)
        .withPrincipals(Principal.AllUsers)
        .withActions(SQSActions.SendMessage)
        .withConditions(ConditionFactory.newSourceArnCondition(myTopicArn)));

Map queueAttributes = new HashMap();
queueAttributes.put(QueueAttributeName.Policy.toString(), policy.toJson());

AmazonSQS sqs = AmazonSQSClientBuilder.defaultClient();
sqs.setQueueAttributes(new SetQueueAttributesRequest(myQueueUrl, queueAttributes));
```

## Amazon SNS 示例
<a name="sns-example"></a>

一些服务提供可用于策略的其他条件。Amazon SNS 根据订阅主题请求的协议（例如电子邮件、HTTP、HTTPS Amazon SQS）和终端节点（例如电子邮件地址、URL、 Amazon SQS ARN）为允许或拒绝订阅 SNS 主题提供了条件。

```
Condition endpointCondition =
    SNSConditionFactory.newEndpointCondition("*@mycompany.com");

Policy policy = new Policy().withStatements(
    new Statement(Effect.Allow)
        .withPrincipals(Principal.AllUsers)
        .withActions(SNSActions.Subscribe)
        .withConditions(endpointCondition));

AmazonSNS sns = AmazonSNSClientBuilder.defaultClient();
sns.setTopicAttributes(
    new SetTopicAttributesRequest(myTopicArn, "Policy", policy.toJson()));
```

# 为 DNS 名称查找设置 JVM TTL
<a name="jvm-ttl-dns"></a>

Java 虚拟机 (JVM) 缓存 DNS 名称查找。当 JVM 将主机名解析为 IP 地址时，它会将该 IP 地址缓存一段指定的时间，即 *time-to-live*(TTL)。

由于 AWS 资源使用的 DNS 名称条目偶尔会发生变化，因此我们建议您将 JVM 的 TTL 值配置为 5 秒。这可确保在资源的 IP 地址发生更改时，您的应用程序将能够通过重新查询 DNS 来接收和使用资源的新 IP 地址。

对于一些 Java 配置，将设置 JVM 默认 TTL，以便在重新启动 JVM 之前*绝不* 刷新 DNS 条目。因此，如果在应用程序仍在运行时 AWS 资源的 IP 地址发生变化，则在您*手动重启* JVM 并刷新缓存的 IP 信息之前，它将无法使用该资源。在此情况下，设置 JVM 的 TTL，以便定期刷新其缓存的 IP 信息是极为重要的。

## 如何设置 JVM TTL
<a name="how-to-set-the-jvm-ttl"></a>

要修改 JVM 的 TTL，请设置 net [workaddress.cache.ttl 安全属性值。](https://docs.oracle.com/en/java/javase/17/core/java-networking.html#GUID-A680DADB-C4C1-40F1-B568-D9A97C917F5D)请注意，`networkaddress.cache.ttl`这是一个*安全属性*，而不是系统属性，也就是说，它不能使用`-D`命令行标志进行设置。

### 选项 1：在应用程序中以编程方式进行设置
<a name="set-ttl-programmatically"></a>

在应用程序启动的[https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/security/Security.html](https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/security/Security.html)早期、创建任何 AWS SDK 客户端之前和发出任何网络请求之前调用：

```
import java.security.Security;

public class MyApplication {
    public static void main(String[] args) {
        Security.setProperty("networkaddress.cache.ttl", "5");

        // ... create SDK clients and run application
    }
}
```

### 选项 2：将其设置在 java.security 文件中
<a name="set-ttl-java-security-file"></a>

在`$JAVA_HOME/jre/lib/security/java.security`文件中为 Java 8 或更高版本设置该`networkaddress.cache.ttl`属性，在 Java 11 或更高版本`$JAVA_HOME/conf/security/java.security`的文件中设置该属性。

以下是 `java.security` 文件中的代码段，该代码段显示 TTL 缓存设置为 5 秒。

```
#
# The Java-level namelookup cache policy for successful lookups:
#
# any negative value: caching forever
# any positive value: the number of seconds to cache an address for
# zero: do not cache
#
...
networkaddress.cache.ttl=5
...
```

在由`$JAVA_HOME`环境变量表示的 JVM 上运行的所有应用程序都使用此设置。

### 选项 3：使用 JDK 系统属性回退（命令行）
<a name="set-ttl-system-property"></a>

如果无法修改安全配置或代码，则可以使用 JDK 系统属性。如果未定义安全属性，则这些属性充当后备选项。
+ `sun.net.inetaddr.ttl`— 控制成功查找（TTL 为正）
+ `sun.net.inetaddr.negative.ttl`— 控制失败的查找（负的 TTL）

```
java -Dsun.net.inetaddr.ttl=5 -Dsun.net.inetaddr.negative.ttl=1 -jar myapp.jar
```

**注意**  
这些是 [Oracle Java 8 网络属性参考文献中记录的 JDK 内部属性](https://docs.oracle.com/javase/8/docs/technotes/guides/net/properties.html)，作为 “未来的版本可能不支持” 的私有属性。尽可能使用选项 1-2。

# 为启用指标 适用于 Java 的 AWS SDK
<a name="generating-sdk-metrics"></a>

 适用于 Java 的 AWS SDK 可以生成用于通过 [Amazon](https://aws.amazon.com/cloudwatch/) 进行可视化和监控的指标，这些指标 CloudWatch可以衡量：
+ 您的应用程序在访问时的性能 AWS 
+ 与一起使用 JVMs 时的表现 AWS 
+ 运行时环境详细信息，例如堆内存、线程数和已打开的文件描述符

## 如何启用 Java SDK 指标生成
<a name="how-to-enable-sdk-java-metric-generation"></a>

您需要添加以下 Maven 依赖项才能让 SDK 向其发送指标。 CloudWatch

```
<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>com.amazonaws</groupId>
      <artifactId>aws-java-sdk-bom</artifactId>
      <version>1.12.490*</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>
<dependencies>
  <dependency>
    <groupId>com.amazonaws</groupId>
    <artifactId>aws-java-sdk-cloudwatchmetrics</artifactId>
    <scope>provided</scope>
  </dependency>
  <!-- Other SDK dependencies. -->
</dependencies>
```

 \$1将版本号替换为 [Maven Central](https://central.sonatype.com/artifact/com.amazonaws/aws-java-sdk-bom) 上可用的最新版 SDK。

适用于 Java 的 AWS SDK *默认情况下，指标处于禁用状态*。要为您的本地开发环境启用此功能，请在启动 JVM 时包括指向您的 AWS 安全凭证文件的系统属性。例如：

```
-Dcom.amazonaws.sdk.enableDefaultMetrics=credentialFile=/path/aws.properties
```

您需要指定证书文件的路径，以便 SDK 可以将收集到的数据点上传到以 CloudWatch 供日后分析。

**注意**  
如果您使用 Amazon EC2 实例元数据服务 AWS 从 Amazon EC2 实例进行访问，则无需指定凭证文件。在这种情况下，您只需要指定以下各项：  

```
-Dcom.amazonaws.sdk.enableDefaultMetrics
```

捕获的所有指标都位于命名空间 **AWSSDK/Java** 下，并上传到 CloudWatch 默认区域 (us *-east-1*)。 适用于 Java 的 AWS SDK 要更改该区域，请使用系统属性中的 `cloudwatchRegion` 属性来指定它。例如，要将 CloudWatch 区域设置为 us-ea *st-1*，请使用：

```
-Dcom.amazonaws.sdk.enableDefaultMetrics=credentialFile=/path/aws.properties,cloudwatchRegion={region_api_default}
```

启用该功能后，每次有 AWS 来自的服务请求时，都会生成指标数据点 适用于 Java 的 AWS SDK，排队等候统计摘要，然后异步上传到 CloudWatch 大约每分钟一次。指标一旦上传，您就可以使用 [AWS 管理控制台](https://console.aws.amazon.com/console/home)将其可视化，并设置潜在问题的警报，如内存泄露、文件描述符泄露等等。

## 可用指标类型
<a name="available-metric-types"></a>

默认指标组分为三大类：

 AWS 请求指标  
+ 涵盖诸如 HTTP 请求/响应的延迟、请求数量、异常和重试等领域。  
![\[RequestMetric 131111\]](http://docs.aws.amazon.com/zh_cn/sdk-for-java/v1/developer-guide/images/RequestMetric-131111.png)

 AWS 服务 指标  
+ 包括 AWS 服务特定数据，例如 S3 上传和下载的吞吐量和字节数。  
![\[ServiceMetric 131111\]](http://docs.aws.amazon.com/zh_cn/sdk-for-java/v1/developer-guide/images/ServiceMetric-131111.png)

机器指标  
+ 涵盖运行时环境，包括堆内存、线程数和打开的文件描述符。  
![\[MachineMetric 131111\]](http://docs.aws.amazon.com/zh_cn/sdk-for-java/v1/developer-guide/images/MachineMetric-131111.png)

  如果您想要排除机器指标，请在系统属性中添加 `excludeMachineMetrics`：

  ```
  -Dcom.amazonaws.sdk.enableDefaultMetrics=credentialFile=/path/aws.properties,excludeMachineMetrics
  ```

## 更多信息
<a name="more-information"></a>
+ 有关预定义核心指标类型的完整列表，请参阅 [amazonaws/metrics package summary](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/metrics/package-summary.html)。
+  适用于 Java 的 AWS SDK 在 “ CloudWatch 使用[CloudWatch 示例” 中了解如何使用 适用于 Java 的 AWS SDK](examples-cloudwatch.md)。
+ 要了解有关性能调整的更多信息，请参[阅 “调整 适用于 Java 的 AWS SDK 以提高弹性](https://aws.amazon.com/blogs/developer/tuning-the-aws-sdk-for-java-to-improve-resiliency)” 博客文章。