

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

# 使用 Amazon EC2 实例元数据
<a name="examples-ec2-IMDS"></a>

适用于 Amazon EC2 实例元数据服务的 Java SDK 客户端（元数据客户端）允许您的应用程序访问其本地 EC2 实例上的元数据。元数据客户端使用本地实例 [IMDSv2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html)（实例元数据服务 v2），并使用面向会话的请求。

SDK 中有两个客户端类可用。同步 `[Ec2MetadataClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/imds/Ec2MetadataClient.html)` 用于阻塞操作，[https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/imds/Ec2MetadataAsyncClient.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/imds/Ec2MetadataAsyncClient.html) 用于异步、非阻塞用例。

## 开始使用
<a name="examples-ec2-IMDS-getstarted"></a>

要使用元数据客户端，请将 `imds` Maven 构件添加到您的项目中。您还需要在类路径上具有 `[SdkHttpClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/http/SdkHttpClient.html)` 的类，或对于异步变体而言，具有 `[SdkAsyncHttpClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/http/async/SdkAsyncHttpClient.html)` 的类。

以下 Maven XML 显示了使用同步的依赖关系片段[UrlConnectionHttpClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/http/urlconnection/UrlConnectionHttpClient.html)以及元数据客户端的依赖关系。

```
<dependencyManagement>
   <dependencies>
        <dependency>
            <groupId>software.amazon.awssdk</groupId>
            <artifactId>bom</artifactId>
            <version>VERSION</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
    <dependency>
        <groupId>software.amazon.awssdk</groupId>
        <artifactId>imds</artifactId>
    </dependency>
    <dependency>
        <groupId>software.amazon.awssdk</groupId>
        <artifactId>url-connection-client</artifactId>
    </dependency>
    <!-- other dependencies --> 
</dependencies>
```

