

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

# 配置基于 Netty 的 HTTP 客户端
<a name="http-configuration-netty"></a>

中用于异步操作的默认 HTTP 客户端 AWS SDK for Java 2.x 是基于 Netty 的。[NettyNioAsyncHttpClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/http/nio/netty/NettyNioAsyncHttpClient.html)基于 Netty 的客户端以 [Netty 项目](https://netty.io/)的异步事件驱动网络框架为基础。

作为备选 HTTP 客户端，您可以使用新的[基于AWS CRT 的 HTTP 客户端](http-configuration-crt.md)。本主题演示如何配置 `NettyNioAsyncHttpClient`。

## 访问 `NettyNioAsyncHttpClient`
<a name="http-config-netty-access"></a>

在大多数情况下，您无需在异步程序中进行任何显式配置即可使用 `NettyNioAsyncHttpClient`。您只需声明您的异步客户端，SDK 将使用标准值为您配置 `NettyNioAsyncHttpClient`。

如果要显式配置 `NettyNioAsyncHttpClient` 或将其用于多个服务客户端，则需要将其设置为可供配置。

### 无需配置
<a name="http-config-netty-no-config"></a>

当您在 Maven 中声明对服务客户端的依赖项时，SDK 会添加对 `netty-nio-client` 构件的*运行时系统*依赖项。这使得 `NettyNioAsyncHttpClient` 类在运行时可供您的代码使用，但在编译时不可用。如果您没有配置基于 Netty 的 HTTP 客户端，则无需为其指定依赖项。

在以下 Maven `pom.xml` 文件的 XML 片段中，使用 `<artifactId>dynamodb-enhanced</artifactId>` 声明的依赖项会以传递的方式引入基于 Netty 的 HTTP 客户端。您无需专门为其声明依赖项。

```
<dependencyManagement>
   <dependencies>
        <dependency>
            <groupId>software.amazon.awssdk</groupId>
            <artifactId>bom</artifactId>
            <version>2.27.21</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
<dependencies>
    <dependency>
        <groupId>software.amazon.awssdk</groupId>
        <artifactId>dynamodb-enhanced</artifactId>
    </dependency>
</dependencies>
```

有了这些依赖项，您无法进行任何 HTTP 配置更改，因为 `NettyNioAsyncHttpClient` 库仅位于运行时系统类路径上。

### 需要配置
<a name="http-config-netty-yes-config"></a>

要配置 `NettyNioAsyncHttpClient`，您需要在*编译* 时添加对 `netty-nio-client` 构件的依赖项。

请参阅以下 Maven `pom.xml` 文件示例来配置 `NettyNioAsyncHttpClient`。

```
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>software.amazon.awssdk</groupId>
                <artifactId>bom</artifactId>
                <version>2.27.21</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>software.amazon.awssdk</groupId>
            <artifactId>dynamodb-enhanced</artifactId>
        </dependency>
        <!-- By adding the netty-nio-client dependency, NettyNioAsyncHttpClient will be 
             added to the compile classpath so you can configure it. -->
        <dependency>
            <groupId>software.amazon.awssdk</groupId>
            <artifactId>netty-nio-client</artifactId>
        </dependency>
    </dependencies>
```

## 使用和配置 `NettyNioAsyncHttpClient`
<a name="http-netty-config"></a>

您可以在生成服务客户端的同时配置一个 `NettyNioAsyncHttpClient` 实例，也可以将单个实例配置为在多个服务客户端之间共享。

无论采用哪种方法，您都可以使用 [NettyNioAsyncHttpClient.Builder](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/http/nio/netty/NettyNioAsyncHttpClient.Builder.html) 来配置基于 Netty 的 HTTP 客户端实例的属性。

### 最佳实践：将一个 `NettyNioAsyncHttpClient` 实例专用于一个服务客户端
<a name="http-config-netty-one-client"></a>

如果您需要配置 `NettyNioAsyncHttpClient` 实例，建议您生成专用 `NettyNioAsyncHttpClient` 实例。您可以通过使用服务客户端生成器的 `httpClientBuilder` 方法来执行此操作。这样，HTTP 客户端的生命周期就由 SDK 管理，这有助于避免在不再需要 `NettyNioAsyncHttpClient` 实例却不关闭实例时可能发生的内存泄漏。

以下示例创建了一个 `DynamoDbAsyncClient` 实例，该实例供 `DynamoDbEnhancedAsyncClient` 实例使用。该 `DynamoDbAsyncClient` 实例包含具有 `connectionTimeout` 和 `maxConcurrency` 值的 `NettyNioAsyncHttpClient` 实例。HTTP 实例是使用 `DynamoDbAsyncClient.Builder` 的 `httpClientBuilder` 方法创建的。

 **导入** 

```
import software.amazon.awssdk.auth.credentials.EnvironmentVariableCredentialsProvider;
import software.amazon.awssdk.awscore.defaultsmode.DefaultsMode;
import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedAsyncClient;
import software.amazon.awssdk.enhanced.dynamodb.extensions.AutoGeneratedTimestampRecordExtension;
import software.amazon.awssdk.http.nio.netty.NettyNioAsyncHttpClient;
import software.amazon.awssdk.services.dynamodb.DynamoDbAsyncClient;
import java.time.Duration;
```

 **代码** 

```
// DynamoDbAsyncClient is the lower-level client used by the enhanced client.
DynamoDbAsyncClient dynamoDbAsyncClient = 
    DynamoDbAsyncClient
        .builder()
            .httpClientBuilder(NettyNioAsyncHttpClient.builder()
            .connectionTimeout(Duration.ofMillis(5_000))
            .maxConcurrency(100)
            .tlsNegotiationTimeout(Duration.ofMillis(3_500)))
        .defaultsMode(DefaultsMode.IN_REGION)
        .credentialsProvider(EnvironmentVariableCredentialsProvider.create())
        .build();

// Singleton: Use dynamoDbAsyncClient and enhancedClient for all requests.
DynamoDbEnhancedAsyncClient enhancedClient = 
    DynamoDbEnhancedAsyncClient
        .builder()
        .dynamoDbClient(dynamoDbAsyncClient)
        .extensions(AutoGeneratedTimestampRecordExtension.create())
        .build();

// Perform work with the dynamoDbAsyncClient and enhancedClient.

// Requests completed: Close dynamoDbAsyncClient.
dynamoDbAsyncClient.close();
```

### 替代方法：共享 `NettyNioAsyncHttpClient` 实例
<a name="http-config-netty-multi-clients"></a>

为了帮助降低应用程序的资源和内存使用量，您可以配置 `NettyNioAsyncHttpClient` 并在多个服务客户端之间共享该客户端。将共享 HTTP 连接池，从而降低资源使用量。

**注意**  
共享 `NettyNioAsyncHttpClient` 实例时，必须在准备好弃置实例时将其关闭。服务客户端关闭后，SDK 不会关闭实例。

以下示例配置了一个基于 Netty 的 HTTP 客户端，该客户端由两个服务客户端使用。配置的 `NettyNioAsyncHttpClient` 实例将传递给每个生成器的 `httpClient` 方法。当不再需要服务客户端和 HTTP 客户端时，代码会显式关闭它们。代码最后关闭 HTTP 客户端。

**导入**

```
import software.amazon.awssdk.http.SdkHttpClient;
import software.amazon.awssdk.http.apache.ApacheHttpClient;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.s3.S3Client;
```

 **代码** 

```
// Create a NettyNioAsyncHttpClient shared instance.
SdkAsyncHttpClient nettyHttpClient = NettyNioAsyncHttpClient.builder().maxConcurrency(100).build();

// Singletons: Use the s3AsyncClient, dbAsyncClient, and enhancedAsyncClient for all requests.
S3AsyncClient s3AsyncClient = 
    S3AsyncClient.builder()
                 .httpClient(nettyHttpClient)
                 .build();

DynamoDbAsyncClient dbAsyncClient = 
    DynamoDbAsyncClient.builder()
                       .httpClient(nettyHttpClient)
                       .defaultsMode(DefaultsMode.IN_REGION)
                       .credentialsProvider(EnvironmentVariableCredentialsProvider.create())
                       .build();

DynamoDbEnhancedAsyncClient enhancedAsyncClient = 
    DynamoDbEnhancedAsyncClient.builder()
                               .dynamoDbClient(dbAsyncClient)
                               .extensions(AutoGeneratedTimestampRecordExtension.create())
                               .build();

// Perform work with s3AsyncClient, dbAsyncClient, and enhancedAsyncClient.

// Requests completed: Close all service clients.
s3AsyncClient.close();
dbAsyncClient.close()
nettyHttpClient.close();  // Explicitly close nettyHttpClient.
```

## 配置 ALPN 协议协商
<a name="http-netty-config-alpn"></a>

ALPN（应用层协议协商）是一个 TLS 扩展，该扩展让应用层可以协商在建立安全连接时应执行哪个协议，从而避免额外的网络往返并提供更好的性能。

要使基于 Netty 的 HTTP 客户端能够使用 ALPN，请调用生成器方法，如以下代码段所示：

```
import software.amazon.awssdk.http.Protocol;
import software.amazon.awssdk.http.ProtocolNegotiation;
import software.amazon.awssdk.http.async.SdkAsyncHttpClient;
import software.amazon.awssdk.http.nio.netty.NettyNioAsyncHttpClient;
import software.amazon.awssdk.services.transcribestreaming.TranscribeStreamingAsyncClient;


// Configure the Netty-based HTTP client to use the ALPN protocol.
SdkAsyncHttpClient nettyClient = NettyNioAsyncHttpClient.builder()
                                                        .protocol(Protocol.HTTP2)
                                                        .protocolNegotiation(ProtocolNegotiation.ALPN)
                                                        .build();
// Use the Netty-based HTTP client with a service client.
TranscribeStreamingAsyncClient transcribeClient = TranscribeStreamingAsyncClient.builder()
                                                                                .httpClient(nettyClient)
                                                                                .build();
```

如前面的代码段所示，ALPN 协议协商目前仅适用于 HTTP/2 协议。

## 代理配置示例
<a name="http-config-netty-proxy-ex"></a>

以下代码段使用了[适用于 Netty HTTP 客户端的代理配置生成器](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/http/nio/netty/ProxyConfiguration.Builder.html)。

```
SdkAsyncHttpClient nettyHttpClient = NettyNioAsyncHttpClient.builder()
    .proxyConfiguration(ProxyConfiguration.builder()
        .scheme("https")
        .host("myproxy")
        .port(1234)
        .username("username")
        .password("password")
        .nonProxyHosts(Set.of("localhost", "host.example.com"))
        .build())
    .build();
```

以下命令行片段显示了代理配置的等效 Java 系统属性。

```
$ java -Dhttps.proxyHost=myproxy -Dhttps.proxyPort=1234 -Dhttps.proxyUser=username \
-Dhttps.proxyPassword=password -Dhttp.nonProxyHosts=localhost|host.example.com -cp ... App
```

**重要**  
要使用任何 HTTPS 代理系统属性，必须在代码中将 `scheme` 属性设置为 `https`。如果未在代码中设置 scheme 属性，则架构默认为 HTTP，SDK 仅查找 `http.*` 系统属性。

使用环境变量的等效设置为：

```
// Set the following environment variables.
// $ export HTTPS_PROXY="https://username:password@myproxy:1234"
// $ export NO_PROXY="localhost|host.example.com"

// Set the 'useSystemPropertyValues' to false on the proxy configuration.
SdkAsyncHttpClient nettyHttpClient = NettyNioAsyncHttpClient.builder()
    .proxyConfiguration(ProxyConfiguration.builder()
        .useSystemPropertyValues(Boolean.FALSE)
        .build())
    .build();

// Run the application.
// $ java -cp ... App
```