

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 疑難排解常見問答集
<a name="troubleshooting"></a>

當您 AWS SDK for Java 2.x 在應用程式中使用 時，您可能會遇到本主題中列出的執行時間錯誤。使用這裡的建議來協助您找出根本原因並解決錯誤。

## 如何修正「`java.net.SocketException`：連線重設」或「伺服器無法完成回應」錯誤？
<a name="faq-socketexception"></a>

連線重設錯誤表示您的主機 AWS 服務、 或任何中介方 （例如 NAT 閘道、代理、負載平衡器） 在請求完成之前關閉連線。由於有許多原因，尋找解決方案需要您了解連線關閉的原因。下列項目通常會導致連線關閉。
+ **連線處於非作用中狀態。 **這在串流操作中很常見，其中資料在一段時間內不會寫入或傳出線路，因此中介方會偵測連線是否無效並關閉它。若要避免這種情況，請確定您的應用程式主動下載或上傳資料。
+ **您已關閉 HTTP 或 SDK 用戶端。**確保在使用資源時不要關閉資源。
+ **設定錯誤的代理。**嘗試略過您已設定的任何代理，以查看它是否修正了問題。如果此問題得到修正，代理會因某些原因而關閉您的連線。研究您的特定代理，以判斷其關閉連線的原因。

如果您無法識別問題，請嘗試在網路的用戶端邊緣 （例如，在您控制的任何代理之後） 為受影響的連線執行 TCP 傾印。

