使用 Amazon EC2 实例元数据 - Amazon SDK for Java 2.x
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

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

使用 Amazon EC2 实例元数据

适用于 Amazon EC2 实例元数据服务的 Java SDK 客户端(元数据客户端)允许您的应用程序访问其本地 EC2 实例上的元数据。元数据客户端使用 IMDSv2(实例元数据服务 v2)的本地实例,并使用面向会话的请求。

SDK 中有两个客户端类可用。同步 Ec2MetadataClient 用于阻塞操作,Ec2MetadataAsyncClient 用于异步、非阻塞用例。

开始使用

要使用元数据客户端,请将 imds Maven 构件添加到您的项目中。您还需要在类路径上具有 SdkHttpClient 的类,或对于异步变体而言,具有 SdkAsyncHttpClient 的类。

以下 Maven XML 显示了使用同步 UrlConnectionHttpClient 的依赖项片段以及元数据客户端的依赖项。

<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 存储库中搜索 bom 构件的最新版本。

要使用异步 HTTP 客户端,请替换 url-connection-client 构件的依赖项片段。例如,以下片段引入了 NettyNioAsyncHttpClient 实现。

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

使用元数据客户端

实例化元数据客户端

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

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

如果您的应用程序有多个 SdkHttpClientSdkHttpAsyncClient 接口的实现,则必须指定一个实现以供元数据客户端使用,如可配置 HTTP 客户端部分所示。

注意

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

发送请求

要检索实例元数据,请实例化 EC2MetadataClient 类,然后使用指定实例元数据类别的路径参数调用 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 方法后,将无法再使用客户端实例。

解析响应

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 实例,如以下代码段所示。

Document fullResponse = response.asDocument();

如果元数据的格式不是 JSON,则会引发异常。如果成功解析了响应,则可以使用 document API 来更详细地检查响应。请查阅实例元数据类别表,了解哪些元数据类别提供了 JSON 格式的响应。

配置元数据客户端

重试

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

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

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

您可以将多种 BackoffStrategies 与元数据客户端结合使用。

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

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

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

IP 版本

默认情况下,元数据客户端使用位于 http://169.254.169.254 的 IPV4端点。要将客户端更改为使用 IPV6 版本,请使用生成器的 endpointModeendpoint 方法。如果在生成器上同时调用这两个方法,则会出现异常。

以下示例演示两个 IPV6 选项。

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

主要特征

异步客户端

要使用非阻塞版本的客户端,请实例化 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 客户端

每个元数据客户端的生成器都有一种可用于提供自定义 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 客户端 主题详细介绍了如何配置适用于 Java 的 SDK 中可用的 HTTP 客户端。

令牌缓存

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

默认情况下,令牌持续六小时(21600 秒)。除非您的特定用例需要高级配置,否则我们建议您保留默认的生存时间值。

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

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

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