

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

# 配置 适用于 Kotlin 的 AWS SDK
配置

本节介绍如何使用配置服务客户端 适用于 Kotlin 的 AWS SDK。有关更多信息，请参阅 [SDK 和工具参考指南](https://docs.aws.amazon.com/sdkref/latest/guide/overview.html)，其中包含适用于所有内容的配置概述 AWS SDKs。

**Contents**
+ [

# 创建服务客户端
](creating-clients.md)
  + [

## 在代码中配置客户端
](creating-clients.md#programmatic-config)
  + [

## 从环境中配置客户端
](creating-clients.md#loading-from-the-environment)
  + [

## 关闭客户端
](creating-clients.md#closing-the-client)
+ [

# AWS 区域 选择
](region-selection.md)
  + [

## 默认区域提供商链
](region-selection.md#default-region-provider-chain)
+ [

# 凭证提供程序
](credential-providers.md)
  + [

## 默认凭证提供者链
](credential-providers.md#default-credential-provider-chain)
    + [

### 了解默认凭证提供商链
](credential-providers.md#default-credentials-retrieval-order)
  + [

## 指定凭证提供商
](credential-providers.md#explicit-credential-provider)
    + [

### 使用独立提供商缓存凭证
](credential-providers.md#credentials-caching)
+ [

# 配置客户端终端节点
](config-endpoint.md)
  + [

## 自定义配置
](config-endpoint.md#config-endpoint-custom-config)
    + [

### Set `endpointUrl`
](config-endpoint.md#config-endpoint-custom-config-endpointurl)
    + [

### Set `endpointProvider`
](config-endpoint.md#config-endpoint-custom-config-endpointprovider)
      + [

#### `EndpointProvider` 属性
](config-endpoint.md#config-endpoint-custom-config-endpointprovider-params)
    + [

### `endpointUrl` 或 `endpointProvider`
](config-endpoint.md#config-endpoint-custom-config-which)
    + [

### 关于 Amazon S3 的说明
](config-endpoint.md#config-endpoint-custom-config-s3)
  + [

## 示例
](config-endpoint.md#config-endpoint-examples)
    + [

### `endpointUrl` 示例
](config-endpoint.md#config-endpoint-examples-endpointurl)
    + [

### `endpointProvider` 示例
](config-endpoint.md#config-endpoint-examples-endpointprovider)
    + [

### `endpointUrl` 和 `endpointProvider`
](config-endpoint.md#config-endpoint-examples-both)
+ [

# HTTP
](http.md)
  + [

# HTTP 客户端配置
](http-client-config.md)
    + [

## 基本配置
](http-client-config.md#basic-http-confg)
      + [

### 导入
](http-client-config.md#basic-config-ex-imports)
      + [

### 代码
](http-client-config.md#basic-config-ex-code)
    + [

## 高级配置
](http-client-config.md#advanced-http-config)
      + [

### 指定 HTTP 引擎类型
](http-client-config.md#http-config-engine)
        + [

#### 导入
](http-client-config.md#http-config-specify-engine-imports)
        + [

#### 代码
](http-client-config.md#http-config-specify-engine-code)
        + [

#### 使用 `OkHttp4Engine`
](http-client-config.md#http-config-okhttp4engine)
        + [

#### 使用显式的 HTTP 客户端
](http-client-config.md#http-client-explicit-usage)
          + [

##### 导入
](http-client-config.md#http-client-explicit-usage-ex-imports)
          + [

##### 代码
](http-client-config.md#http-client-explicit-usage-ex-code)
      + [

### 空闲连接监控
](http-client-config.md#http-idle-connection-monitoring)
        + [

#### 导入
](http-client-config.md#http-idle-connection-ex-imports)
        + [

#### 代码
](http-client-config.md#http-idle-connection-ex-code)
  + [

# 使用 HTTP 代理
](using-http-proxy.md)
    + [

## 使用 JVM 系统属性
](using-http-proxy.md#http-proxy-jvm-properties)
    + [

## 使用环境变量
](using-http-proxy.md#http-proxy-environment-variables)
    + [

## 在 EC2 实例上使用代理
](using-http-proxy.md#http-proxy-ec2)
  + [

# HTTP 拦截器
](interceptors.md)
    + [

## 拦截器注册
](interceptors.md#interceptor-registration)
      + [

### 用于所有服务客户端操作的拦截器
](interceptors.md#interceptor-all-ops)
      + [

### 拦截器仅用于特定操作
](interceptors.md#interceptor-specific-ops)
  + [

# 强制使用最低版本的 TLS
](configure-http-tls.md)
    + [

## 配置 HTTP 引擎
](configure-http-tls.md#configure-http-tls-engine)
    + [

## 设置 `sdk.minTls` JVM 系统属性
](configure-http-tls.md#configure-http-tls-sysprop)
    + [

## 设置`SDK_MIN_TLS`环境变量
](configure-http-tls.md#configure-http-tls-envvar)
+ [

# 在中重试 适用于 Kotlin 的 AWS SDK
](retries.md)
  + [

## 了解重试行为
](retries.md#retries-understanding)
    + [

### 默认重试配置
](retries.md#retries-default)
    + [

### 哪些异常是可以重试的？
](retries.md#retries-default-policy-details)
      + [

#### 可通过错误代码重试
](retries.md#retries-retryable-by-error-code)
      + [

#### 可通过 HTTP 状态码重试
](retries.md#retries-retryable-by-status-code)
      + [

#### 可按错误类型重试
](retries.md#retries-retryable-by-error-type)
      + [

#### 可通过 SDK 元数据重试
](retries.md#retries-retryable-by-metadata)
    + [

### 检查异常是否可以重试
](retries.md#retries-check-exception-retryable)
    + [

### 当重试失败时，你的代码会出现哪些异常
](retries.md#retries-exception-types-during-retries)
  + [

## 自定义重试行为
](retries.md#retries-customizing)
    + [

### 配置最大尝试次数
](retries.md#retires-max-attempts)
    + [

### 配置延迟和退缩
](retries.md#retries-delays-backoff)
    + [

### 配置重试令牌存储桶
](retries.md#retries-token-bucket)
    + [

### 配置自适应重试
](retries.md#retries-adaptive-retries)
+ [

# 可观测性
](observability.md)
  + [

## 配置 `TelemetryProvider`
](observability.md#observability-conf-telemetry-provider)
    + [

### 配置默认的全局遥测提供程序
](observability.md#observability-conf-telemetry-provider-global)
    + [

### 为特定服务客户端配置遥测提供程序
](observability.md#observability-conf-telemetry-provider-client)
  + [

# 指标
](observability-telemetry-metrics.md)
  + [

# 日志记录
](logging.md)
    + [

## 为线级消息指定日志模式
](logging.md#sdk-log-mode)
      + [

### 在代码中设置日志模式
](logging.md#set-log-mode-programmatically)
      + [

### 从环境中设置日志模式
](logging.md#set-log-mode-from-enviironment)
  + [

# 遥测提供程序
](observability-telemetry-providers.md)
    + [

# 配置 OpenTelemetry基于遥测的提供商
](observability-telemetry-providers-otel.md)
      + [

## 先决条件
](observability-telemetry-providers-otel.md#observability-telemetry-providers-otel-prereqs)
      + [

## 配置 SDK
](observability-telemetry-providers-otel.md#observability-telemetry-providers-otel-conf)
      + [

## 资源
](observability-telemetry-providers-otel.md#observability-telemetry-providers-otel-res)
+ [

# 覆盖服务客户端配置
](override-client-config.md)
  + [

## 被覆盖的客户端的生命周期
](override-client-config.md#override-client-lifecycle)
  + [

## 客户之间共享的资源
](override-client-config.md#override-client-shared-res)

# 创建服务客户端


要向发出请求 AWS 服务，必须先为该服务实例化客户端。

您可以为服务客户端配置常用设置，例如要使用的 HTTP 客户端、日志级别和重试配置。此外，每个服务客户端都需要一个 AWS 区域 和一个凭据提供程序。SDK 使用这些值向正确的区域发送请求，并使用正确的凭据对请求进行签名。

您可以在代码中以编程方式指定这些值，也可以让它们从环境变量中自动加载。

## 在代码中配置客户端


要使用特定值配置服务客户端，可以在传递给服务客户端工厂方法的 lambda 函数中指定这些值，如以下代码段所示。

```
val dynamoDbClient = DynamoDbClient {
    region = "us-east-1"
    credentialsProvider = ProfileCredentialsProvider(profileName = "myprofile")
}
```

您未在配置块中指定的任何值都将设置为默认值。例如，如果您没有像前面的代码那样指定凭证提供程序，则凭证提供程序将默认为[默认的凭证提供程序链](credential-providers.md#default-credential-provider-chain)。

**警告**  
某些属性（例如）`region`没有默认值。使用编程配置时，必须在配置块中明确指定它们。如果 SDK 无法解析该属性，API 请求可能会失败。

## 从环境中配置客户端


创建服务客户端时，SDK 可以检查当前执行环境中的位置以确定某些配置属性。这些位置包括[共享配置和凭据文件](https://docs.aws.amazon.com/sdkref/latest/guide/file-format.html)、[环境变量](https://docs.aws.amazon.com/sdkref/latest/guide/environment-variables.html)以及 [JVM 系统属性](https://docs.aws.amazon.com/sdkref/latest/guide/jvm-system-properties.html)。可供解析的属性包括[AWS 区域](region-selection.md)、[重试策略](retries.md)、[日志模式](logging.md#sdk-log-mode)等。有关 SDK 可以从执行环境中解析的所有设置的更多信息，请参阅[AWS SDKs 和工具设置参考指南](https://docs.aws.amazon.com/sdkref/latest/guide/settings-reference.html)。

要创建具有环境源配置的客户端，请在服务客户端界`suspend fun fromEnvironment()`面上使用静态方法：

```
val dynamoDbClient = DynamoDbClient.fromEnvironment()
```

在 Amazon EC2 上运行时 AWS Lambda，或者在任何其他可从环境中配置服务客户端的环境中运行时，以这种方式创建客户端非常有用。这样可以将您的代码与其运行的环境分离，从而无需更改代码即可更轻松地将应用程序部署到多个区域。

此外，您可以通过将 lambda 块传递给来覆盖特定属性。`fromEnvironment`以下示例从环境（例如 Region）加载一些配置属性，但特别重写了证书提供者以使用配置文件中的证书。

```
val dynamoDbClient = DynamoDbClient.fromEnvironment { 
    credentialsProvider = ProfileCredentialsProvider(profileName = "myprofile")
}
```

对于任何无法通过编程设置或环境确定的配置属性，SDK 都使用默认值。例如，如果您没有在代码或环境设置中指定凭证提供程序，则凭证提供程序默认为[默认的凭证提供程序链](credential-providers.md#default-credential-provider-chain)。

**警告**  
某些属性（例如 “区域”）没有默认值。您必须在环境设置中或在配置块中明确指定它们。如果 SDK 无法解析该属性，API 请求可能会失败。

**注意**  
尽管可以在执行环境中找到与凭证相关的属性（例如临时访问密钥和 SSO 配置），但在创建时这些值并不是由客户端获取的。相反，凭证提供程序层会在每次请求时访问这些值。

## 关闭客户端


当您不再需要服务客户端时，请将其关闭以释放它正在使用的任何资源：

```
val dynamoDbClient = DynamoDbClient.fromEnvironment()
// Invoke several DynamoDB operations.
dynamoDbClient.close()
```

由于服务客户端会扩展[https://docs.aws.amazon.com/smithy-kotlin/api/latest/runtime-core/aws.smithy.kotlin.runtime.io/-closeable/index.html](https://docs.aws.amazon.com/smithy-kotlin/api/latest/runtime-core/aws.smithy.kotlin.runtime.io/-closeable/index.html)接口，因此您可以使用[https://docs.aws.amazon.com/smithy-kotlin/api/latest/runtime-core/aws.smithy.kotlin.runtime.io/use.html](https://docs.aws.amazon.com/smithy-kotlin/api/latest/runtime-core/aws.smithy.kotlin.runtime.io/use.html)扩展程序在区块结束时自动关闭客户端，如以下代码段所示。

```
DynamoDbClient.fromEnvironment().use { dynamoDbClient ->
    // Invoke several DynamoDB operations.
}
```

在前面的示例中，lambda 块接收对刚刚创建的客户端的引用。您可以对此客户端引用调用操作，当区块完成时（包括抛出异常），客户端就会关闭。

# AWS 区域 选择
AWS 区域 选择

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

## 默认区域提供商链


[从环境](creating-clients.md#loading-from-the-environment)中加载服务客户端的配置时，将使用以下查找过程：

1. 在生成器上设置的任何显式区域。

1. 已检查 `aws.region` JVM 系统属性。如果已设置，则在客户端的配置中使用该区域。

1. 系统会检查 `AWS_REGION` 环境变量。如果已设置，则在客户端的配置中使用该区域。

   1. **注意**：此环境变量由 Lambda 容器设置。

1. SDK 会检查 AWS 共享的配置文件。如果为活动配置文件设置了该`region`属性，则 SDK 将使用该属性。

   1. `AWS_CONFIG_FILE` 环境变量可用于自定义共享配置文件的位置。

   1. `aws.profile`JVM 系统属性或`AWS_PROFILE`环境变量可用于自定义 SDK 加载的配置文件。

1. 软件开发工具包尝试使用 Amazon EC2 实例元数据服务来确定当前运行的 EC2 实例的区域。

1. 如果此时仍未解析该区域，则客户端创建会失败，但会出现异常。

# 凭证提供程序
凭证提供程序

****  
**默认凭证提供程序链解析在 1.4.0 版本中更改的凭据的顺序有关详细信息，请参阅以下注释。**

当您使用向 Amazon Web Services 发送请求时 适用于 Kotlin 的 AWS SDK，必须使用颁发的凭证对请求进行 AWS加密签名。Kotlin 软件开发工具包会自动为您签署请求。要获取证书，软件开发工具包可以使用位于多个位置的配置设置，例如 JVM 系统属性、环境变量、共享 AWS `config`和`credentials`文件以及 Amazon EC2 实例元数据。

SDK 使用*凭证提供程序*抽象来简化从各种来源检索凭证的过程。SDK 包含[多个凭据提供程序实现](https://docs.aws.amazon.com/sdk-for-kotlin/api/latest/aws-config/aws.sdk.kotlin.runtime.auth.credentials/index.html)。

例如，如果检索到的配置包括共享`config`文件中的 IAM Identity Center 单点登录访问权限设置，则软件开发工具包将与 IAM Identity Center 合作检索用于向其发出请求的临时证书。 AWS 服务通过这种获取证书的方法，软件开发工具包使用 IAM 身份中心提供商（也称为 SSO 凭证提供商）。本指南的[设置部分](setup-basic-onetime-setup.md#setup-sso-access)描述了此配置。

要使用特定的凭据提供程序，可以在创建服务客户端时指定一个。或者，您可以使用默认凭证提供程序链自动搜索配置设置。

## 默认凭证提供者链
默认凭证提供程序链

如果在客户端构造时没有明确指定，Kotlin 的 SDK 会使用凭证提供程序，该提供程序会按顺序检查每个可以提供凭据的地方。此默认凭证提供程序是作为证书提供者链实现的。

要使用默认链在应用程序中提供凭证，请在不显式提供`credentialsProvider`属性的情况下创建服务客户端。

```
val ddb = DynamoDbClient {
    region = "us-east-2"
}
```

有关创建服务客户端的更多信息，请参阅[构造和配置客户端](creating-clients.md)。

### 了解默认凭证提供商链


默认凭证提供程序链使用以下预定义顺序搜索凭证配置。当配置的设置提供有效的凭据时，链就会停止。

**1。 [AWS 访问密钥（JVM 系统属性）](https://docs.aws.amazon.com/sdkref/latest/guide/feature-static-credentials.html)**  
SDK 会查找`aws.accessKeyId``aws.secretAccessKey`、和 `aws.sessionToken` JVM 系统属性。

**2。 [AWS 访问密钥（环境变量）](https://docs.aws.amazon.com/sdkref/latest/guide/feature-static-credentials.html)**  
SDK 尝试从 `AWS_ACCESS_KEY_ID` 和 `AWS_SECRET_ACCESS_KEY` 以及 `AWS_SESSION_TOKEN` 环境变量加载凭证。

**3. [网络身份令牌](https://docs.aws.amazon.com/sdkref/latest/guide/access-assume-role-web.html)**  
SDK 会查找环境变量`AWS_WEB_IDENTITY_TOKEN_FILE`和`AWS_ROLE_ARN`（或 JVM 系统属性`aws.webIdentityTokenFile`和`aws.roleArn`）。根据令牌信息和角色，SDK 获取临时证书。

**4. [配置文件中的配置文件](https://docs.aws.amazon.com/sdkref/latest/guide/file-format.html)**  
在此步骤中，SDK 使用与配置文件关联的设置。默认情况下，SDK 使用共享 AWS `config`和`credentials`文件，但如果设置了`AWS_CONFIG_FILE`环境变量，SDK 将使用该值。如果*未*设置`AWS_PROFILE`环境变量（或 `aws.profile` JVM 系统属性），SDK 将查找 “默认” 配置文件，否则会查找与`AWS_PROFILE’s`值匹配的配置文件。  
SDK 根据上一段所述的配置查找配置文件，并使用此处定义的设置。如果 SDK 找到的设置包含适用于不同凭证提供者方法的混合设置，则 SDK 将按以下顺序排列：  

1. [AWS 访问密钥（配置文件）](https://docs.aws.amazon.com/sdkref/latest/guide/feature-static-credentials.html)-SDK 使用`aws_access_key_id``aws_access_key_id`、和的设置`aws_session_token`。

1. [假设角色配置](https://docs.aws.amazon.com/sdkref/latest/guide/access-assume-role.html)-如果 SDK 找到`role_arn`和 `source_profile` /或`credential_source`设置，则会尝试代入角色。如果 SDK 找到了该`source_profile`设置，它会从另一个配置文件获取凭证，以接收指定角色的临时证书`role_arn`。如果软件开发工具包找到了该`credential_source`设置，则它会根据设置的值从 Amazon ECS 容器、Amazon EC2 实例或环境变量中`credential_source`获取证书。然后，它使用这些证书为该角色获取临时证书。

   配置文件应包含`source_profile`设置或`credential_source`设置，但不能同时包含两者。

1. [Web 身份令牌配置](https://docs.aws.amazon.com/sdkref/latest/guide/access-assume-role-web.html)-如果 SDK 找到`role_arn`并进行了`web_identity_token_file`设置，则它会根据`role_arn`和令牌获取访问 AWS 资源的临时证书。

1. [SSO 令牌配置](https://docs.aws.amazon.com/sdkref/latest/guide/feature-sso-credentials.html)-如果软件开发工具包找到`sso_session`、`sso_account_id`、`sso_role_name`设置（以及配置文件中的配套`sso-session`部分），则软件开发工具包将从 IAM Identity Center 服务中检索临时证书。

1. [旧版 SSO 配置](https://docs.aws.amazon.com/sdkref/latest/guide/feature-sso-credentials.html#sso-legacy)-如果软件开发工具包找到` sso_start_url`、`sso_region``sso_account_id`、和`sso_role_name`设置，则软件开发工具包会从 IAM Identity Center 服务中检索临时证书。

1. [登录配置](https://docs.aws.amazon.com/sdkref/latest/guide/feature-sso-credentials.html#sso-legacy)-如果 SDK 找到`login_session`设置，它将使用登录会话中的临时证书，或者如果这些证书在 5 分钟内过期，则尝试刷新它们。要了解如何启动登录会话，请参阅 [AWS CLI 用户指南](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-sign-in.html)。

1. [流程配置](https://docs.aws.amazon.com/sdkref/latest/guide/feature-process-credentials.html)-如果 SDK 找到`credential_process`设置，它将使用路径值来调用流程并获取临时证书。

**5. [容器凭证](https://docs.aws.amazon.com/sdkref/latest/guide/feature-container-credentials.html)**  
SDK 会查找环境变量`AWS_CONTAINER_CREDENTIALS_RELATIVE_URI`或`AWS_CONTAINER_CREDENTIALS_FULL_URI`和`AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE`或`AWS_CONTAINER_AUTHORIZATION_TOKEN`。它使用这些值通过 GET 请求从指定的 HTTP 端点加载证书。

**6. [IMDS 凭证](https://docs.aws.amazon.com/sdkref/latest/guide/feature-imds-credentials.html)**  
SDK 尝试使用默认或配置的 HTTP 端点从[实例元数据服务](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html)获取凭证。SDK 仅支持[IMDSv2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html)。

如果此时仍未解析凭证，则客户端创建会失败，但会出现异常。

**注意：更改凭据解析顺序**  
上面描述的凭证解析顺序适用于适用于 Kotlin 的 SDK 的`1.4.x+`发布。在`1.4.0`发布之前，3号和4号的物品被切换，当前的4a物品紧随当前的4g物品。

## 指定凭证提供商


您可以指定凭证提供商，而不是使用默认的提供者链。通过这种方法，您可以直接控制 SDK 使用哪些凭据。

例如，要使用代入的 IAM 角色的证书，请在创建客户端`StsAssumeRoleCredentialsProvider`时指定：

```
val ddb = DynamoDbClient {
    region = "us-east-1"
    credentialsProvider = StsAssumeRoleCredentialsProvider()
}
```

您也可以创建一个自定义链 (`CredentialsProviderChain`)，该链按您的首选顺序组合多个提供商。

### 使用独立提供商缓存凭证


**重要**  
默认链会自动缓存凭证。独立提供商不缓存凭证。为避免在每次 API 调用时获取凭证，请将您的提供程序包起来。`CachedCredentialsProvider`仅当当前凭证过期时，缓存的提供者才会获取新凭证。

要使用独立提供程序缓存凭证，请使用以下`CachedCredentialsProvider`类：

```
val ddb = DynamoDbClient {
     region = "us-east-1"
     credentialsProvider = CachedCredentialsProvider(StsAssumeRoleCredentialsProvider())
 }
```

 或者，使用`cached()`扩展函数获取更简洁的代码：

```
val ddb = DynamoDbClient {
      region = "us-east-1"
      credentialsProvider = StsAssumeRoleCredentialsProvider().cached()
 }
```

# 配置客户端终端节点
客户端端点

当 适用于 Kotlin 的 AWS SDK 调用 a 时 AWS 服务，其第一步之一就是确定将请求路由到何处。此过程称为端点解析。

在构建服务客户端时，可以为 SDK 配置端点解析。端点解析的默认配置通常没问题，但是有几个原因可能会导致您修改默认配置。两个示例原因如下所示：
+ 向服务的预发行版本或服务的本地部署提出请求。
+ 访问尚未在 SDK 中建模的特定服务功能。

**警告**  
端点解析是一个高级 SDK 主题。如果您更改默认设置，则可能会破坏代码。默认设置应适用于生产环境中的大多数用户。

## 自定义配置


您可以使用构建客户端时可用的两个属性自定义服务客户端的端点解析：

1. `endpointUrl: Url`

1. `endpointProvider: EndpointProvider`

### Set `endpointUrl`


您可以为 `endpointUrl` 设置一个值来表示服务的“基本”主机名。但是，此值不是最终值，因为它是作为参数传递给客户端 `EndpointProvider` 实例的。然后，`EndpointProvider`实现可以检查并可能修改该值以确定最终端点。

例如，如果您为亚马逊简单存储服务 (Amazon S3) Simple Service 客户端指定`endpointUrl`值并执行`GetObject`操作，则默认终端节点提供程序实现会将存储桶名称注入主机名值。

实际上，用户将`endpointUrl`值设置为指向服务的开发或预览实例。

### Set `endpointProvider`


服务客户端的`EndpointProvider`实现决定了终端节点的最终解析。以下代码块中显示的`EndpointProvider`接口公开了该`resolveEndpoint`方法。

```
public fun interface EndpointProvider<T> {
    public suspend fun resolveEndpoint(params: T): Endpoint
}
```

服务客户端为每个请求调用该`resolveEndpoint`方法。服务客户端使用提供者返回的`Endpoint`值，不做任何进一步的更改。

#### `EndpointProvider` 属性


该`resolveEndpoint`方法接受服务特定的`EndpointParameters`对象，该对象包含端点解析中使用的属性。

每项服务都包括以下基本属性。


****  

| Name | Type | 说明 | 
| --- | --- | --- | 
| region | 字符串 | 客户 AWS 所在的地区 | 
| endpoint | 字符串 | endpointUrl 的值集的字符串表示形式 | 
| useFips | 布尔值 | 是否在客户端配置中启用了 FIPS 端点 | 
| useDualStack | 布尔值 | 是否在客户端配置中启用了双栈端点 | 

服务可以指定解析所需的其他属性。例如，Amazon S3 [https://docs.aws.amazon.com/sdk-for-kotlin/api/latest/s3/aws.sdk.kotlin.services.s3.endpoints/-s3-endpoint-parameters/index.html](https://docs.aws.amazon.com/sdk-for-kotlin/api/latest/s3/aws.sdk.kotlin.services.s3.endpoints/-s3-endpoint-parameters/index.html)包括存储桶名称以及几个特定于 Amazon S3 的功能设置。例如，`forcePathStyle` 属性决定是否可以使用虚拟主机寻址。

如果您实现了自己的提供程序，则无需构造自己的实例`EndpointParameters`。SDK 为每个请求提供属性并将其传递给您的 `resolveEndpoint` 实现。

### `endpointUrl` 或 `endpointProvider`


重要的是要明白，以下两个语句不会生成具有相同端点解析行为的客户端：

```
// Use endpointUrl.
S3Client.fromEnvironment { 
    endpointUrl = Url.parse("https://endpoint.example")
}

// Use endpointProvider.
S3Client.fromEnvironment {
    endpointProvider = object : S3EndpointProvider {
        override suspend fun resolveEndpoint(params: S3EndpointParameters): Endpoint = Endpoint("https://endpoint.example")
    }
}
```

设置该`endpointUrl`属性的语句指定了传递给（默认）提供者的*基本* URL，可以在端点解析过程中对其进行修改。

设置的语句`endpointProvider`指定了`S3Client`使用*的最终* URL。

尽管您可以设置这两个属性，但在大多数需要自定义的情况下，您可以提供其中一个。作为一般 SDK 用户，您通常会提供`endpointUrl`价值。

### 关于 Amazon S3 的说明


Amazon S3 是一项复杂的服务，其许多功能都是通过自定义终端节点自定义建模的，例如存储桶虚拟托管。虚拟托管是 Amazon S3 的一项功能，其中存储桶名称会插入到主机名中。

因此，我们建议您不要替换 Amazon S3 服务客户端中的`EndpointProvider`实现。如果您需要扩展其解析行为，例如通过向本地开发堆栈发送请求以及其他端点注意事项，我们建议您封装默认实现。以下`endpointProvider`示例显示了此方法的示例实现。

## 示例


### `endpointUrl` 示例


以下代码段显示了如何为 Amazon S3 客户端覆盖通用服务终端节点。

```
val client = S3Client.fromEnvironment {
    endpointUrl = Url.parse("https://custom-s3-endpoint.local")
    // EndpointProvider is left as the default.
}
```

### `endpointProvider` 示例


以下代码段展示了如何提供封装 Amazon S3 默认实现的自定义终端节点提供程序。

```
import aws.sdk.kotlin.services.s3.endpoints.DefaultS3EndpointProvider
import aws.sdk.kotlin.services.s3.endpoints.S3EndpointParameters
import aws.sdk.kotlin.services.s3.endpoints.S3EndpointProvider
import aws.smithy.kotlin.runtime.client.endpoints.Endpoint

public class CustomS3EndpointProvider : S3EndpointProvider {
    override suspend fun resolveEndpoint(params: S3EndpointParameters) =
        if (/* Input params indicate we must route another endpoint for whatever reason. */) {
            Endpoint(/* ... */)
        } else {
            // Fall back to the default resolution.
            DefaultS3EndpointProvider().resolveEndpoint(params)
        }
}
```

### `endpointUrl` 和 `endpointProvider`


以下示例程序演示了`endpointUrl`和`endpointProvider`设置之间的交互。这是一个高级使用案例。

```
import aws.sdk.kotlin.services.s3.S3Client
import aws.sdk.kotlin.services.s3.endpoints.DefaultS3EndpointProvider
import aws.sdk.kotlin.services.s3.endpoints.S3EndpointParameters
import aws.sdk.kotlin.services.s3.endpoints.S3EndpointProvider
import aws.smithy.kotlin.runtime.client.endpoints.Endpoint

fun main() = runBlocking {
    S3Client.fromEnvironment {
        endpointUrl = Url.parse("https://example.endpoint")
        endpointProvider = CustomS3EndpointProvider()
    }.use { s3 ->
        // ...
    }
}

class CustomS3EndpointProvider : S3EndpointProvider {
    override suspend fun resolveEndpoint(params: S3EndpointParameters) {
        // The resolved string value of the endpointUrl set in the client above is available here.
        println(params.endpoint) 
        // ...
    }
}
```

# HTTP


本节介绍中与 HTTP 相关的设置的配置。 适用于 Kotlin 的 AWS SDK

**Topics**
+ [

# HTTP 客户端配置
](http-client-config.md)
+ [

# 使用 HTTP 代理
](using-http-proxy.md)
+ [

# HTTP 拦截器
](interceptors.md)
+ [

# 强制使用最低版本的 TLS
](configure-http-tls.md)

# HTTP 客户端配置


默认情况下， 适用于 Kotlin 的 AWS SDK 使用基于的 HTTP 客户端[OkHttp](https://square.github.io/okhttp)。您可以通过提供明确配置的客户端来覆盖 HTTP 客户端及其配置。

**警告**  
无论您使用哪个 HTTP 引擎，项目中的其他依赖项都可能具有传递依赖关系，这些依赖关系与 SDK 要求的特定引擎版本相冲突。特别是，众所周知，诸如Spring Boot之类的框架可以管理依赖关系， OkHttp并且依赖于比SDK更旧的版本。请参[如何解决依赖冲突？](ts-faq-dep-conflict-resolution.md)阅，了解更多信息。

**注意**  
默认情况下，每个服务客户端都使用自己的 HTTP 客户端副本。如果您在应用程序中使用多个服务，则可能需要构建一个 HTTP 客户端并在所有服务客户端之间共享该客户端。

## 基本配置


配置服务客户端时，可以配置默认引擎类型。SDK 管理生成的 HTTP 客户端引擎，并在不再需要时自动将其关闭。

以下示例显示了 DynamoDB 客户端初始化期间的 HTTP 客户端配置。

### 导入


```
import aws.sdk.kotlin.services.dynamodb.DynamoDbClient
import kotlin.time.Duration.Companion.seconds
```

### 代码


```
DynamoDbClient {
    region = "us-east-2"
    httpClient {
        maxConcurrency = 64u
        connectTimeout = 10.seconds
    }
}.use { ddb ->

    // Perform some actions with Amazon DynamoDB.
}
```

## 高级配置


默认 HTTP 配置适用于大多数用例。对于某些高级用例，例如高吞吐量环境，以下高级配置选项提供了其他特性和功能：

### 指定 HTTP 引擎类型


要指定非默认 HTTP 引擎类型或自定义特定于特定 HTTP 引擎类型的配置，可以向其中传递一个用于指定`httpClient`引擎类型的附加参数。

以下示例指定了可用于配置[https://docs.aws.amazon.com/smithy-kotlin/api/latest/http-client-engine-okhttp/aws.smithy.kotlin.runtime.http.engine.okhttp/-ok-http-engine/index.html](https://docs.aws.amazon.com/smithy-kotlin/api/latest/http-client-engine-okhttp/aws.smithy.kotlin.runtime.http.engine.okhttp/-ok-http-engine/index.html)该[https://docs.aws.amazon.com/smithy-kotlin/api/latest/http-client-engine-okhttp/aws.smithy.kotlin.runtime.http.engine.okhttp/-ok-http-engine-config/index.html](https://docs.aws.amazon.com/smithy-kotlin/api/latest/http-client-engine-okhttp/aws.smithy.kotlin.runtime.http.engine.okhttp/-ok-http-engine-config/index.html)属性的内容。

#### 导入


```
import aws.sdk.kotlin.services.dynamodb.DynamoDbClient
import aws.smithy.kotlin.runtime.http.engine.okhttp.OkHttpEngine
```

#### 代码


```
DynamoDbClient {
    region = "us-east-2"
    httpClient(OkHttpEngine) {  // The first parameter specifies the HTTP engine type.
        // The following parameter is generic HTTP configuration available in any engine type.
        maxConcurrency = 64u

            // The following parameter is OkHttp-specific configuration.
        maxConcurrencyPerHost = 32u
    }
}.use { ddb ->

    // Perform some actions with Amazon DynamoDB.
}
```

引擎类型的可能值为`OkHttpEngine`[https://docs.aws.amazon.com/smithy-kotlin/api/latest/http-client-engine-okhttp4/aws.smithy.kotlin.runtime.http.engine.okhttp4/-ok-http4-engine/index.html](https://docs.aws.amazon.com/smithy-kotlin/api/latest/http-client-engine-okhttp4/aws.smithy.kotlin.runtime.http.engine.okhttp4/-ok-http4-engine/index.html)、和[https://docs.aws.amazon.com/smithy-kotlin/api/latest/http-client-engine-crt/aws.smithy.kotlin.runtime.http.engine.crt/-crt-http-engine/index.html](https://docs.aws.amazon.com/smithy-kotlin/api/latest/http-client-engine-crt/aws.smithy.kotlin.runtime.http.engine.crt/-crt-http-engine/index.html)。

要使用特定于 HTTP 引擎的配置参数，必须将该引擎添加为编译时依赖项。对于`OkHttpEngine`，您可以使用 Gradle 添加以下依赖项。

（您可以导航到该*X.Y.Z*链接以查看可用的最新版本。）

```
implementation(platform("aws.smithy.kotlin:bom:[https://github.com/smithy-lang/smithy-kotlin/releases/latest](https://github.com/smithy-lang/smithy-kotlin/releases/latest)"))
implementation("aws.smithy.kotlin:http-client-engine-okhttp")
```

对于`CrtHttpEngine`，添加以下依赖关系。

```
implementation(platform("aws.smithy.kotlin:bom:[https://github.com/smithy-lang/smithy-kotlin/releases/latest](https://github.com/smithy-lang/smithy-kotlin/releases/latest)"))
implementation("aws.smithy.kotlin:http-client-engine-crt")
```

#### 使用 `OkHttp4Engine`


`OkHttp4Engine`如果不能使用默认值，请使用`OkHttpEngine`。[smithy-kotlin GitHub 存储库](https://github.com/smithy-lang/smithy-kotlin/tree/main/runtime/protocol/http-client-engines/http-client-engine-okhttp4)包含有关如何配置和使用的信息。`OkHttp4Engine`

#### 使用显式的 HTTP 客户端


当你使用显式 HTTP 客户端时，你要对其生命周期负责，包括在不再需要它时关闭。HTTP 客户端的存活时间必须至少与使用它的任何服务客户端一样长。

以下代码示例显示了在 HTTP 客户端处于活动状态时保持 HTTP 客户端保持活动`DynamoDbClient`状态的代码。该[https://docs.aws.amazon.com/smithy-kotlin/api/latest/runtime-core/aws.smithy.kotlin.runtime.io/use.html](https://docs.aws.amazon.com/smithy-kotlin/api/latest/runtime-core/aws.smithy.kotlin.runtime.io/use.html)函数可确保 HTTP 客户端正确关闭。

##### 导入


```
import aws.sdk.kotlin.services.dynamodb.DynamoDbClient
import aws.smithy.kotlin.runtime.http.engine.okhttp.OkHttpEngine
import kotlin.time.Duration.Companion.seconds
```

##### 代码


```
OkHttpEngine {
    maxConcurrency = 64u
    connectTimeout = 10.seconds
}.use { okHttpClient ->

     DynamoDbClient {
        region = "us-east-2"
        httpClient = okHttpClient
    }.use { ddb ->
        {
            // Perform some actions with Amazon DynamoDB.
        }
    }
}
```

### 空闲连接监控


**重要**  
 OkHttp 引擎的连接空闲轮询功能 ([https://docs.aws.amazon.com/smithy-kotlin/api/latest/http-client-engine-okhttp/aws.smithy.kotlin.runtime.http.engine.okhttp/-ok-http-engine-config/connection-idle-polling-interval.html](https://docs.aws.amazon.com/smithy-kotlin/api/latest/http-client-engine-okhttp/aws.smithy.kotlin.runtime.http.engine.okhttp/-ok-http-engine-config/connection-idle-polling-interval.html)) 已被自动连接失败重试 () 所取代。[https://docs.aws.amazon.com/smithy-kotlin/api/latest/http-client-engine-okhttp/aws.smithy.kotlin.runtime.http.engine.okhttp/-ok-http-engine-config/retry-on-connection-failure.html](https://docs.aws.amazon.com/smithy-kotlin/api/latest/http-client-engine-okhttp/aws.smithy.kotlin.runtime.http.engine.okhttp/-ok-http-engine-config/retry-on-connection-failure.html)**连接空闲轮询将在 SDK 版本 1.7 中**弃用**，在 SDK 版本 **v1.** **8 中将移除**。**有关更多详细信息[，请参阅相关的 GitHub 讨论帖子](https://github.com/aws/aws-sdk-kotlin/discussions/1797)。

[https://docs.aws.amazon.com/smithy-kotlin/api/latest/http-client-engine-okhttp/aws.smithy.kotlin.runtime.http.engine.okhttp/-ok-http-engine/](https://docs.aws.amazon.com/smithy-kotlin/api/latest/http-client-engine-okhttp/aws.smithy.kotlin.runtime.http.engine.okhttp/-ok-http-engine/)提供了用于监控空闲连接以进行远程关闭的[https://docs.aws.amazon.com/smithy-kotlin/api/latest/http-client-engine-okhttp/aws.smithy.kotlin.runtime.http.engine.okhttp/-ok-http-engine-config/connection-idle-polling-interval.html](https://docs.aws.amazon.com/smithy-kotlin/api/latest/http-client-engine-okhttp/aws.smithy.kotlin.runtime.http.engine.okhttp/-ok-http-engine-config/connection-idle-polling-interval.html)配置选项。此功能可检测服务何时关闭了仍在连接池中的连接，从而防止后续请求出现错误。

当设置`connectionIdlePollingInterval`为非空值时，引擎会轮询释放回连接池的连接。轮询过程在套接字超时设置为指定间隔的情况下执行阻塞读取。当引擎从池中获取连接或连接被逐出并关闭时，轮询会自动取消。

当此值为`null`（默认）时，轮询处于禁用状态。远程关闭的池中的空闲连接在为后续调用获取连接时可能会遇到错误。

**注意**  
 由于轮询循环使用阻塞读取，因此获取或关闭连接的引擎调用的延迟时间可能与`connectionIdlePollingInterval`间隔一样长。为间隔选择较低的值意味着 SDK 可以更快地获取连接，但会增加空闲资源使用量。

#### 导入


```
import aws.sdk.kotlin.services.s3.S3Client
import aws.smithy.kotlin.runtime.http.engine.okhttp.OkHttpEngine
import kotlin.time.Duration.Companion.milliseconds
```

#### 代码


```
S3Client.fromEnvironment {
    httpEngine(OkHttpEngine) {
        connectionIdlePollingInterval = 50.milliseconds
    }
}.use { s3 -> 
  // Use the Amazon S3 client
}
```

# 使用 HTTP 代理


要使用 AWS 通过代理服务器进行访问 适用于 Kotlin 的 AWS SDK，可以配置 JVM 系统属性或环境变量。如果同时提供两者，则 JVM 系统属性优先。

## 使用 JVM 系统属性


SDK 会查找 JVM 系统属性`https.proxyHost``https.proxyPort`、和。`http.nonProxyHosts`有关这些常用 JVM 系统属性的更多信息，请参阅 Java 文档中的[网络和代理](https://docs.oracle.com/javase/8/docs/technotes/guides/net/proxies.html)。

```
java -Dhttps.proxyHost=10.15.20.25 -Dhttps.proxyPort=1234 -Dhttp.nonProxyHosts=localhost|api.example.com MyApplication
```

## 使用环境变量


SDK 会查找`https_proxy``http_proxy`、和`no_proxy`环境变量（以及每个变量的大写版本）。

```
export http_proxy=http://10.15.20.25:1234
export https_proxy=http://10.15.20.25:5678
export no_proxy=localhost,api.example.com
```

## 在 EC2 实例上使用代理


如果您在使用附加的 IAM 角色启动的 EC2 实例上配置代理，请确保豁免用于访问[实例元数据](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html)的地址。为此，请将 `http.nonProxyHosts` JVM 系统属性或`no_proxy`环境变量设置为实例元数据服务的 IP 地址，即`169.254.169.254`。该地址保持不变。

```
export no_proxy=169.254.169.254
```

# HTTP 拦截器
拦截器

您可以使用拦截器介入 API 请求和响应的执行过程。拦截器是一种开放式机制，在这种机制中，SDK 调用您编写的代码将行为注入 request/response 生命周期。这样，您便可修改正在进行的请求、调试请求处理、查看异常等。

以下示例显示了一个简单的拦截器，它在进入重试循环之前向所有传出的请求添加一个额外的标头。

```
class AddHeader(
    private val key: String,
    private val value: String
) : HttpInterceptor {
    override suspend fun modifyBeforeRetryLoop(context: ProtocolRequestInterceptorContext<Any, HttpRequest>): HttpRequest {
        val httpReqBuilder = context.protocolRequest.toBuilder()
        httpReqBuilder.headers[key] = value
        return httpReqBuilder.build()
    }
}
```

有关更多信息和可用的拦截挂钩，请参阅[拦截器](https://docs.aws.amazon.com/smithy-kotlin/api/latest/smithy-client/aws.smithy.kotlin.runtime.client/-interceptor/index.html)接口。

## 拦截器注册


在构造服务客户端或覆盖一组特定操作的配置时，可以注册拦截器。

### 用于所有服务客户端操作的拦截器


以下代码向生成器的拦截器属性中添加了一个`AddHeader`实例。在进入重试循环之前，此新增功能会将`x-foo-version`标题添加到所有操作中。

```
val s3 = S3Client.fromEnvironment {
    interceptors += AddHeader("x-foo-version", "1.0")
}

// All service operations invoked using 's3' will have the header appended.
s3.listBuckets { ... }
s3.listObjectsV2 { ... }
```

### 拦截器仅用于特定操作


通过使用该`withConfig`扩展，您可以为任何[服务客户端的一个或多个操作覆盖服务客户端配置](override-client-config.md)。使用此功能，您可以为一部分操作注册其他拦截器。

以下示例覆盖了`use`扩展中操作的`s3`实例配置。上调用的操作同时`s3Scoped`包含`x-foo-version`和标`x-bar-version`题。

```
// 's3' instance created in the previous code snippet.
s3.withConfig {
    interceptors += AddHeader("x-bar-version", "3.7")
}.use { s3Scoped ->
    // All service operations invoked using 's3Scoped' trigger interceptors
    // that were registered when the client was created and any added in the
    // withConfig { ... } extension.
}
```

# 强制使用最低版本的 TLS
强制使用最低版本的 TLS

借助 适用于 Kotlin 的 AWS SDK，您可以在连接到服务终端节点时配置最低 TLS 版本。SDK 提供不同的配置选项。按优先级从高到低的顺序排列，选项为：
+ 显式配置 HTTP 引擎
+ 设置 `sdk.minTls` JVM 系统属性
+ 设置`SDK_MIN_TLS`环境变量

## 配置 HTTP 引擎
HTTP 引擎

为服务客户端指定非默认 HTTP 引擎时，可以设置该`tlsContext.minVersion`字段。

以下示例将 HTTP 引擎和使用它的所有服务客户端配置为至少使用 TLS v1.2。

```
DynamoDbClient {
    region = "us-east-2"
    httpClient {
        tlsContext {
            minVersion = TlsVersion.TLS_1_2
        }
    }
}.use { ddb ->

    // Perform some actions with Amazon DynamoDB.
}
```

## 设置 `sdk.minTls` JVM 系统属性
JVM 系统属性

您可以设置 `sdk.minTls` JVM 系统属性。当您启动设置了系统属性的应用程序时，默认情况下，由构造的所有 HTTP 引擎都 适用于 Kotlin 的 AWS SDK 使用指定的最低 TLS 版本。但是，您可以在 HTTP 引擎配置中显式覆盖此设置。允许的值为：
+ TLS\$11\$10
+ TLS\$11\$11
+ TLS\$11\$12
+ TLS\$11\$13

## 设置`SDK_MIN_TLS`环境变量
环境变量

您可以设置`SDK_MIN_TLS`环境变量。当您启动设置了环境变量的应用程序时，由其构造的所有 HTTP 引擎都 适用于 Kotlin 的 AWS SDK 使用指定的最低 TLS 版本，除非被其他选项覆盖。

允许的值为：
+ TLS\$11\$10
+ TLS\$11\$11
+ TLS\$11\$12
+ TLS\$11\$13

# 在中重试 适用于 Kotlin 的 AWS SDK
重试[在中重试 适用于 Kotlin 的 AWS SDK](#retries)

重新整理内容并添加了有关可重试异常的详细信息。

调用 AWS 服务 偶尔会返回意外异常。如果重试调用，某些类型的错误（例如节流或暂时错误）可能会成功。

本页介绍如何自动 适用于 Kotlin 的 AWS SDK 处理重试以及如何为您的应用程序自定义重试行为。

## 了解重试行为


以下各节说明了 SDK 如何确定何时重试请求以及哪些异常被视为可重试。

### 默认重试配置
默认配置

默认情况下，每个服务客户端都会自动配置[标准重试策略](https://docs.aws.amazon.com/smithy-kotlin/api/latest/runtime-core/aws.smithy.kotlin.runtime.retries/-standard-retry-strategy/index.html)。默认配置最多会尝试失败三次的呼叫（初次尝试加上两次重试）。每次呼叫之间的中间延迟配置为指数退避和随机抖动，以避免重试风暴。此配置适用于大多数用例，但在某些情况下可能不适合，例如高吞吐量系统。

SDK 仅在出现可重试错误时才会尝试重试。可重试错误的示例包括套接字超时、服务端节流、并发或乐观锁失败以及暂时性服务错误。参数缺失或无效、 authentication/security 错误和配置错误异常不被视为可重试。

您可以通过设置最大尝试次数、延迟和退避次数以及令牌桶配置来自定义标准重试策略。

### 哪些异常是可以重试的？


 适用于 Kotlin 的 AWS SDK 使用预配置的重试策略来确定哪些异常是可重试的。服务客户端配置具有一个`retryPolicy`属性，用于指定应用于重试的策略。如果未指定自定义值，则默认值为[AwsRetryPolicy](https://docs.aws.amazon.com/sdk-for-kotlin/api/latest/aws-http/aws.sdk.kotlin.runtime.http.retries/-aws-retry-policy/)。

以下异常通过以下方式确定为可重试：`AwsRetryPolicy`

#### 可通过错误代码重试


任何`ServiceException`具有以下值的`sdkErrorMetadata.errorCode`任意：
+ `BandwidthLimitExceeded`
+ `EC2ThrottledException`
+ `IDPCommunicationError`
+ `LimitExceededException`
+ `PriorRequestNotComplete`
+ `ProvisionedThroughputExceededException`
+ `RequestLimitExceeded`
+ `RequestThrottled`
+ `RequestThrottledException`
+ `RequestTimeout`
+ `RequestTimeoutException`
+ `SlowDown`
+ `ThrottledException`
+ `Throttling`
+ `ThrottlingException`
+ `TooManyRequestsException`
+ `TransactionInProgressException`

#### 可通过 HTTP 状态码重试


任何`ServiceException`具有以下值的`sdkErrorMetadata.statusCode`任意：
+ 500（内部服务错误）
+ 502（错误的网关）
+ 503（服务不可用）
+ 504（网关超时）

#### 可按错误类型重试


任何`ServiceException`具有以下值的`sdkErrorMetadata.errorType`任意：
+ `ErrorType.Server`（例如内部服务错误）
+ `ErrorType.Client`（例如请求无效、未找到资源、访问被拒绝等）

#### 可通过 SDK 元数据重试


任何`SdkBaseException`地方：
+ `sdkErrorMetadata.isRetryable`是`true`（例如客户端超时、 networking/socket 错误等）
+ `sdkErrorMetadata.isThrottling`是`true`（例如在短时间内发出太多请求）

有关每个服务客户端可能抛出的异常的完整列表，请参阅[特定于服务的 API 参考文档](https://docs.aws.amazon.com/#products)。

### 检查异常是否可以重试


要确定 SDK 是否认为异常可重试，请检查捕获到的异常的`isRetryable`属性：

```
try {
    dynamoDbClient.putItem {
        tableName = "MyTable"
        item = mapOf("id" to AttributeValue.S("123"))
    }
} catch (e: SdkBaseException) {
    println("Exception occurred: ${e.message}")
    
    if (e.sdkErrorMetadata.isRetryable) {
        println("This exception is retryable - SDK will automatically retry")
        println("If you're seeing this, retries may have been exhausted")
    } else {
        println("This exception is not retryable - fix the underlying issue")
        
        // Common non-retryable scenarios.
        when {
            e.message?.contains("ValidationException") == true -> 
                println("Check your request parameters")
            e.message?.contains("AccessDenied") == true -> 
                println("Check your IAM permissions")
            e.message?.contains("ResourceNotFound") == true -> 
                println("Verify the resource exists")
        }
    }
}
```

### 当重试失败时，你的代码会出现哪些异常


当 SDK 的重试机制无法解决问题时，您的应用程序代码就会抛出异常。了解这些异常类型有助于您实现适当的错误处理。这些*不是*触发重试的例外情况，而是由 SDK 内部处理的。

当重试用尽或禁用时，你的代码将捕获以下类型的异常：

重试耗尽后的服务异常  
当所有重试尝试都失败时，您的代码会捕获导致最后一次重试失败的最终服务异常（的子类`AwsServiceException`）。这可能是限制错误、服务器错误或其他特定于服务的异常，SDK 无法通过重试解决这些异常。

重试耗尽后的网络异常  
当网络问题在所有重试尝试中仍然存在时，您的代码会捕获连接超时、DNS 解析失败以及 SDK 无法解决的其他连接问题等问题的`ClientException`实例。

使用以下模式来处理应用程序中的这些异常：

```
try {
    s3Client.getObject { 
        bucket = "amzn-s3-demo-bucket"
        key = "my-key" 
    }
} catch (e: AwsServiceException) {
    // Service-side errors that persisted through all retries.
    println("Service error after retries: ${e.errorDetails?.errorCode} - ${e.message}")
    
    // Handle specific service errors that couldn't be resolved.
    if (e.errorDetails?.errorCode == "ServiceQuotaExceededException" || 
        e.errorDetails?.errorCode == "ThrottlingException") {
        println("Rate limiting persisted - consider longer delays or quota increase")
    }
} catch (e: ClientException) {
    // Client-side errors (persistent network issues, DNS resolution failures, etc.)
    println("Client error after retries: ${e.message}")
}
```

## 自定义重试行为


以下各节介绍如何针对您的特定用例自定义 SDK 的重试行为。

### 配置最大尝试次数
最大尝试次数

在构造客户端期间，您可以自定义 [`retryStrategy`DSL 区块](https://docs.aws.amazon.com/smithy-kotlin/api/latest/runtime-core/aws.smithy.kotlin.runtime.retries/-standard-retry-strategy/-config/-builder/index.html)中的默认最大尝试次数 (3)。

```
val dynamoDb = DynamoDbClient.fromEnvironment {
    retryStrategy {
        maxAttempts = 5
    }
}
```

上一个片段中显示了 DynamoDB 服务客户端，SDK 最多会尝试五次失败的 API 调用（初次尝试加上四次重试）。

您可以通过将最大尝试次数设置为一次来完全禁用自动重试，如以下代码段所示。

```
val dynamoDb = DynamoDbClient.fromEnvironment {
    retryStrategy {
        maxAttempts = 1  // The SDK makes no retries.
    }
}
```

### 配置延迟和退缩
延迟和回退

如果需要重试，默认的重试策略会在进行下一次尝试之前等待一段时间。第一次重试的延迟时间很短，但后续重试的延迟时间会呈指数级增长。最长延迟时间是有上限的，以防延迟时间过长。

最后，随机抖动会应用于所有尝试之间的延迟。抖动有助于降低可能导致重试风暴的大量重试的影响。（有关指数回退和抖[动的更深入讨论，请参阅这篇AWS 架构博客文章](https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/)。）

延迟参数可在 [`delayProvider`DSL 模块](https://docs.aws.amazon.com/smithy-kotlin/api/latest/runtime-core/aws.smithy.kotlin.runtime.retries.delay/-exponential-backoff-with-jitter/-config/index.html)中进行配置。

```
val dynamoDb = DynamoDbClient.fromEnvironment {
    retryStrategy {
        delayProvider {
            initialDelay = 100.milliseconds
            maxBackoff = 5.seconds
        }
    }
}
```

使用上一个片段所示的配置，客户端将第一次重试尝试最多延迟 100 毫秒。任何重试尝试之间的最大间隔为 5 秒。

以下参数可用于调整延迟和退缩。


| 参数 | 默认 值 | 说明 | 
| --- | --- | --- | 
| initialDelay | 10 毫秒 | 第一次重试的最大延迟时间。施加抖动时，实际延迟量可能会更少。 | 
| jitter | 1.0（完全抖动） |  随机减少计算延迟的最大振幅。默认值为 1.0 意味着计算出的延迟可以减少到不超过 100% 的任意值（例如，降至 0）。值为 0.5 意味着计算出的延迟最多可以减少一半。因此，10 毫秒的最大延迟可以减少到 5 毫秒到 10 毫秒之间的任何值。值为 0.0 表示不施加任何抖动。  ️ 抖动配置是一项高级功能。通常不建议自定义此行为。   | 
| maxBackoff | 20 秒 | 适用于任何尝试的最大延迟时间。设置此值可以限制在后续尝试之间发生的指数级增长，并防止计算出的最大值过大。此参数限制了在应用抖动之前计算出的延迟。如果应用抖动，则可能会进一步缩短延迟。 | 
| scaleFactor | 1.5 | 随后的最大延迟将增加的指数基数。例如，假定 a 为 `initialDelay` 10ms，a 为 `scaleFactor` 1.5，则将计算出以下最大延迟：[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/sdk-for-kotlin/latest/developer-guide/retries.html)当施加抖动时，每次延迟的实际量可能会更少。 | 

### 配置重试令牌存储桶
重试令牌桶

您可以通过调整默认令牌桶配置来进一步修改标准重试策略的行为。重试令牌存储桶有助于减少不太可能成功或可能需要更多时间才能解决的重试，例如超时和限制失败。

**重要**  
令牌存储桶配置是一项高级功能。通常不建议自定义此行为。

每次重试尝试（可选包括初次尝试）都会减少令牌桶中的一些容量。减少的金额取决于尝试的类型。例如，重试瞬态错误可能很便宜，但重试超时或限制错误可能会更昂贵。

成功尝试将容量返回到存储桶。存储桶的增量不得超过其最大容量，也不得减至零以下。

根据`useCircuitBreakerMode`设置的值，尝试将容量减少到零以下会导致以下结果之一：
+ 如果设置为 TRUE，则会引发异常 — 例如，如果重试次数过多，并且不太可能成功更多的重试。
+ 如果设置为 FALSE，则会有延迟，例如，延迟到存储桶再次有足够的容量。

**注意**  
当断路器激活（令牌桶容量为零）时，SDK 会抛出 “已`ClientException`超出重试容量” 消息。这是客户端异常，而不是`AwsServiceException`，因为它源于 SDK 的重试逻辑而不是服务。 AWS 无需尝试操作即可立即抛出异常，这有助于防止服务中断期间的重试风暴。

令牌桶参数可在 [`tokenBucket`DSL 区块](https://docs.aws.amazon.com/smithy-kotlin/api/latest/runtime-core/aws.smithy.kotlin.runtime.retries.delay/-standard-retry-token-bucket/-config/index.html)中配置：

```
val dynamoDb = DynamoDbClient.fromEnvironment {
    retryStrategy {
        tokenBucket {
            maxCapacity = 100
            refillUnitsPerSecond = 2
        }
    }
}
```

以下参数可用于调整重试令牌存储桶：


| 参数 | 默认 值 | 说明 | 
| --- | --- | --- | 
| initialTryCost | 0 | 初始尝试时要从存储桶中减少的金额。默认值 0 表示容量不会减少，因此初始尝试不会停止或延迟。 | 
| initialTrySuccessIncrement | 1 | 初始尝试成功时要增加容量的量。 | 
| maxCapacity | 500 | 令牌桶的最大容量。可用代币的数量不能超过此数字。 | 
| refillUnitsPerSecond | 0 | 每秒向存储桶重新添加的容量。值为 0 表示不会自动重新添加任何容量。（例如，只有成功的尝试才会增加容量）。如果值为 0，则必须useCircuitBreakerMode为 TRUE。 | 
| retryCost | 5 | 暂时失败后尝试从存储桶中减少的金额。如果尝试成功，则将相同的金额重新递增回存储桶。 | 
| timeoutRetryCost | 10 | 超时或限制失败后尝试从存储桶中减少的金额。如果尝试成功，则将相同的金额重新递增回存储桶。 | 
| useCircuitBreakerMode | TRUE | 确定尝试减少容量会导致存储桶容量降至零以下时的行为。如果为 TRUE，则令牌存储桶将抛出一个异常，表示不再存在重试容量。如果为 FALSE，则令牌存储桶将延迟尝试，直到重新填充了足够的容量。 | 

有关在重试场景中引发的异常类型（包括断路器异常）的详细信息，请参阅[当重试失败时，你的代码会出现哪些异常](#retries-exception-types-during-retries)。

### 配置自适应重试
自适应重试

作为标准重试策略的替代方案，自适应重试策略是一种高级方法，它寻求理想的请求速率以最大限度地减少限制错误。

**重要**  
自适应重试是一种高级重试模式。通常不建议使用这种重试策略。

自适应重试具备标准重试的所有功能。它添加了一个客户端速率限制器，用于衡量节流请求与非节流请求的比率。它还会限制尝试流量以保持在安全带宽内，理想情况下会使节流错误为零。

该速率会根据不断变化的服务条件和流量模式实时调整，并可能相应地增加或减少流量速率。至关重要的是，在高流量场景中，速率限制器可能会延迟初始尝试。

您可以通过为`retryStrategy`方法提供附加参数来选择自适应重试策略。速率限制器参数可在 [`rateLimiter`DSL](https://docs.aws.amazon.com/smithy-kotlin/api/latest/runtime-core/aws.smithy.kotlin.runtime.retries.delay/-adaptive-rate-limiter/-config/index.html) 模块中进行配置。

```
val dynamoDb = DynamoDbClient.fromEnvironment {
    retryStrategy(AdaptiveRetryStrategy) {
        maxAttempts = 10
        rateLimiter {
            minFillRate = 1.0
            smoothing = 0.75
        }
    }
}
```

**注意**  
自适应重试策略假设客户端使用单个资源（例如，一个 DynamoDB 表或一个 Amazon S3 存储桶）。  
如果您使用单个客户端处理多个资源，则当客户端访问所有其他资源时，与一个资源相关的节流或中断会导致延迟增加和出现故障。当您使用自适应重试策略时，我们建议您为每种资源使用一个客户端。

# 可观测性


可观测性是指可以根据系统发出的数据推断出其当前状态的程度。发出的数据通常称为遥测。

 适用于 Kotlin 的 AWS SDK 可以提供所有三种常见的遥测信号：指标、跟踪和日志。您可以连接[https://docs.aws.amazon.com/smithy-kotlin/api/latest/telemetry-api/aws.smithy.kotlin.runtime.telemetry/-telemetry-provider/index.html](https://docs.aws.amazon.com/smithy-kotlin/api/latest/telemetry-api/aws.smithy.kotlin.runtime.telemetry/-telemetry-provider/index.html)以将遥测数据发送到可观测性后端（例如或 [AWS X-Ray](https://docs.aws.amazon.com/xray/?icmpid=docs_homepage_devtools)A [ma](https://docs.aws.amazon.com/cloudwatch/?icmpid=docs_homepage_mgmtgov) zon CloudWatch），然后对其进行操作。

默认情况下，SDK 中仅启用日志功能，禁用其他遥测信号。本主题介绍如何启用和配置遥测输出。

**重要**  
`TelemetryProvider`目前是一个实验性 API，必须选择加入才能使用。

## 配置 `TelemetryProvider`


您可以在应用程序`TelemetryProvider`中为所有服务客户端或单个客户端全局配置。以下示例使用假设`getConfiguredProvider()`函数来演示 `TelemetryProvider` API 操作。本[遥测提供程序](observability-telemetry-providers.md)节介绍了 SDK 提供的实现信息。如果不支持提供商，则可以实现自己的支持或[在上打开功能请求 GitHub](https://github.com/awslabs/aws-sdk-kotlin/issues/new/choose)。

### 配置默认的全局遥测提供程序


默认情况下，每个服务客户端都尝试使用全局可用的遥测提供程序。这样，您只需设置一次提供程序，所有客户端都会使用它。在实例化任何服务客户端之前，只能执行一次。

要使用全局遥测提供程序，请先更新您的项目依赖项以添加遥测默认模块，如以下 Gradle 代码段所示。

（您可以导航到该*X.Y.Z*链接以查看可用的最新版本。）

```
dependencies {
    implementation(platform("aws.smithy.kotlin:bom:[https://github.com/smithy-lang/smithy-kotlin/releases/latest](https://github.com/smithy-lang/smithy-kotlin/releases/latest)"))
    implementation("aws.smithy.kotlin:telemetry-defaults")
    ...
}
```

然后在创建服务客户端之前设置全局遥测提供商，如以下代码所示。

```
import aws.sdk.kotlin.services.s3.S3Client
import aws.smithy.kotlin.runtime.telemetry.GlobalTelemetryProvider
import kotlinx.coroutines.runBlocking

fun main() = runBlocking {
    val myTelemetryProvider = getConfiguredProvider()
    GlobalTelemetryProvider.set(myTelemetryProvider)

    S3Client.fromEnvironment().use { s3 ->
        …
    }     
}

fun getConfiguredProvider(): TelemetryProvider {
    TODO("TODO - configure a provider")
}
```

### 为特定服务客户端配置遥测提供程序


您可以为单个服务客户端配置特定的遥测提供程序（而不是全局遥测提供程序）。如以下示例所示。

```
import aws.sdk.kotlin.services.s3.S3Client
import kotlinx.coroutines.runBlocking

fun main() = runBlocking {
    S3Client.fromEnvironment{
        telemetryProvider = getConfiguredProvider()
    }.use { s3 ->
        ...
    }
}

fun getConfiguredProvider(): TelemetryProvider {
    TODO("TODO - configure a provider")
}
```

# 指标


下表列出了 SDK 发出的遥测指标。[配置遥测提供程序](observability.md#observability-conf-telemetry-provider)以使指标可观测。


**发出哪些指标？**  

| 指标名称 | 单位 | Type | 属性 | 说明 | 
| --- | --- | --- | --- | --- | 
| smithy.client.call.durati | s | 直方图 | rpc.service, rpc.method | 总通话时长（包括重试次数） | 
| smithy.client.call.tept | \$1attempt\$1 | MonotonicCounter | rpc.service, rpc.method | 单个操作的尝试次数 | 
| smithy.client.call.errors | \$1error\$1 | MonotonicCounter | rpc.service, rpc.method, exception.type | 操作的错误数 | 
| smithy.client.call.tempt\$1duration | s | 直方图 | rpc.service, rpc.method | 连接到服务、发送请求以及获取 HTTP 状态代码和标头所用的时间（包括等待发送的排队时间） | 
| smithy.client.call.resolve\$1endpoint\$1持续时间 | s | 直方图 | rpc.service, rpc.method | 解析请求的端点（端点解析器，不是 DNS）所用的时间 | 
| smithy.client.call.serialization\$1dur | s | 直方图 | rpc.service, rpc.method | 序列化消息正文所用的时间 | 
| smithy.client.call.derization\$1duration | s | 直方图 | rpc.service, rpc.method | 反序列化消息正文所用的时间 | 
| smithy.client.call.auth.signing\$1durati | s | 直方图 | rpc.service、rpc.method、auth.scheme\$1 | 签署请求所用的时间 | 
| smithy.client.call.auth.resolve\$1identity\$1持续时间 | s | 直方图 | rpc.service、rpc.method、auth.scheme\$1 | 从身份提供商处获取身份（例如 AWS 凭证或持有者令牌）所花费的时间 | 
| smithy.client.http.connections.acquire\$1 | s | 直方图 |  | 请求获取连接所花费的时间 | 
| smithy.client.http.connections. | \$1连接\$1 | [异步] UpDownCounter |  | HTTP 客户端的最大打开连接数 allowed/configured  | 
| smithy.client.http.connections. | \$1连接\$1 | [异步] UpDownCounter | 状态：闲置 \$1 已获得 | 连接池的当前状态 | 
| smithy.client.http.connections. | s | 直方图 |  | 连接打开的时间 | 
| smithy.client.http.requests. | \$1请求\$1 | [异步] UpDownCounter | 状态：已排队 \$1 飞行中 | HTTP 客户端请求并发的当前状态 | 
| smithy.client.http.requead\$1duration | s | 直方图 |  | 请求排队等待 HTTP 客户端执行所花费的时间 | 
| smithy.client.http.bytes\$1sent | 方式 | MonotonicCounter | server.address | HTTP 客户端发送的字节总数 | 
| smithy.client.http.bytes\$1receiv | 方式 | MonotonicCounter | server.address | HTTP 客户端接收的字节总数 | 

以下是列说明：
+ **指标名称** – 发出的指标的名称。
+ **单位** - 指标的度量单位。单位以 [UCUM](https://unitsofmeasure.org/ucum) 区分大小写（“c/s”）表示法给出。
+ **类型** - 用于捕获指标的工具类型。
+ **描述** - 对指标所衡量内容的描述。
+ **属性** - 与指标一起发出的一组属性（维度）。

# 日志记录
日志记录

将兼容 [SLF4J](https://www.slf4j.org/manual.html) 的记录器 适用于 Kotlin 的 AWS SDK 配置为遥测提供商`LoggerProvider`的默认记录器。使用 SLF4 J（抽象层），您可以在运行时使用多个日志系统中的任何一个。[支持的日志系统包括 [Java Logging APIs](https://docs.oracle.com/javase/8/docs/technotes/guides/logging/)、[Log4j 2](https://logging.apache.org/log4j/2.x/) 和 Logback。](https://logback.qos.ch/)

**警告**  
我们建议您仅将线路日志用于调试目的。（下文将讨论线路记录。） 在生产环境中将其关闭，因为它可以记录敏感数据，例如电子邮件地址、安全令牌、API 密钥、密码和 AWS Secrets Manager 机密。即使是 HTTPS 呼叫，电线日志记录也无需加密即可记录完整的请求或响应。  
对于大型请求（例如将文件上传到 Amazon S3）或响应，冗长的电汇记录也会显著影响应用程序的性能。

## Log4j 2 日志配置示例


 虽然可以使用任何`SLF4J`兼容的日志库，但此示例使用 Log4j 2 在 JVM 程序中启用 SDK 的日志输出：

**Gradle 依赖关系**

（您可以导航到该*X.Y.Z*链接以查看可用的最新版本。）

```
implementation("org.apache.logging.log4j:log4j-slf4j2-impl:[https://search.maven.org/#search|gav|1|g:org.apache.logging.log4j%20AND%20a:log4j-slf4j2-impl](https://search.maven.org/#search|gav|1|g:org.apache.logging.log4j%20AND%20a:log4j-slf4j2-impl)")
```

**Log4j 2 配置文件**

`log4j2.xml`在您的`resources`目录中创建一个名为的文件（例如，`<project-dir>/src/main/resources`）。将以下 XML 配置添加到文件中：

```
<Configuration status="ERROR">
    <Appenders>
        <Console name="Out">
            <PatternLayout pattern="%d{YYYY-MM-dd HH:mm:ss} %-5p %c:%L %X - %encode{%m}{CRLF}%n"/>
        </Console>
    </Appenders>
    <Loggers>
        <Root level="info">
            <AppenderRef ref="Out"/>
        </Root>
    </Loggers>
</Configuration>
```

此配置在`pattern`属性中包含启用 MDC（映射的诊断上下文）日志记录的`%X`说明符。

SDK 为每个操作添加以下 MDC 元素。

**rpc**  
例如`S3.GetObject`，被调用的 RPC 的名称。

**sdkInvocationId**  
服务客户端为操作分配的唯一 ID。该 ID 关联与调用单个操作相关的所有日志事件。

## 为线级消息指定日志模式


默认情况下， 适用于 Kotlin 的 AWS SDK 不记录线级消息，因为它们可能包含来自 API 请求和响应的敏感数据。但是，有时出于调试目的，你需要这种详细程度。

使用 Kotlin SDK，您可以在代码中设置日志模式，也可以使用环境设置为以下内容启用调试消息：
+ HTTP 请求
+ HTTP 响应

日志模式由一个位域支持，其中每个位都是一个标志（模式），值是累加的。您可以将一种请求模式和一种响应模式结合使用。

### 在代码中设置日志模式


要选择使用其他日志记录，请在构建服务客户端时设置该`logMode`属性。

以下示例说明如何启用请求（使用正文）和响应（不带正文）的日志记录。

```
import aws.smithy.kotlin.runtime.client.LogMode

// ...

val client = DynamoDbClient {
    // ...
    logMode = LogMode.LogRequestWithBody + LogMode.LogResponse
}
```

在服务客户端构建期间设置的日志模式值会覆盖环境中设置的任何日志模式值。

### 从环境中设置日志模式


要为所有未在代码中明确配置的服务客户机设置全局日志模式，请使用以下方法之一：
+ JVM 系统属性：`sdk.logMode`
+ 环境变量：`SDK_LOG_MODE`

以下不区分大小写的值可用：
+ `LogRequest`
+ `LogRequestWithBody`
+ `LogResponse`
+ `LogResponseWithBody`

要使用环境中的设置创建组合日志模式，请使用竖线 (`|`) 符号分隔值。

例如，以下示例设置的日志模式与前面的示例相同。

```
# Environment variable.
export SDK_LOG_MODE=LogRequestWithBody|LogResponse
```

```
# JVM system property.
java -Dsdk.logMode=LogRequestWithBody|LogResponse ...
```

**注意**  
您还必须配置兼容的 SLF4 J Logger 并将日志级别设置为 DEBUG 才能启用线级日志记录。

# 遥测提供程序


SDK 目前支持 [OpenTelemetry](https://opentelemetry.io/)(OTel) 作为提供者。SDK 将来可能会提供其他遥测提供商。

**Topics**
+ [

# 配置 OpenTelemetry基于遥测的提供商
](observability-telemetry-providers-otel.md)

# 配置 OpenTelemetry基于遥测的提供商
OpenTelemetry

适用于 Kotlin 的 SDK 提供了由 OpenTelemetry支持的`TelemetryProvider`接口的实现。

## 先决条件


更新您的项目依赖项以添加 OpenTelemetry 提供者，如以下 Gradle 代码段所示。您可以导航到该*X.Y.Z*链接以查看可用的最新版本。

```
dependencies {
    implementation(platform("aws.smithy.kotlin:bom:[https://github.com/smithy-lang/smithy-kotlin/releases/latest](https://github.com/smithy-lang/smithy-kotlin/releases/latest)"))
    implementation(platform("io.opentelemetry.instrumentation:opentelemetry-instrumentation-bom:[https://search.maven.org/#search|gav|1|g:io.opentelemetry.instrumentation%20AND%20a:opentelemetry-instrumentation-bom](https://search.maven.org/#search|gav|1|g:io.opentelemetry.instrumentation%20AND%20a:opentelemetry-instrumentation-bom)"))
    implementation("aws.smithy.kotlin:telemetry-provider-otel")

    // OPTIONAL: If you use log4j, the following entry enables the ability to export logs through OTel.
    runtimeOnly("io.opentelemetry.instrumentation:opentelemetry-log4j-appender-2.17")
}
```

## 配置 SDK


以下代码使用 OpenTelemetry遥测提供程序配置服务客户端。

```
import aws.sdk.kotlin.services.s3.S3Client
import aws.smithy.kotlin.runtime.telemetry.otel.OpenTelemetryProvider
import io.opentelemetry.api.GlobalOpenTelemetry
import kotlinx.coroutines.runBlocking

fun main() = runBlocking {
    val otelProvider = OpenTelemetryProvider(GlobalOpenTelemetry.get())

    S3Client.fromEnvironment().use { s3 ->
        telemetryProvider = otelProvider
        …
    }
}
```

**注意**  
关于如何配置 OpenTelemetry SDK 的讨论不在本指南的讨论范围之内。[OpenTelemetryJava 文档](https://opentelemetry.io/docs/instrumentation/java/)包含有关各种方法的配置信息：[手动](https://opentelemetry.io/docs/instrumentation/java/manual/)、通过 [Java 代理](https://opentelemetry.io/docs/instrumentation/java/automatic/)自动或（可选）[收集器](https://opentelemetry.io/docs/collector/)。

## 资源


以下资源可帮助您入门 OpenTelemetry。
+ [AWS 发行版 for OpenTelemetry](https://aws-otel.github.io/docs/introduction)- AWS OTe L Distro 主页
+ [aws-otel-java-instrumentation](https://github.com/aws-observability/aws-otel-java-instrumentation)- OpenTelemetry Java 工具库 AWS 发行版
+ [aws-otel-lambda](https://github.com/aws-observability/aws-otel-lambda)- AWS 托管 OpenTelemetry Lambda 层
+ [aws-otel-collector](https://github.com/aws-observability/aws-otel-collector)- AWS 收藏家发行 OpenTelemetry版
+ [AWS 可观测性最佳实践](https://aws-observability.github.io/observability-best-practices/)-特定于可观测性的一般最佳实践 AWS

# 覆盖服务客户端配置
覆盖客户端配置

[创建服务客户端](creating-clients.md)后，服务客户端将对所有操作使用固定配置。但是，有时您可能需要覆盖一个或多个特定操作的配置。

每个服务客户端都有一个`withConfig`扩展，因此您可以修改现有配置的副本。该`withConfig`扩展程序返回一个配置经过修改的新服务客户端。原始客户机独立存在，并使用其原始配置。

以下示例显示如何创建调用两个操作的`S3Client`实例。

```
val s3 = S3Client.fromEnvironment {
    logMode = LogMode.LogRequest
    region = "us-west-2"
    // ...other configuration settings...
}

s3.listBuckets { ... }
s3.listObjectsV2 { ... }
```

以下代码段显示了如何覆盖单个`listObjectV2`操作的配置。

```
s3.withConfig {
    region = "eu-central-1"
}.use { overriddenS3 ->
    overriddenS3.listObjectsV2 { ... }
}
```

`s3`客户端上的操作调用使用创建客户端时指定的原始配置。其配置包括[请求日志](logging.md#sdk-log-mode)`us-west-2 region`和区域配置。

`overriddenS3`客户端上的`listObjectsV2`调用使用与原始`s3`客户端相同的设置，但区域除外，现在`eu-central-1`是。

## 被覆盖的客户端的生命周期
被覆盖的客户端生命周期

在前面的示例中，`s3`客户端和`overriddenS3`客户端彼此独立。只要操作保持打开状态，就可以在任一客户端上调用。每个都使用单独的配置，但它们可以共享底层资源（例如 HTTP 引擎），除非这些资源也被覆盖。

您可以分别关闭配置被覆盖的客户端和原始客户端。在关闭原始客户端之前或之后，您可以关闭配置被覆盖的客户端。除非您需要长时间使用配置被覆盖的客户端，否则我们建议您使用该方法来封装其生命周期。`use`该`use`方法可确保在发生异常时关闭客户端。

## 客户之间共享的资源
共享的 资源

使用创建服务客户端时`withConfig`，它可能会与原始客户机共享资源。相比之下，当您使用 [FromEnvironMen](creating-clients.md#loading-from-the-environment) t 创建客户机或[对其进行明确配置](creating-clients.md#programmatic-config)时，该客户端将使用独立的资源。诸如 HTTP 引擎和凭证提供程序之类的资源是共享的，除非它们在区块中被覆盖。`withConfig`

由于每个客户机的生命周期是独立的，因此共享资源将保持开放和可用状态，直到最后一个客户机关闭。因此，当您不再需要被覆盖的服务客户端时，务必将其关闭。这样可以防止共享资源保持打开状态并消耗系统资源，例如内存、连接和 CPU 周期。

以下示例显示了共享资源和独立资源。

`s3`和`overriddenS3`客户端共享相同的凭证提供程序实例，包括其缓存配置。如果`s3`客户端调用的缓存值仍然是最新的，则通过`overriddenS3`重用凭证发出的调用。

 两个客户端之间不共享 HTTP 引擎。每个客户端都有一个独立的 HTTP 引擎，因为它在调用中被覆盖。`withConfig`

```
val s3 = S3Client.fromEnvironment {
    region = "us-west-2"
    credentialsProvider = CachedCredentialsProvider(CredentialsProviderChain(...))
    httpClientEngine = OkHttpEngine { ... }
}

s3.listBuckets { ... }

s3.withConfig {
    httpClientEngine = CrtHttpEngine { ... }
}.use { overriddenS3 ->
    overriddenS3.listObjectsV2 { ... }
}
```