如果您看到 AWS 端點正在傳送 `TCP RST`（重設）[，請聯絡受影響的服務](https://aws.amazon.com/contact-us/)，看看他們是否可以判斷重設的原因。準備好提供問題發生時的請求 IDs 和時間戳記。 AWS 支援團隊也可能受益於[線路日誌](logging-slf4j.md#sdk-java-logging-verbose)，該日誌確切顯示應用程式傳送和接收的位元組，以及傳送和接收時間。

## 如何修正「連線逾時」？
<a name="faq-connection-timeout"></a>

連線逾時錯誤表示您的主機 AWS 服務、 或任何中介方 （例如 NAT 閘道、代理、負載平衡器） 無法在設定的連線逾時內與伺服器建立新的連線。以下項目說明此問題的常見原因。
+ **設定的連線逾時太低。**根據預設， 中的連線逾時為 2 秒 AWS SDK for Java 2.x。如果您設定太低的連線逾時，您可能會收到此錯誤。如果您只進行區域內呼叫，則建議的連線逾時為 1 秒；如果您提出跨區域請求，則建議的連線逾時為 3 秒。
+ **設定錯誤的代理。**嘗試略過您設定的任何代理，以查看它是否修正了問題。如果這修正了問題，代理就是連線逾時的原因。研究您的特定代理，以判斷發生這種情況的原因

如果您無法識別問題，請嘗試在網路的用戶端邊緣 （例如，在您控制的任何代理之後） 為受影響的連線執行 TCP 傾印，以調查任何網路問題。

## 如何修正「`java.net.SocketTimeoutException`：讀取逾時」？
<a name="faq-socket-timeout"></a>

讀取逾時錯誤表示 JVM 嘗試從基礎作業系統讀取資料，但資料並未在透過 SDK 設定的時間內傳回。如果作業系統、 AWS 服務或任何中介方 （例如 NAT 閘道、代理、負載平衡器） 無法在 JVM 預期的時間內傳送資料，就會發生此錯誤。由於有許多原因，尋找解決方案需要您了解未傳回資料的原因。

嘗試在網路的用戶端邊緣 （例如，在您控制的任何代理之後） 為受影響的連線執行 TCP 傾印。

如果您看到 AWS 端點正在傳送 `TCP RST`（重設）[，請聯絡受影響的服務](https://aws.amazon.com/contact-us/)。準備好提供問題發生時的請求 IDs 和時間戳記。 AWS 支援團隊也可能受益於[線路日誌](logging-slf4j.md#sdk-java-logging-verbose)，該日誌確切顯示應用程式傳送和接收的位元組，以及傳送和接收時間。

## 如何修正「無法執行 HTTP 請求：等待從集區連線逾時」錯誤？
<a name="faq-pool-timeout"></a>

此錯誤表示請求無法在指定的最長時間內從集區取得連線。若要疑難排解問題，建議您[啟用 SDK 用戶端指標](metrics.md)，將指標發佈至 Amazon CloudWatch。HTTP 指標有助於縮小根本原因範圍。以下項目說明此錯誤的常見原因。
+ **連線洩漏。**您可以檢查 `LeasedConcurrency` 、 `AvailableConcurrency`和 `MaxConcurrency`指標來調查此問題。如果 `LeasedConcurrency` 增加，直到達到 `MaxConcurrency` 但永遠不會減少，則可能會發生連線洩漏。洩漏的常見原因是串流操作未關閉，例如 S3 `getObject`方法。我們建議您的應用程式盡快從輸入串流讀取所有資料[，並在之後關閉輸入串流](best-practices.md#bestpractice2)。下圖顯示連線洩漏的 SDK 指標可能看起來像什麼。  
![\[顯示可能連線洩漏的 CloudWatch 指標螢幕擷取畫面。\]](http://docs.aws.amazon.com/zh_tw/sdk-for-java/latest/developer-guide/images/JavaDevGuide-connection-leak-metrics-chart.png)
+ **連線集區匱乏。 **如果您的請求率太高，且已設定的連線集區大小無法滿足請求需求，就會發生這種情況。預設連線集區大小為 50，當集區中的連線達到上限時，HTTP 用戶端會將傳入請求排入佇列，直到連線可用為止。下圖顯示連線集區匱乏的 SDK 指標可能看起來像什麼。  
![\[CloudWatch 指標的螢幕擷取畫面，顯示連線集區匱乏的外觀。\]](http://docs.aws.amazon.com/zh_tw/sdk-for-java/latest/developer-guide/images/JavaDevGuide-connection-pool-starvation-chart.png)

  若要緩解此問題，請考慮採取下列任何動作。
  + 增加連線集區大小，
  + 增加取得逾時。
  + 減慢請求率。

  透過增加連線數量上限，用戶端輸送量可以增加 （除非網路界面已充分利用）。不過，您最終可以對程序使用的檔案描述項數量達到操作系統限制。如果您已經完全使用網路界面，或無法進一步增加連線計數，請嘗試增加取得逾時。隨著增加，您可以在逾時之前獲得請求取得連線的額外時間。如果連線未釋出，後續請求仍會逾時。

  如果您無法使用前兩個機制修正問題，請嘗試以下選項來降低請求率。
  + 平滑您的請求，讓大型流量爆增不會讓用戶端超載。
  + 呼叫 時更有效率 AWS 服務。
  + 增加傳送請求的主機數量。
+ **I/O 執行緒太忙碌。**這僅適用於使用非同步 SDK 用戶端搭配 的情況[https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/http/nio/netty/NettyNioAsyncHttpClient.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/http/nio/netty/NettyNioAsyncHttpClient.html)。如果`AvailableConcurrency`指標不低，表示集區中有可用的連線，但`ConcurrencyAcquireDuration`很高，可能是因為 I/O 執行緒無法處理請求。請確定您不會傳遞`Runnable:run`為[未來的完成執行器，](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/client/config/SdkAdvancedAsyncClientOption.html#FUTURE_COMPLETION_EXECUTOR)並在回應未來的完成鏈中執行耗時的任務，因為這可能會封鎖 I/O 執行緒。如果不是這種情況，請考慮使用 `[eventLoopGroupBuilder](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/http/nio/netty/NettyNioAsyncHttpClient.Builder.html#eventLoopGroupBuilder(software.amazon.awssdk.http.nio.netty.SdkEventLoopGroup.Builder))`方法增加 I/O 執行緒的數量。做為參考，`NettyNioAsyncHttpClient`執行個體的預設 I/O 執行緒數量是主機 CPU 核心數量的兩倍。
+ **高 TLS 交握延遲。**如果您的`AvailableConcurrency`指標接近 0 `LeasedConcurrency` 且低於 `MaxConcurrency`，可能是因為 TLS 交握延遲很高。下表顯示 SDK 指標在高 TLS 交握延遲時可能看起來像什麼。  
![\[可能表示高 TLS 交握延遲的 CloudWatch 指標螢幕擷取畫面。\]](http://docs.aws.amazon.com/zh_tw/sdk-for-java/latest/developer-guide/images/JavaDevGuide-high-tls-latency-chart.png)

  對於不是以 CRT 為基礎的 Java 開發套件提供的 HTTP 用戶端，請嘗試啟用 [TLS 日誌](security-java-tls.md)來疑難排解 TLS 問題。對於以 CRT 為基礎的 HTTP AWS 用戶端，請嘗試啟用 [AWS CRT 日誌](logging-slf4j.md#sdk-java-logging-verbose)。如果您看到 AWS 端點似乎需要很長的時間來執行 TLS 交握，您應該[聯絡受影響的服務](https://aws.amazon.com/contact-us/)。

## 如何修正 `NoClassDefFoundError`、 `NoSuchMethodError`或 `NoSuchFieldError`？
<a name="faq-classpath-errors"></a>

`NoClassDefFoundError` 表示無法在執行時間載入類別。此錯誤的兩個最常見原因是：
+ 類別不存在於 classpath 中，因為 JAR 遺失或 JAR 的錯誤版本位於 classpath 上。
+ 類別無法載入，因為其靜態初始化器擲回例外狀況。

同樣地， `NoSuchMethodError`和 `NoSuchFieldError`通常由不相符的 JAR 版本造成。我們建議您執行下列步驟。

1. **檢查您的相依性**，以確保您使用*所有 SDK jar 的相同版本*。類別、方法或欄位找不到的最常見原因是當您升級至新的用戶端版本，但您繼續使用舊的「共用」開發套件相依版本時。新的用戶端版本可能會嘗試使用僅存在於較新「共用」 SDK 相依性的類別。嘗試執行 `mvn dependency:tree`或 `gradle dependencies`（針對 Gradle) 以確認 SDK 程式庫版本完全相符。為了避免未來完全發生此問題，我們建議您使用 [BOM （物料清單）](setup-project-maven.md#sdk-as-dependency) 來管理 SDK 模組版本。

   下列範例顯示混合 SDK 版本的範例。

   ```
   [INFO] +- software.amazon.awssdk:dynamodb:jar:2.20.00:compile
   [INFO] |  +- software.amazon.awssdk:aws-core:jar:2.13.19:compile
   [INFO] +- software.amazon.awssdk:netty-nio-client:jar:2.20.00:compile
   ```

   的版本`dynamodb`為 2.20.00，而 的版本`aws-core`為 2.13.19。`aws-core` 成品版本也應該是 2.20.00。

1. 儘**早檢查日誌中的陳述**式，以查看類別是否因為靜態初始化失敗而無法載入。類別第一次無法載入時，可能會擲回不同、更實用的例外狀況，指定無法載入類別*的原因*。此可能有用的例外狀況只會發生一次，因此之後的日誌陳述式只會報告找不到 類別。

1. **檢查您的部署程序**，以確保其與您的應用程式一起實際部署所需的 JAR 檔案。您可能會使用正確的版本建置 ，但為您的應用程式建立 classpath 的程序會排除必要的相依性。

## 如何修正「`SignatureDoesNotMatch`」錯誤或「我們計算的請求簽章與您提供的簽章不符」錯誤？
<a name="faq-signature-does-not-match-error"></a>

`SignatureDoesNotMatch` 錯誤表示 產生的簽章 適用於 Java 的 AWS SDK 和 產生的簽章 AWS 服務 不相符。以下項目說明潛在原因。
+ 代理或中介方會修改請求。例如，代理或負載平衡器可能會修改 SDK 簽署的標頭、路徑或查詢字串。
+ 當每個 產生要簽署的字串時，服務和 SDK 的編碼方式會有所不同。

若要偵錯此問題，建議您啟用 SDK 的[偵錯記錄](logging-slf4j.md#sdk-debug-level-logging)。嘗試重現錯誤，並尋找 SDK 產生的正式請求。在 日誌中，正式請求會標示為 `AWS4 Canonical Request: ...`，而要簽署的字串會標示為 `AWS4 String to sign: ...` 。

如果您無法啟用偵錯，例如，因為它只能在生產環境中重現，請將邏輯新增至應用程式，以便在發生錯誤時記錄請求的相關資訊。然後，您可以使用該資訊，在啟用偵錯記錄的整合測試中，嘗試在生產環境外複寫錯誤。

在您收集正式請求和要簽署的字串之後，請將它們與 [AWS Signature 第 4 版規格](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_aws-signing.html)進行比較，以判斷 SDK 產生要簽署的字串是否存在任何問題。如果似乎有問題，您可以建立 [GitHub 錯誤報告](https://github.com/aws/aws-sdk-java-v2/issues/new/choose)給 適用於 Java 的 AWS SDK。

如果沒有顯示錯誤，您可以將 SDK 的字串與字串進行比較，以簽署一些 AWS 服務 傳回 作為失敗回應的一部分 （例如 Amazon S3)。如果無法使用，您應該[聯絡受影響的服務](https://aws.amazon.com/contact-us/)，查看產生哪些正式請求和字串來簽署它們以供比較。這些比較有助於識別可能已修改請求的中介方，或編碼服務與用戶端之間的差異。

如需簽署請求的更多背景資訊，請參閱 AWS Identity and Access Management 《 使用者指南》中的[簽署 AWS API 請求](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_aws-signing.html)。

**Example 正式請求的**  

```
PUT
/Example-Bucket/Example-Object
partNumber=19&uploadId=string
amz-sdk-invocation-id:f8c2799d-367c-f024-e8fa-6ad6d0a1afb9
amz-sdk-request:attempt=1; max=4
content-encoding:aws-chunked
content-length:51
content-type:application/octet-stream
host:xxxxx
x-amz-content-sha256:STREAMING-UNSIGNED-PAYLOAD-TRAILER
x-amz-date:20240308T034733Z
x-amz-decoded-content-length:10
x-amz-sdk-checksum-algorithm:CRC32
x-amz-trailer:x-amz-checksum-crc32
```

**Example 要簽署的字串**  

```
AWS4-HMAC-SHA256
20240308T034435Z
20240308/us-east-1/s3/aws4_request
5f20a7604b1ef65dd89c333fd66736fdef9578d11a4f5d22d289597c387dc713
```

## 如何修正「`java.lang.IllegalStateException`：連線集區關閉」錯誤？
<a name="faq-connection-pool-shutdown-exception"></a>

此錯誤表示基礎 Apache HTTP 連線集區已關閉。以下項目說明潛在原因。
+ **SDK 用戶端已提早關閉。 **開發套件只會在關聯的用戶端關閉時關閉連線集區。確保在使用資源時不要關閉資源。
+ **`java.lang.Error`已擲出 。**`OutOfMemoryError` 導致 Apache HTTP 連線集區[關閉](https://github.com/apache/httpcomponents-client/blob/6a741b4f8f23e6c5c7cc42c36c2acabfac19c3d6/httpclient/src/main/java/org/apache/http/impl/execchain/MainClientExec.java#L368)等錯誤。檢查您的日誌是否有錯誤堆疊追蹤。也請檢閱您的程式碼，找出它捕獲 `Throwable`或 的位置，`Error`但會吞下防止錯誤浮現的輸出。如果您的程式碼未報告錯誤，請重寫程式碼，以便記錄資訊。記錄的資訊有助於判斷錯誤的根本原因。
+ **您嘗試使用關閉`DefaultCredentialsProvider#create()`後從 傳回的登入資料提供者**。 [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/auth/credentials/DefaultCredentialsProvider.html#create()](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/auth/credentials/DefaultCredentialsProvider.html#create())會傳回單一執行個體，因此，如果已關閉且您的程式碼呼叫 `resolveCredentials`方法，則會在快取的登入資料 （或權杖） 過期後擲回例外狀況。

  檢查您的程式碼是否有`DefaultCredentialsProvider`關閉 的位置，如下列範例所示。
  + 呼叫 來關閉單一執行個體 `DefaultCredentialsProvider#close().`

    ```
    DefaultCredentialsProvider defaultCredentialsProvider = DefaultCredentialsProvider.create(); // Singleton instance returned.
    AwsCredentials credentials = defaultCredentialsProvider.resolveCredentials();
    
    // Make calls to AWS 服務.
    
    defaultCredentialsProvider.close();  // Explicit close.
    
    // Make calls to AWS 服務.
    
    // After the credentials expire, either of the following calls eventually results in a "Connection pool shut down" exception.
    credentials = defaultCredentialsProvider.resolveCredentials();
    // Or
    credentials = DefaultCredentialsProvider.create().resolveCredentials();
    ```
  + 在 try-with-resources 區塊`DefaultCredentialsProvider#create()`中調用 。

    ```
    try (DefaultCredentialsProvider defaultCredentialsProvider = DefaultCredentialsProvider.create()) {
        AwsCredentials credentials = defaultCredentialsProvider.resolveCredentials();
        
        // Make calls to AWS 服務.
    
    } // After the try-with-resources block exits, the singleton DefaultCredentialsProvider is closed.
    
    // Make calls to AWS 服務.
    
    DefaultCredentialsProvider defaultCredentialsProvider = DefaultCredentialsProvider.create(); // The closed singleton instance is returned.
    // If the credentials (or token) has expired, the following call results in the error.
    AwsCredentials credentials = defaultCredentialsProvider.resolveCredentials();
    ```

  `DefaultCredentialsProvider.builder().build()` 如果您的程式碼已關閉單一執行個體，而且您需要使用 解析登入資料，請呼叫 來建立新的非單一執行個體`DefaultCredentialsProvider`。

## 如何修正「無法從鏈結 AwsCredentialsProviderChain 中的任何供應商載入登入資料」？
<a name="faq-credentials-provider-chain"></a>

此錯誤表示 AWS SDK for Java 2.x 無法透過預設 AWS 登入資料提供者鏈結中的任何登入資料提供者找到有效的登入資料。軟體開發套件會自動以特定順序搜尋登入資料，當鏈結中的所有供應商無法提供有效的登入資料時，就會發生此錯誤。

完整的錯誤訊息通常如下所示 （新增行尾和縮排以提高可讀性）：

```
Unable to load credentials from any of the providers in the chain AwsCredentialsProviderChain(
    credentialsProviders=[
        SystemPropertyCredentialsProvider(),
        EnvironmentVariableCredentialsProvider(), 
        WebIdentityTokenCredentialsProvider(), 
        ProfileCredentialsProvider(profileName=default, profileFile=ProfileFile(sections=[])), 
        ContainerCredentialsProvider(), 
        InstanceProfileCredentialsProvider()
    ]) : [
        SystemPropertyCredentialsProvider(): Unable to load credentials from system settings.
        Access key must be specified either via environment variable (AWS_ACCESS_KEY_ID) 
        or system property (aws.accessKeyId)., 

        EnvironmentVariableCredentialsProvider(): Unable to load credentials from system settings. 
        Access key must be specified either via environment variable (AWS_ACCESS_KEY_ID) 
        or system property (aws.accessKeyId)., 

        WebIdentityTokenCredentialsProvider(): To use web identity tokens, the 'sts' service module 
        must be on the class path., 

        ProfileCredentialsProvider(profileName=default, profileFile=ProfileFile(sections=[])): 
        Profile file contained no credentials for profile 'default': ProfileFile(sections=[]), 

        ContainerCredentialsProvider(): Cannot fetch credentials from container - neither 
        AWS_CONTAINER_CREDENTIALS_FULL_URI or AWS_CONTAINER_CREDENTIALS_RELATIVE_URI environment 
        variables are set., 

        InstanceProfileCredentialsProvider(): Failed to load credentials from IMDS.]
```

### 常見原因和解決方案
<a name="faq-cred-provider-chain-common-causes-and-solutions"></a>

#### 檢閱您的登入資料組態
<a name="faq-cred-provider-chain-check-config"></a>

當您使用預設登入資料提供者 （透過呼叫 `ServiceClient.create()`而不明確設定登入資料） 時，軟體開發套件會依特定順序搜尋登入資料。檢閱[預設登入資料提供者鏈結的運作方式](credentials-chain.md)，以了解 SDK 檢查的登入資料來源和順序。

請確定您打算使用的登入資料組態方法已在您的環境中正確設定：

##### 對於 Amazon EC2 執行個體
<a name="faq-cred-check-ec2"></a>
+ **檢查 IAM 角色：**確認 IAM 角色已連接至您的執行個體。
+ **間歇 IMDS 故障：**如果您遇到間歇性故障 （通常持續數百毫秒），這通常表示暫時性網路問題到達執行個體中繼資料服務 (IMDS)。

  解決方案：
  + 啟用[偵錯記錄](logging-slf4j.md#sdk-debug-level-logging)，以分析故障的時間和頻率
  + 考慮在您的應用程式中實作重試邏輯，以解決登入資料相關的故障
  + 檢查執行個體與 IMDS 端點之間的網路連線問題

##### 對於容器環境
<a name="faq-cred-check-container-env"></a>

確認任務角色 (Amazon ECS) 或服務帳戶 (Amazon EKS) 已設定，且已設定必要的環境變數。

##### 針對本機開發
<a name="faq-cred-check-local-dev"></a>

檢查環境變數、登入資料檔案或 IAM Identity Center 組態是否已就緒。

##### 針對 Web 聯合身分
<a name="faq-cred-check-web-id-federation"></a>
+ **驗證組態：**驗證 Web 身分字符檔案是否存在，以及是否已設定必要的環境變數。
+ **缺少 STS 模組相依性：**如果您看到錯誤 `To use web identity tokens, the 'sts' service module must be on the class path`，則需要新增 STS 模組做為相依性。這在使用 Amazon EKS Pod Identity 或其他 Web 身分字符身分驗證時很常見。

  解決方案：將 STS 模組新增至您的專案相依性：
  + 

    ```
    <dependency>
        <groupId>software.amazon.awssdk</groupId>
        <artifactId>sts</artifactId>
    </dependency>
    ```

    對於某些服務，您可能還需要 `aws-query-protocol` 相依性：

    ```
    <dependency>
        <groupId>software.amazon.awssdk</groupId>
        <artifactId>aws-query-protocol</artifactId>
    </dependency>
    ```

#### 網路或代理連線問題
<a name="faq-credentials-provider-chain-network-issues"></a>

如果您在登入資料提供者鏈中看到`Connection refused`錯誤，這通常表示 SDK 嘗試到達 AWS 端點時的網路連線問題。

**解決方案：**
+ 如果您使用代理伺服器，請驗證代理組態
+ 檢查您的網路是否允許對外 HTTPS 連線至 AWS 端點
+ 啟用[偵錯記錄](logging-slf4j.md#sdk-debug-level-logging)以查看詳細的連線嘗試
+ 使用 等工具測試連線能力`curl`，以驗證端點 AWS 的網路存取