在 [Maven Central 存储库](https://central.sonatype.com/artifact/software.amazon.awssdk/bom)中搜索 `bom` 构件的最新版本。

要使用异步 HTTP 客户端，请替换 `url-connection-client` 构件的依赖项片段。例如，以下代码段引入了[NettyNioAsyncHttpClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/http/nio/netty/NettyNioAsyncHttpClient.html)实现。

```
    <dependency>
        <groupId>software.amazon.awssdk</groupId>
        <artifactId>netty-nio-client</artifactId>
    </dependency>
```

## 使用元数据客户端
<a name="examples-ec2-IMDS-use"></a>

### 实例化元数据客户端
<a name="examples-ec2-IMDS-use-create"></a>

当类路径上只有一个 `SdkHttpClient` 接口的实现时，您可以实例化同步 `Ec2MetadataClient` 的实例。为此，请调用 static `Ec2MetadataClient#create()` 方法，如以下代码段所示。

```
Ec2MetadataClient client = Ec2MetadataClient.create(); // 'Ec2MetadataAsyncClient#create' is the asynchronous version.
```

如果您的应用程序有多个 `SdkHttpClient` 或 `SdkHttpAsyncClient` 接口的实现，则必须指定一个实现以供元数据客户端使用，如[可配置 HTTP 客户端](#examples-ec2-IMDS-features-http)部分所示。

**注意**  
对于大多数服务客户端（例如 Amazon S3），适用于 Java 的 SDK 会自动添加 `SdkHttpClient` 或 `SdkHttpAsyncClient` 接口的实现。如果您的元数据客户端使用相同的实现，则 `Ec2MetadataClient#create()` 将起作用。如果您需要不同的实现，则必须在创建元数据客户端时指定它。

### 发送请求
<a name="examples-ec2-IMDS-use-req"></a>

要检索实例元数据，请实例化 `EC2MetadataClient` 类，然后使用指定[实例元数据类别](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instancedata-data-categories.html)的路径参数调用 `get` 方法。

以下示例将与 `ami-id` 键关联的值打印到控制台。

```
Ec2MetadataClient client = Ec2MetadataClient.create();
Ec2MetadataResponse response = client.get("/latest/meta-data/ami-id");
System.out.println(response.asString());
client.close(); // Closes the internal resources used by the Ec2MetadataClient class.
```

如果路径无效，则 `get` 方法将引发异常。

请对多个请求重复使用同一个客户端实例，但当不再需要该客户端时，请在该客户端上调用 `close` 来释放资源。调用 close 方法后，将无法再使用客户端实例。

### 解析响应
<a name="examples-ec2-IMDS-use-pares"></a>

EC2 实例元数据可以以不同的格式输出。纯文本和 JSON 是最常用的格式。元数据客户端提供了使用这些格式的方法。

如以下示例所示，使用 `asString` 方法以 Java 字符串的形式获取数据。您还可以使用 `asList` 方法来分隔返回多行的纯文本响应。

```
Ec2MetadataClient client = Ec2MetadataClient.create();
Ec2MetadataResponse response = client.get("/latest/meta-data/");
String fullResponse = response.asString();
List<String> splits = response.asList();
```

如果响应采用 JSON 格式，请使用 `Ec2MetadataResponse#asDocument` 方法将 JSON 响应解析为 [Document](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/document/Document.html) 实例，如以下代码段所示。

```
Document fullResponse = response.asDocument();
```

如果元数据的格式不是 JSON，则会引发异常。如果成功解析了响应，则可以使用 [document API](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/document/package-summary.html) 来更详细地检查响应。请查阅实例[元数据类别表](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instancedata-data-categories.html)，了解哪些元数据类别提供了 JSON 格式的响应。

## 配置元数据客户端
<a name="examples-ec2-IMDS-config"></a>

### 重试
<a name="examples-ec2-IMDS-config-retries"></a>

您可以为元数据客户端配置重试机制。如果这样做，则客户端可以自动重试因意外原因而失败的请求。默认情况下，客户端对失败的请求重试三次，两次尝试之间的时间呈指数回退。

如果您的用例需要不同的重试机制，则可以使用其客户端生成器上的 `retryPolicy` 方法自定义客户端。例如，以下示例将同步客户端配置为共五次重试，每两次重试之间固定延迟两秒钟。

```
BackoffStrategy fixedBackoffStrategy = FixedDelayBackoffStrategy.create(Duration.ofSeconds(2));
Ec2MetadataClient client =
    Ec2MetadataClient.builder()
                     .retryPolicy(retryPolicyBuilder -> retryPolicyBuilder.numRetries(5)
                                                                           .backoffStrategy(fixedBackoffStrategy))
                     .build();
```

有几种[BackoffStrategies](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/retry/backoff/package-summary.html)可以与元数据客户端一起使用。

您也可以完全禁用重试机制，如以下代码段所示。

```
Ec2MetadataClient client =
    Ec2MetadataClient.builder()
                    .retryPolicy(Ec2MetadataRetryPolicy.none())
                    .build();
```

使用 `Ec2MetadataRetryPolicy#none()` 会禁用默认的重试策略，因此元数据客户端不尝试重试。

### IP 版本
<a name="examples-ec2-IMDS-config-ipversion"></a>

默认情况下，元数据客户端使用的 IPV4 终端节点`http://169.254.169.254`。要将客户端更改为使用 IPV6 版本，请使用构建器的`endpointMode`或`endpoint`方法。如果在生成器上同时调用这两个方法，则会出现异常。

以下示例显示了这两个 IPV6 选项。

```
Ec2MetadataClient client =
    Ec2MetadataClient.builder()
                     .endpointMode(EndpointMode.IPV6)
                     .build();
```

```
Ec2MetadataClient client =
    Ec2MetadataClient.builder()
                     .endpoint(URI.create("http://[fd00:ec2::254]"))
                     .build();
```

## 主要 功能
<a name="examples-ec2-IMDS-features"></a>

### 异步客户端
<a name="examples-ec2-IMDS-features-async"></a>

要使用非阻塞版本的客户端，请实例化 `Ec2MetadataAsyncClient` 类的实例。以下示例中的代码使用默认设置创建异步客户端，并使用 `get` 方法检索 `ami-id` 键的值。

```
Ec2MetadataAsyncClient asyncClient = Ec2MetadataAsyncClient.create();
CompletableFuture<Ec2MetadataResponse> response = asyncClient.get("/latest/meta-data/ami-id");
```

当响应返回时，`get` 方法返回的 `java.util.concurrent.CompletableFuture` 就完成了。以下示例将 `ami-id` 元数据打印到控制台。

```
response.thenAccept(metadata -> System.out.println(metadata.asString()));
```

### 可配置 HTTP 客户端
<a name="examples-ec2-IMDS-features-http"></a>

每个元数据客户端的生成器都有一种可用于提供自定义 HTTP 客户端的 `httpClient` 方法。

以下示例显示了自定义 `UrlConnectionHttpClient` 实例的代码。

```
SdkHttpClient httpClient =
    UrlConnectionHttpClient.builder()
                           .socketTimeout(Duration.ofMinutes(5))
                           .proxyConfiguration(proxy -> proxy.endpoint(URI.create("http://proxy.example.net:8888"))))
                           .build();
Ec2MetadataClient metaDataClient =
    Ec2MetadataClient.builder()
                     .httpClient(httpClient)
                     .build();
// Use the metaDataClient instance.
metaDataClient.close();   // Close the instance when no longer needed.
```

以下示例显示了带有异步元数据客户端的自定义 `NettyNioAsyncHttpClient` 实例的代码。

```
SdkAsyncHttpClient httpAsyncClient = 
    NettyNioAsyncHttpClient.builder()
                           .connectionTimeout(Duration.ofMinutes(5))
                           .maxConcurrency(100)
                           .build();
Ec2MetadataAsyncClient asyncMetaDataClient =
    Ec2MetadataAsyncClient.builder()
                          .httpClient(httpAsyncClient)
                          .build();
// Use the asyncMetaDataClient instance.
asyncMetaDataClient.close();   // Close the instance when no longer needed.
```

本指南中的 [在中配置 HTTP 客户端 AWS SDK for Java 2.x](http-configuration.md) 主题详细介绍了如何配置适用于 Java 的 SDK 中可用的 HTTP 客户端。

### 令牌缓存
<a name="examples-ec2-IMDS-features-token"></a>

由于客户端使用元数据 IMDSv2，因此所有请求都与会话关联。会话由带过期时间的令牌定义，元数据客户端会为您管理该令牌。每个元数据请求都会自动重复使用令牌，直到令牌过期。

默认情况下，令牌持续六小时（21600 秒）。除非您的特定用例需要高级配置，否则我们建议您保留默认 time-to-live值。

如果需要，可使用 `tokenTtl` 生成器方法配置持续时间。例如，以下代码段中的代码创建了一个会话持续时间为五分钟的客户端。

```
Ec2MetadataClient client =
    Ec2MetadataClient.builder()
                     .tokenTtl(Duration.ofMinutes(5))
                     .build();
```

如果您省略调用生成器上的 `tokenTtl` 方法，则改用默认持续时间 21,600。