

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

# 搭配 Amazon SQS 使用 APIs
<a name="sqs-working-with-apis"></a>

本主題提供建構 Amazon SQS 端點、使用 GET 和 POST 方法提出查詢 API 請求，以及使用批次 API 動作的相關資訊。如需 Amazon SQS [動作](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_Operations.html) (包括參數、錯誤、範例和[資料類型](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_Types.html)) 的詳細資訊，請參閱《[Amazon Simple Queue Service API 參考](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/)》**。

您若是使用各種程式設計語言存取 Amazon SQS，還可以利用 [AWS 開發套件](https://aws.amazon.com/tools/#sdk)提供的下列自動化功能：
+ 加密簽署服務請求
+ 重試請求
+ 處理錯誤回應

如需詳細資訊，請參閱[搭配 SDK 使用 Amazon SQS AWS](sdk-general-information-section.md)。

如需命令列工具的相關資訊，請參閱 [https://docs.aws.amazon.com/cli/latest/reference/sqs/index.html](https://docs.aws.amazon.com/cli/latest/reference/sqs/index.html)以及 [https://docs.aws.amazon.com/powershell/latest/reference/](https://docs.aws.amazon.com/powershell/latest/reference/)中的 Amazon SQS 章節。

**具有 AWS JSON 通訊協定的 Amazon SQS API APIs **

Amazon SQS 使用 AWS JSON 通訊協定做為指定 [AWS SDK 版本](sqs-json-faqs.md#json-protocol-getting-started)上所有 Amazon SQS APIs 的傳輸機制。 AWS JSON 通訊協定提供更高的輸送量、更低的延遲和更快application-to-application通訊。相較於 AWS 查詢通訊協定， AWS JSON 通訊協定在請求和回應的序列化/還原序列化方面更有效率。如果您仍然偏好搭配 SQS APIs 使用 AWS 查詢通訊協定，請參閱 [Amazon SQS APIs 中使用的 AWS JSON 通訊協定支援哪些語言？](sqs-json-faqs.md#json-protocol-supported-languages) 以取得支援 Amazon SQS AWS 查詢通訊協定的 AWS SDK 版本。

Amazon SQS 使用 AWS JSON 通訊協定，在 AWS SDK 用戶端 （例如 Java、Python、Golang、JavaScript) 和 Amazon SQS 伺服器之間進行通訊。Amazon SQS API 操作的 HTTP 請求接受 JSON 格式的輸入。系統會執行 Amazon SQS 作業，執行回應會以 JSON 格式傳回 SDK 用戶端。相較於 AWS 查詢， AWS JSON 在用戶端和伺服器之間傳輸資料更為簡單、快速且更有效率。
+ AWS JSON 通訊協定可做為 Amazon SQS 用戶端和伺服器之間的中介裝置。
+ 伺服器不了解建立 Amazon SQS 操作的程式設計語言，但了解 AWS JSON 通訊協定。
+  AWS JSON 通訊協定使用 Amazon SQS 用戶端和伺服器之間的序列化 （將物件轉換為 JSON 格式） 和去序列化 （將 JSON 格式轉換為物件）。

如需使用 Amazon SQS 的 AWS JSON 通訊協定詳細資訊，請參閱 [Amazon SQS AWS JSON 通訊協定FAQs](sqs-json-faqs.md)。

AWS JSON 通訊協定可在指定的 [AWS SDK 版本](sqs-json-faqs.md#json-protocol-getting-started)上使用。若要查看跨語言變體的 SDK 版本和發行日期，請參閱《AWS 開發套件和工具參考指南》**中的 [AWS 開發套件及工具版本支援對照表](https://docs.aws.amazon.com/sdkref/latest/guide/version-support-matrix.html)

# 在 Amazon SQS 中使用 AWS JSON 通訊協定提出查詢 API 請求
<a name="sqs-making-api-requests-json"></a>

本主題說明如何建構 Amazon SQS 端點、提出 POST 請求，以及解譯回應。

**注意**  
AWS 大多數語言變體都支援 JSON 通訊協定。如需支援的語言變體完整清單，請參閱 [Amazon SQS APIs 中使用的 AWS JSON 通訊協定支援哪些語言？](sqs-json-faqs.md#json-protocol-supported-languages)。

## 建構端點
<a name="sqs-api-constructing-endpoints-json"></a>

為了使用 Amazon SQS 佇列，您必須建構端點。如需 Amazon SQS 端點的相關資訊，請參閱 *Amazon Web Services 一般參考* 中的以下頁面：
+ [區域端點](https://docs.aws.amazon.com/general/latest/gr/rande.html#regional-endpoints)
+ [Amazon Simple Queue Service 端點和配額](https://docs.aws.amazon.com/general/latest/gr/sqs-service)

每個 Amazon SQS 端點都是獨立的。例如，若有兩個佇列同樣名為 *MyQueue*，其中一個佇列具有端點 `sqs.us-east-2.amazonaws.com`，而另一個佇列具有端點 `sqs.eu-west-2.amazonaws.com`，這兩個佇列便不會相互共享任何資料。

以下是某個端點提出請求建立佇列的範例。

```
POST / HTTP/1.1
Host: sqs.us-west-2.amazonaws.com
X-Amz-Target: AmazonSQS.CreateQueue
X-Amz-Date: <Date>
Content-Type: application/x-amz-json-1.0
Authorization: <AuthParams>
Content-Length: <PayloadSizeBytes>
Connection: Keep-Alive 
{
    "QueueName":"MyQueue",
    "Attributes": {
        "VisibilityTimeout": "40"
    },
    "tags": {
        "QueueType": "Production"
    }
}
```

**注意**  
佇列名稱和佇列 URL 區分大小寫。  
*`AUTHPARAMS`* 的結構取決於 API 請求的簽署。如需詳細資訊，請參閱《*Amazon Web Services 一般參考*》中的[簽署 AWS API 請求](https://docs.aws.amazon.com/general/latest/gr/signing_aws_api_requests.html)。

## 提出 POST 請求
<a name="structure-post-request"></a>

Amazon SQS POST 請求是以 HTTP 請求本文的形式傳送查詢參數。

以下是 `X-Amz-Target` 設定為 `AmazonSQS.<operationName>` 的 HTTP 標頭範例，以及 `Content-Type` 設定為 `application/x-amz-json-1.0` 的 HTTP 標頭。

```
POST / HTTP/1.1
Host: sqs.<region>.<domain>
X-Amz-Target: AmazonSQS.SendMessage
X-Amz-Date: <Date>
Content-Type: application/x-amz-json-1.0
Authorization: <AuthParams>
Content-Length: <PayloadSizeBytes>
Connection: Keep-Alive 
{
    "QueueUrl": "https://sqs.<region>.<domain>/<awsAccountId>/<queueName>/",
    "MessageBody": "This is a test message"
}
```

這個 HTTP POST 請求會將訊息發佈至 Amazon SQS 佇列。

**注意**  
這兩個 HTTP 標頭 `X-Amz-Target` 和 `Content-Type` 是必要的。  
視用戶端的 HTTP 版本而定，HTTP 用戶端可能會對 HTTP 請求增加其他項目。

# 解譯 Amazon SQS JSON API 回應
<a name="sqs-json-api-responses"></a>

當您將請求傳送至 Amazon SQS 時，它會傳回包含結果的 JSON 回應。回應結構取決於您使用的 API 動作。

若要了解這些回應的詳細資訊，請參閱：
+ *Amazon Simple Queue Service API 參考中* [API 動作中的特定 API 動作](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_Operations.html) 
+ [Amazon SQS AWS JSON 通訊協定FAQs](sqs-json-faqs.md)

## 成功的 JSON 回應結構
<a name="sqs-json-api-successful-response-structure"></a>

如果請求成功，則主要回應元素是 `x-amzn-RequestId`，其中包含請求的通用唯一標識符（UUID）以及其他附加回應欄位。例如，下列 [https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_CreateQueue.html](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_CreateQueue.html) 回應包含 `QueueUrl` 欄位，此欄位又包含建立的佇列的 URL。

```
HTTP/1.1 200 OK
x-amzn-RequestId: <requestId>
Content-Length: <PayloadSizeBytes>
Date: <Date>
Content-Type: application/x-amz-json-1.0
{
    "QueueUrl":"https://sqs.us-east-1.amazonaws.com/111122223333/MyQueue"
}
```

## JSON 錯誤回應結構
<a name="sqs-api-error-response-structure"></a>

如果請求未成功，Amazon SQS 會傳回主要回應，包括 HTTP 標頭和本文。

在 HTTP 標頭中，`x-amzn-RequestId` 包含請求的 UUID。`x-amzn-query-error` 包含兩項資訊：錯誤類型，以及錯誤是否為生產者或取用者錯誤。

在回應本文中，`"__type"` 指出其他錯誤詳細資訊，而 `Message` 則以可讀格式指出錯誤狀況。

以下為 JSON 格式的錯誤回應範例：

```
HTTP/1.1 400 Bad Request
x-amzn-RequestId: 66916324-67ca-54bb-a410-3f567a7a0571
x-amzn-query-error: AWS.SimpleQueueService.NonExistentQueue;Sender
Content-Length: <PayloadSizeBytes>
Date: <Date>
Content-Type: application/x-amz-json-1.0
{
    "__type": "com.amazonaws.sqs#QueueDoesNotExist",
    "message": "The specified queue does not exist."
}
```

# Amazon SQS AWS JSON 通訊協定FAQs
<a name="sqs-json-faqs"></a>

本主題涵蓋搭配 Amazon SQS 使用 AWS JSON 通訊協定的常見問題。

## 什麼是 AWS JSON 通訊協定，它與現有的 Amazon SQS API 請求和回應有何不同？
<a name="json-protocol-what-is"></a>

JSON 是用於異質系統之間通訊的最廣泛使用和接受的佈線方法之一。Amazon SQS 使用 JSON 在 AWS SDK 用戶端 (例如 Java、Python、Golang、JavaScript) 和 Amazon SQS 伺服器之間進行通訊。Amazon SQS API 操作的 HTTP 請求接受 JSON 格式的輸入。系統會執行 Amazon SQS 操作，而回應會以 JSON 格式傳回 SDK 用戶端。與 AWS 查詢相比，JSON 可更有效率地在用戶端和伺服器之間傳輸資料。
+ Amazon SQS AWS JSON 通訊協定充當 Amazon SQS 用戶端和伺服器之間的中介裝置。
+ 伺服器不了解建立 Amazon SQS 操作的程式設計語言，但了解 AWS JSON 通訊協定。
+ Amazon SQS AWS JSON 通訊協定使用 Amazon SQS 用戶端和伺服器之間的序列化 （將物件轉換為 JSON 格式） 和還原序列化 （將 JSON 格式轉換為物件）。

## 如何開始使用 Amazon SQS 的 AWS JSON 通訊協定？
<a name="json-protocol-getting-started"></a>

若要開始使用最新的 AWS SDK 版本，以實現 Amazon SQS 的更快傳訊，請將您的 AWS SDK 升級到指定的版本或任何後續版本。若要進一步了解 SDK 用戶端，請參閱下表中的「指南」資料欄。

以下是 AWS JSON 通訊協定與 Amazon SQS APIs 搭配使用之不同語言版本的 SDK 版本清單：


| Language | SDK 用戶端儲存庫 | 必要的 SDK 用戶端版本 | 指南 | 
| --- | --- | --- | --- | 
|  C\$1\$1  |  [aws/aws-sdk-cpp](https://github.com/aws/aws-sdk-cpp)  |  [1.11.98](https://github.com/aws/aws-sdk-cpp/releases/tag/1.11.198)  |  [AWS 適用於 C\$1\$1 的 SDK](https://aws.amazon.com/sdk-for-cpp/)  | 
|  Golang 1.x  |  [aws/aws-sdk-go](https://github.com/aws/aws-sdk-go)  |  [v1.47.7](https://github.com/aws/aws-sdk-go/releases/tag/v1.47.7)  |  [AWS 適用於 Go 的 SDK](https://aws.amazon.com/sdk-for-go/)  | 
|  Golang 2.x  |  [aws/aws-sdk-go-v2](https://github.com/aws/aws-sdk-go-v2)  |  [v1.28.0](https://github.com/aws/aws-sdk-go-v2/blob/release-2023-11-09/service/sqs/CHANGELOG.md#v1270-2023-11-09)  |  [AWS 適用於 Go V2 的 SDK](https://aws.github.io/aws-sdk-go-v2/docs/)  | 
|  Java 1.x  |  [aws/aws-sdk-java](https://github.com/aws/aws-sdk-java)  |  [1.12.585](https://github.com/aws/aws-sdk-java/releases/tag/1.12.585)  |  [AWS 適用於 Java 的開發套件](https://aws.amazon.com/sdk-for-java/)  | 
|  Java 2.x  |  [aws/aws-sdk-java-v2](https://github.com/aws/aws-sdk-java-v2)  |  [2.21.19](https://github.com/aws/aws-sdk-java-v2/releases/tag/2.21.19)  |  [AWS 適用於 Java 的開發套件](https://aws.amazon.com/sdk-for-java/)  | 
|  JavaScript v2.x  |  [aws/aws-sdk-js](https://github.com/aws/aws-sdk-js)  |  [上的 JavaScript AWS](https://aws.amazon.com/developer/language/javascript/)  | 
|  JavaScript v3.x  |  [aws/aws-sdk-js-v3](https://github.com/aws/aws-sdk-js-v3)  |  [v3.447.0](https://github.com/aws/aws-sdk-js-v3/releases/tag/v3.447.0)  |  [上的 JavaScript AWS](https://aws.amazon.com/developer/language/javascript/)  | 
|  .NET  |  [aws/aws-sdk-net](https://github.com/aws/aws-sdk-net)  |  [3.7.681.0](https://github.com/aws/aws-sdk-net/releases/tag/3.7.681.0)  |  [AWS 適用於 .NET 的 SDK](https://aws.amazon.com/sdk-for-net/)  | 
|  PHP  |  [aws/aws-sdk-php](https://github.com/aws/aws-sdk-php)  |  [3.285.2](https://github.com/aws/aws-sdk-php/releases/tag/3.285.2)  |  [AWS 適用於 PHP 的 SDK](https://aws.amazon.com/sdk-for-php/)  | 
|  Python-boto3  |   [boto/boto3](https://github.com/boto/boto3)   |  [1.28.82](https://github.com/boto/boto3/releases/tag/1.28.82)  |  [AWS 適用於 Python 的 SDK (Boto3)](https://aws.amazon.com/sdk-for-python/)  | 
|  Python-botocore  |   [boto/botocore](https://github.com/boto/botocore/)   |  [1.31.82](https://github.com/boto/botocore/releases/tag/1.31.82)  |  [AWS 適用於 Python 的 SDK (Boto3)](https://aws.amazon.com/sdk-for-python/)  | 
|  awscli  |  [AWS CLI](https://github.com/aws/aws-cli)  |  [1.29.82](https://github.com/aws/aws-cli/releases/tag/1.29.82)  |  [AWS命令列介面](https://aws.amazon.com/cli/)  | 
|  Ruby  |  [aws/aws-sdk-ruby](https://github.com/aws/aws-sdk-ruby)  |  [1.67.0](https://rubygems.org/gems/aws-sdk-sqs/versions/1.67.0)  |  [AWS 適用於 Ruby 的 SDK](https://aws.amazon.com/sdk-for-ruby/)  | 

## 為我的 Amazon SQS 工作負載啟用 JSON 通訊協定有何風險？
<a name="json-protocol-risks"></a>

如果您使用 AWS SDK 的自訂實作或自訂用戶端和 AWS SDK 的組合來與產生以 AWS 查詢為基礎 （又稱為 XML 類型） 回應的 Amazon SQS 互動，則可能與 AWS JSON 通訊協定不相容。如果您遇到任何問題，請聯絡 AWS Support。

## 如果我已經使用最新的 AWS SDK 版本，但我的開放原始碼解決方案不支援 JSON，該怎麼辦？
<a name="json-protocol-sdk-version-open-source"></a>

您必須將 SDK 版本變更為您正在使用的版本之前的版本。[如何開始使用 Amazon SQS 的 AWS JSON 通訊協定？](#json-protocol-getting-started) 如需詳細資訊，請參閱 中列出的 AWS SDK 版本[如何開始使用 Amazon SQS 的 AWS JSON 通訊協定？](#json-protocol-getting-started)使用 Amazon SQS APIs的 JSON 線路通訊協定。如果您將 AWS SDK 變更為舊版，Amazon SQS APIs 將使用 AWS 查詢。

## Amazon SQS APIs 中使用的 AWS JSON 通訊協定支援哪些語言？
<a name="json-protocol-supported-languages"></a>

Amazon SQS 支援所有正式推出 AWS SDKs的語言變體 (GA)。目前，我們不支援 Kotlin、Rust 或 Swift。若要深入了解其他語言變體，請參閱[在 AWS上建立的工具](https://aws.amazon.com/developer/tools/)。

## Amazon SQS APIs 中使用的 AWS JSON 通訊協定支援哪些區域
<a name="json-protocol-supported-regions"></a>

Amazon SQS 在所有可使用 Amazon SQS 的[AWS 區域中](https://docs.aws.amazon.com/general/latest/gr/sqs-service.html)支援 AWS JSON 通訊協定。

## 使用 AWS JSON 通訊協定升級至 Amazon SQS 的指定 AWS SDK 版本時，可以預期哪些延遲改善？
<a name="json-protocol-upgrading-sdk"></a>

AWS 與 AWS 查詢通訊協定相比，JSON 通訊協定在序列化和還原序列化請求和回應方面更有效率。根據 5 KB 訊息承載 AWS 的效能測試，Amazon SQS 的 JSON 通訊協定可將end-to-end訊息處理延遲降低高達 23%，並減少應用程式用戶端 CPU 和記憶體使用量。

## AWS 查詢通訊協定是否會棄用？
<a name="query-protocol"></a>

AWS 查詢通訊協定將繼續受到支援。只要 AWS 軟體開發套件版本已設定任何先前版本，且該版本列於如何開始使用 Amazon SQS 的 JSON 通訊協定中，您就可以繼續使用 AWS 查詢通訊協定。 [AWS Amazon SQS](#json-protocol-getting-started)

## 哪裡可以找到 JSON AWS 通訊協定的詳細資訊？
<a name="json-protocol-more-info"></a>

您可以在 *Smithy* 文件中的 [AWS JSON 1.0 通訊協定](https://smithy.io/2.0/aws/protocols/aws-json-1_0-protocol.html)中找到有關 JSON 通訊協定的更多資訊。如需使用 AWS JSON 通訊協定的 Amazon SQS API 請求的詳細資訊，請參閱 [在 Amazon SQS 中使用 AWS JSON 通訊協定提出查詢 API 請求](sqs-making-api-requests-json.md)。

# 在 Amazon SQS 中使用查詢通訊協定提出 AWS 查詢 API 請求
<a name="sqs-making-api-requests-xml"></a>

本主題說明如何建構 Amazon SQS 端點、提出 GET 和 POST 請求，以及解譯回應。

## 建構端點
<a name="sqs-api-constructing-endpoints"></a>

為了能夠使用 Amazon SQS 佇列，您必須建構端點。如需 Amazon SQS 端點的相關資訊，請參閱 *Amazon Web Services 一般參考* 中的以下頁面：
+ [區域端點](https://docs.aws.amazon.com/general/latest/gr/rande.html#sqs_region)
+ [Amazon Simple Queue Service 端點和配額](https://docs.aws.amazon.com/general/latest/gr/sqs-service)

每個 Amazon SQS 端點都是獨立的。例如，若有兩個佇列同樣名為 *MyQueue*，其中一個佇列具有端點 `sqs.us-east-2.amazonaws.com`，而另一個佇列具有端點 `sqs.eu-west-2.amazonaws.com`，這兩個佇列便不會相互共享任何資料。

以下是某個端點提出請求建立佇列的範例。

```
https://sqs.eu-west-2.amazonaws.com/   
?Action=CreateQueue
&DefaultVisibilityTimeout=40
&QueueName=MyQueue
&Version=2012-11-05
&AUTHPARAMS
```

**注意**  
佇列名稱和佇列 URL 區分大小寫。  
*`AUTHPARAMS`* 的結構取決於 API 請求的簽署。如需詳細資訊，請參閱《*Amazon Web Services 一般參考*》中的[簽署 AWS API 請求](https://docs.aws.amazon.com/general/latest/gr/signing_aws_api_requests.html)。

## 提出 GET 請求
<a name="structure-get-request"></a>

Amazon SQS GET 請求的架構是由以下各部分組成的 URL：
+ **端點** - 請求所作用的資源 ([佇列名稱和 URL](sqs-queue-message-identifiers.md#queue-name-url))，例如：`https://sqs.us-east-2.amazonaws.com/123456789012/MyQueue`
+ **動作** – 要在端點上執行的[動作](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_Operations.html)。端點與動作之間用問號 (`?`) 隔開，例如：`?Action=SendMessage&MessageBody=Your%20Message%20Text`
+ **參數** - 任何請求的參數。每個參數以 ampersand (`&`) 分隔，例如： `&Version=2012-11-05&AUTHPARAMS`

以下是提出 GET 請求將訊息傳送至 Amazon SQS 佇列的範例。

```
https://sqs.us-east-2.amazonaws.com/123456789012/MyQueue
?Action=SendMessage&MessageBody=Your%20message%20text
&Version=2012-11-05
&AUTHPARAMS
```

**注意**  
佇列名稱和佇列 URL 區分大小寫。  
由於 GET 請求是 URL，所有參數值必須以 URL 編碼處理。由於 URL 不允許空格，每個空格都按 URL 編碼處理為 `%20` 為便於閱讀，範例的其餘部分並未以 URL 編碼處理。

## 提出 POST 請求
<a name="structure-post-request"></a>

Amazon SQS POST 請求是以 HTTP 請求本文的形式傳送查詢參數。

以下是 `Content-Type` 設為 `application/x-www-form-urlencoded` 的 HTTP 標頭範例。

```
POST /123456789012/MyQueue HTTP/1.1
Host: sqs.us-east-2.amazonaws.com
Content-Type: application/x-www-form-urlencoded
```

標頭後面接著的是 `[form-urlencoded](https://www.w3.org/MarkUp/html-spec/html-spec_8.html#SEC8.2)` GET 請求，其將傳送訊息至 Amazon SQS 佇列。每個參數之間用 `&` 符號隔開。

```
Action=SendMessage
&MessageBody=Your+Message+Text
&Expires=2020-10-15T12%3A00%3A00Z
&Version=2012-11-05
&AUTHPARAMS
```

**注意**  
僅需要有 `Content-Type` HTTP 標頭。`AUTHPARAMS` 的作用與 GET 請求的情形相同。  
視用戶端的 HTTP 版本而定，HTTP 用戶端可能會對 HTTP 請求增加其他項目。

# 解譯 Amazon SQS XML API 回應
<a name="sqs-xml-api-responses"></a>

當您將請求傳送至 Amazon SQS 時，它會傳回包含請求結果的 XML 回應。若要了解這些回應的結構和詳細資訊，請參閱《*Amazon Simple Queue Service API 參考》中的特定* [API 動作](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_Operations.html)。

## 成功的 XML 回應結構
<a name="sqs-api-successful-response-structure"></a>

若請求成功，主要回應元素將以請求的動作命名並加上 `Response` (例如 `ActionNameResponse`)。

此元素內含以下子元素：
+ **`ActionNameResult`** – 內含專屬於動作的元素。例如，`CreateQueueResult` 元素內含 `QueueUrl` 元素，後者又內含建立的佇列所在 URL。
+ **`ResponseMetadata`** – 包含 ，`RequestId`其會依序包含請求的通用唯一識別碼 (UUID)。

以下為 XML 格式的成功回應範例：

```
<CreateQueueResponse
   xmlns=https://sqs.us-east-2.amazonaws.com/doc/2012-11-05/
   xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance
   xsi:type=CreateQueueResponse>
   <CreateQueueResult>
      <QueueUrl>https://sqs.us-east-2.amazonaws.com/770098461991/queue2</QueueUrl>
   </CreateQueueResult>
   <ResponseMetadata>
      <RequestId>cb919c0a-9bce-4afe-9b48-9bdf2412bb67</RequestId>
   </ResponseMetadata>
</CreateQueueResponse>
```

## XML 錯誤回應結構
<a name="sqs-api-error-response-structure"></a>

若請求不成功，Amazon SQS 一律會傳回主要回應元素 `ErrorResponse`。此元素內含 `Error` 元素和 `RequestId` 元素。

`Error` 元素內含以下子元素：
+ **`Type`** – 指定此錯誤是來自生產者還是消費者。
+ **`Code`** – 指定錯誤的類型。
+ **`Message`** – 指定易讀格式的錯誤情況。
+ **`Detail`** – (選用) 指定關於錯誤的額外詳細資訊。

`RequestId` 元素內含請求的 UUID。

以下為 XML 格式的錯誤回應範例：

```
<ErrorResponse>
   <Error>
      <Type>Sender</Type>
      <Code>InvalidParameterValue</Code>
      <Message>
         Value (quename_nonalpha) for parameter QueueName is invalid.
         Must be an alphanumeric String of 1 to 80 in length.
      </Message>
   </Error>
   <RequestId>42d59b56-7407-4c4a-be0f-4c88daeea257</RequestId>
</ErrorResponse>
```

# 驗證 Amazon SQS 的請求
<a name="sqs-api-request-authentication"></a>

身分驗證是辨識與確認傳送請求的當事方身分的過程。在身分驗證的第一階段， 會 AWS 驗證生產者的身分，以及生產者是否已[註冊使用 AWS](https://aws.amazon.com/) （如需詳細資訊，請參閱 [步驟 1：建立 AWS 帳戶 和 IAM 使用者](sqs-setting-up.md#sqs-creating-aws-account))。接著，依照下列程序 AWS 刪除 ：

1. 生產者 (發送者) 必須取得必要的登入資料。

1. 生產者將請求和登入資料發送給消費者 (接收者)。

1. 消費者使用登入資料來確認是否為生產者發送請求。

1. 以下其中一種情況將發生：
   + 若身分驗證成功，消費者便會繼續進行流程。
   + 若身分驗證失敗，消費者便會拒絕請求並傳回錯誤。

## 使用 HMAC-SHA 的基本身分驗證流程
<a name="sqs-api-basic-authentication-process"></a>

使用查詢 API 存取 Amazon SQS 時，必須提供下列項目以對您的請求進行身分驗證：
+ 識別您 的**AWS 存取金鑰 ID** AWS 帳戶，其 AWS 會使用 來查詢您的私密存取金鑰。
+ **HMAC-SHA 請求簽章**，使用您的私密存取金鑰 （只有您知道的共用秘密 AWS，如需詳細資訊，請參閱 [RFC2104](http://www.faqs.org/rfcs/rfc2104.html))。[AWS 開發套件](https://aws.amazon.com/code/)會處理簽署程序，但若您透過 HTTP 或 HTTPS 提交查詢請求，則每一次查詢請求都必須附上簽章。

  1. 衍生 Signature 第 4 版簽署金鑰。如需詳細資訊，請參閱[使用 Java 衍生簽署金鑰](https://docs.aws.amazon.com/general/latest/gr/signature-v4-examples.html#signature-v4-examples-java)。
**注意**  
Amazon SQS 支援 Signature 第 4 版，此版本比起之前版本提供更佳的 SHA256 型安全性與效能。若您建立的新應用程式會用到 Amazon SQS，請使用 Signature 第 4 版。

  1. 對請求簽章進行 Base64 編碼。以下範例 Java 程式碼執行此作業：

     ```
     package amazon.webservices.common;
     
     // Define common routines for encoding data in AWS requests.
     public class Encoding {
     
         /* Perform base64 encoding of input bytes.
          * rawData is the array of bytes to be encoded.
          * return is the base64-encoded string representation of rawData.
          */
         public static String EncodeBase64(byte[] rawData) {
             return Base64.encodeBytes(rawData);
         }
     }
     ```
+ 請求的**時間戳記 (或過期時間)**。在請求中使用的時間戳記必須是 `dateTime` 物件，有[完整的日期，包含小時、分鐘、秒鐘](http://www.w3.org/TR/xmlschema-2/#dateTime)。例如：`2007-01-31T23:59:59Z`。儘管並非必要，但建議您使用國際標準時間 (格林威治標準時間) 時區提供此物件。
**注意**  
請確定您的伺服器時間設定正確。如果您指定時間戳記 （而不是過期），請求會在指定的時間後 15 分鐘自動過期 (AWS 不會處理時間戳記早於伺服器上目前時間 AWS 15 分鐘以上的請求）。  
如果您是使用 .NET，切勿傳送過於精確的時間戳記 (因為該平台對於如何去除多餘的時間準度有不同的解釋)。在此情況下，應手動建構精準度不超過一毫秒的 `dateTime` 物件。

## 第 1 部分：來自使用者的請求
<a name="sqs-authentication-user"></a>

以下是使用 HMAC-SHA AWS 請求簽章來驗證請求時必須遵循的程序。

![\[描述使用者請求的圖表。\]](http://docs.aws.amazon.com/zh_tw/AWSSimpleQueueService/latest/SQSDeveloperGuide/images/sqs-basic-authentication-process-hmac-user.png)


1. 建構 請求 AWS。

1. 使用您的私密存取金鑰，計算金鑰式雜湊訊息身分驗證碼 (HMAC-SHA) 簽章。

1. 在請求中包含簽章和存取金鑰 ID，然後將請求傳送到 AWS。

## 第 2 部分：來自 的回應 AWS
<a name="sqs-authentication-aws"></a>

AWS 會開始下列程序以回應。

![\[描述 回應的圖表 AWS。\]](http://docs.aws.amazon.com/zh_tw/AWSSimpleQueueService/latest/SQSDeveloperGuide/images/sqs-basic-authentication-process-hmac-aws.png)


1. AWS 使用存取金鑰 ID 來查詢您的私密存取金鑰。

1. AWS 會使用您在請求中傳送的簽章時所使用的相同演算法，從請求資料和私密存取金鑰產生簽章。

1. 以下其中一種情況將發生：
   + 如果 AWS 產生的簽章符合您在請求中傳送的簽章， 會將請求 AWS 視為真實。
   + 如果比較失敗，則會捨棄請求，並 AWS 傳回錯誤。

# Amazon SQS 批次動作
<a name="sqs-batch-api-actions"></a>

Amazon SQS 提供批次動作，可協助您降低成本，並使用單一動作操作多達 10 則訊息。這些批次動作包括：
+ `[SendMessageBatch](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_SendMessageBatch.html)`
+ `[DeleteMessageBatch](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_DeleteMessageBatch.html)`
+ `[ChangeMessageVisibilityBatch](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_ChangeMessageVisibilityBatch.html)`

使用批次動作，您可以在單一 API 呼叫中執行多個操作，這有助於最佳化效能並降低成本。您可以使用查詢 API 或任何支援 Amazon SQS 批次動作的 AWS SDK 來利用批次功能。

**重要詳細資訊**
+ **訊息大小限制：**單一`SendMessageBatch`呼叫中傳送的所有訊息總大小不得超過 1，048，576 位元組 (1 MiB)
+ **許可：**您無法明確設定 `SendMessageBatch`、 `DeleteMessageBatch`或 的許可`ChangeMessageVisibilityBatch`。反之，為 `SendMessage`、 `DeleteMessage`或 設定許可，為對應的 動作批次版本`ChangeMessageVisibility`設定許可。
+ **主控台支援：**Amazon SQS 主控台不支援批次動作。您必須使用查詢 API 或 AWS SDK 來執行批次操作。

## 批次訊息動作
<a name="batching-message-actions"></a>

若要進一步最佳化成本和效率，請考慮下列批次處理訊息動作的最佳實務：
+ **批次 API 動作：**使用 [Amazon SQS 批次 API 動作](#sqs-batch-api-actions)來傳送、接收和刪除訊息，以及使用單一動作變更多個訊息的訊息可見性逾時。這可減少 API 呼叫的數量和相關聯的成本。
+ **用戶端緩衝和長輪詢：**使用長輪詢搭配 隨附的[緩衝非同步用戶端](sqs-client-side-buffering-request-batching.md)，將用戶端緩衝與請求批次結合在一起 適用於 Java 的 AWS SDK。此方法有助於將請求數量降至最低，並最佳化大量訊息的處理。

**注意**  
Amazon SQS 緩衝非同步用戶端目前不支援 FIFO 佇列。

# 使用 Amazon SQS 啟用用戶端緩衝和請求批次處理
<a name="sqs-client-side-buffering-request-batching"></a>

[適用於 Java 的 AWS SDK](https://aws.amazon.com/sdkforjava/) 包含可存取 Amazon SQS 的 `AmazonSQSBufferedAsyncClient`。此用戶端允許使用用戶端緩衝，進行簡單的請求批次處理。從用戶端發出的呼叫會先緩衝，然後以批次請求的形式傳送至 Amazon SQS。

用戶端緩衝功能最多可緩衝處理 10 個請求並以批次請求的形式傳送，降低了使用 Amazon SQS 的成本且能減少傳送的請求數。`AmazonSQSBufferedAsyncClient` 會對同步和非同步的呼叫進行緩衝處理。批次處理的請求以及對[長輪詢](sqs-short-and-long-polling.md)的支援也有助於提高傳輸量。如需詳細資訊，請參閱 [透過 Amazon SQS 使用水平擴展和動作批次來增加輸送量](sqs-throughput-horizontal-scaling-and-batching.md)。

由於 `AmazonSQSBufferedAsyncClient` 實作的介面與 `AmazonSQSAsyncClient` 相同，從 `AmazonSQSAsyncClient` 移轉到 `AmazonSQSBufferedAsyncClient` 通常只需對既有的程式碼進行最少的更動。

**注意**  
Amazon SQS 緩衝非同步用戶端目前不支援 FIFO 佇列。

## 使用 AmazonSQSBufferedAsyncClient
<a name="using-buffered-async-client"></a>

開始之前，請完成 [設定 Amazon SQS](sqs-setting-up.md) 中的步驟。

### AWS 適用於 Java 的 SDK 1.x
<a name="using-buffered-async-client-java1"></a>

對於適用於 Java 的 AWS SDK 1.x，您可以`AmazonSQSBufferedAsyncClient`根據下列範例建立新的 ：

```
// Create the basic Amazon SQS async client
final AmazonSQSAsync sqsAsync = new AmazonSQSAsyncClient();
 
// Create the buffered client
final AmazonSQSAsync bufferedSqs = new AmazonSQSBufferedAsyncClient(sqsAsync);
```

新的 `AmazonSQSBufferedAsyncClient` 建立完成後，您可以使用它來傳送多個請求至 Amazon SQS (如同使用 `AmazonSQSAsyncClient`)，例如：

```
final CreateQueueRequest createRequest = new CreateQueueRequest().withQueueName("MyQueue");
 
final CreateQueueResult res = bufferedSqs.createQueue(createRequest);
 
final SendMessageRequest request = new SendMessageRequest();
final String body = "Your message text" + System.currentTimeMillis();
request.setMessageBody( body );
request.setQueueUrl(res.getQueueUrl());
 
final Future<SendMessageResult> sendResult = bufferedSqs.sendMessageAsync(request);
 
final ReceiveMessageRequest receiveRq = new ReceiveMessageRequest()
    .withMaxNumberOfMessages(1)
    .withQueueUrl(queueUrl);
final ReceiveMessageResult rx = bufferedSqs.receiveMessage(receiveRq);
```

### 設定 AmazonSQSBufferedAsyncClient
<a name="configuring-buffered-async-client"></a>

`AmazonSQSBufferedAsyncClient` 已預先設為適合大多數使用案例的組態。您可以進一步設定 `AmazonSQSBufferedAsyncClient`，例如：

1. 使用必要的組態參數，建立 `QueueBufferConfig` 類別的執行個體。

1. 對 `AmazonSQSBufferedAsyncClient` 建構函式提供此執行個體。

```
// Create the basic Amazon SQS async client
final AmazonSQSAsync sqsAsync = new AmazonSQSAsyncClient();
 
final QueueBufferConfig config = new QueueBufferConfig()
    .withMaxInflightReceiveBatches(5)
    .withMaxDoneReceiveBatches(15);
 
// Create the buffered client
final AmazonSQSAsync bufferedSqs = new AmazonSQSBufferedAsyncClient(sqsAsync, config);
```


**QueueBufferConfig 組態參數**  

| 參數 | 預設值 | Description | 
| --- | --- | --- | 
| longPoll | true |  若 `longPoll` 設為 `true`，`AmazonSQSBufferedAsyncClient` 在消費訊息時會嘗試使用長輪詢。  | 
| longPollWaitTimeoutSeconds | 20 秒 |  在傳回空的接收結果前，`ReceiveMessage` 呼叫留置於伺服器上等待訊息出現在佇列中的時間上限 (單位為秒)。  停用長輪詢時，此設定沒有作用。   | 
| maxBatchOpenMs | 200 毫秒 |  傳出呼叫對於其他也要批次處理同類型訊息的呼叫稍作等待的時間上限 (單位為毫秒)。 此設定值越高，執行相同工作量所需的批次數就越少 (但是，批次的第一次呼叫就需要花越長時間等待)。 若將此參數設為 `0`，提交的請求便不會等待其他請求，實際上即是停用了批次處理功能。  | 
| maxBatchSize | 每批次 10 個請求 |  單次請求同時批次處理的訊息數上限。此設定值越高，執行相同請求數所需的批次數量就越少。  Amazon SQS 允許的上限值為每批次 10 個請求。   | 
| maxBatchSizeBytes | 1 MiB |  用戶端嘗試傳送至 Amazon SQS 之訊息批次的大小上限，單位為位元組。  1 MiB 是 Amazon SQS 允許的最大值。   | 
| maxDoneReceiveBatches | 10 個批次 |  `AmazonSQSBufferedAsyncClient` 在用戶端預取並存放的接收批次數上限。 此設定值越高，則不必呼叫 Amazon SQS 就能滿足越多的接收請求 (但是，預取的訊息越多，停留在緩衝區內的時間就越久，而導致訊息的可見性逾時會到期)。  `0` 表示已停用所有訊息預先擷取，且訊息只會隨需使用。   | 
| maxInflightOutboundBatches | 5 個批次 |  可同時處理的活動中傳出批次的上限。 此設定值越高，傳出批次的傳送速度越快 (受限於 CPU 或頻寬等的配額)，且 `AmazonSQSBufferedAsyncClient` 所耗用的執行緒越多。  | 
| maxInflightReceiveBatches | 10 個批次 |  可同時處理的活動中接收批次的上限。 此設定值越高，可接收的訊息數越多 (受限於 CPU 或頻寬等的配額)，且 `AmazonSQSBufferedAsyncClient` 所耗用的執行緒越多。  `0` 表示已停用所有訊息預先擷取，且訊息只會隨需使用。   | 
| visibilityTimeoutSeconds | -1 |  若將此參數設為非零正值，其設定的可見性逾時值就會覆寫消費訊息的佇列所設的可見性逾時值。  `-1` 表示將選擇佇列預設的設定。 可見性逾時不可設為 `0`。   | 

### AWS 適用於 Java 的 SDK 2.x
<a name="using-buffered-async-client-java2"></a>

對於適用於 Java 的 AWS SDK 2.x，您可以`SqsAsyncBatchManager`根據下列範例建立新的 ：

```
// Create the basic Sqs Async Client
SqsAsyncClient sqs = SqsAsyncClient.builder() 
    .region(Region.US_EAST_1) 
    .build();

// Create the batch manager
SqsAsyncBatchManager sqsAsyncBatchManager = sqs.batchManager();
```

新的 `SqsAsyncBatchManager` 建立完成後，您可以使用它來傳送多個請求至 Amazon SQS (如同使用 `SqsAsyncClient`)，例如：

```
final String queueName = "MyAsyncBufferedQueue" + UUID.randomUUID();
final CreateQueueRequest request = CreateQueueRequest.builder().queueName(queueName).build();
final String queueUrl = sqs.createQueue(request).join().queueUrl();
System.out.println("Queue created: " + queueUrl);


// Send messages
CompletableFuture<SendMessageResponse> sendMessageFuture;
for (int i = 0; i < 10; i++) {
    final int index = i;
    sendMessageFuture = sqsAsyncBatchManager.sendMessage(
            r -> r.messageBody("Message " + index).queueUrl(queueUrl));
    SendMessageResponse response= sendMessageFuture.join();
    System.out.println("Message " + response.messageId() + " sent!");
}

// Receive messages with customized configurations
CompletableFuture<ReceiveMessageResponse> receiveResponseFuture = customizedBatchManager.receiveMessage(
        r -> r.queueUrl(queueUrl)
                .waitTimeSeconds(10)
                .visibilityTimeout(20)
                .maxNumberOfMessages(10)
);
System.out.println("You have received " + receiveResponseFuture.join().messages().size() + " messages in total.");

// Delete messages
DeleteQueueRequest deleteQueueRequest =  DeleteQueueRequest.builder().queueUrl(queueUrl).build();
int code = sqs.deleteQueue(deleteQueueRequest).join().sdkHttpResponse().statusCode();
System.out.println("Queue is deleted, with statusCode " + code);
```

### 設定 SqsAsyncBatchManager
<a name="configuring-SqsAsyncBatchManager"></a>

`SqsAsyncBatchManager` 已預先設為適合大多數使用案例的組態。您可以進一步設定 `SqsAsyncBatchManager`，例如：

透過 建立自訂組態`SqsAsyncBatchManager.Builder`：

```
SqsAsyncBatchManager customizedBatchManager = SqsAsyncBatchManager.builder() 
    .client(sqs)
    .scheduledExecutor(Executors.newScheduledThreadPool(5))
    .overrideConfiguration(b -> b 
        .maxBatchSize(10)
        .sendRequestFrequency(Duration.ofMillis(200))
        .receiveMessageMinWaitDuration(Duration.ofSeconds(10))
        .receiveMessageVisibilityTimeout(Duration.ofSeconds(20)) 
        .receiveMessageAttributeNames(Collections.singletonList("*"))
        .receiveMessageSystemAttributeNames(Collections.singletonList(MessageSystemAttributeName.ALL)))
    .build();
```


**`BatchOverrideConfiguration` 參數**  

| 參數 | 預設值 | Description | 
| --- | --- | --- | 
| maxBatchSize |  每批次 10 個請求  | 單次請求同時批次處理的訊息數上限。此設定值越高，執行相同請求數所需的批次數量就越少。  Amazon SQS 允許的值上限為每個批次 10 個請求。  | 
| sendRequestFrequency |  200 毫秒  | 傳出呼叫對於其他也要批次處理同類型訊息的呼叫稍作等待的時間上限 (單位為毫秒)。 此設定值越高，執行相同工作量所需的批次數就越少 (但是，批次的第一次呼叫就需要花越長時間等待)。 若將此參數設為 `0`，提交的請求便不會等待其他請求，實際上即是停用了批次處理功能。 | 
| receiveMessageVisibilityTimeout |  -1  | 若將此參數設為非零正值，其設定的可見性逾時值就會覆寫消費訊息的佇列所設的可見性逾時值。   `1` 表示將選擇佇列預設的設定。可見性逾時不可設為 `0`。   | 
| receiveMessageMinWaitDuration |  50 毫秒  | `receiveMessage` 呼叫等待擷取可用訊息的時間下限 （以毫秒為單位）。設定越高，執行相同數量的請求所需的批次就越少。  | 

# 透過 Amazon SQS 使用水平擴展和動作批次來增加輸送量
<a name="sqs-throughput-horizontal-scaling-and-batching"></a>

Amazon SQS 支援高輸送量傳訊。如需輸送量限制的詳細資訊，請參閱 [Amazon SQS 訊息配額](quotas-messages.md)。

若要最大化輸送量：
+ 透過新增更多每個 的執行個體，水平[擴展](#horizontal-scaling)生產者和消費者。
+ 使用[動作批次](#request-batching)在單一請求中傳送或接收多則訊息，減少 API 呼叫額外負荷。

## 水平擴展
<a name="horizontal-scaling"></a>

由於您是透過 HTTP 請求-回應協定來存取 Amazon SQS，*請求延遲* (自開始請求至收到回應的時間間隔) 會限制您透過單一連線使用單一執行緒所能達到的輸送量。例如，若 Amazon EC2 型的用戶端到 Amazon SQS 的延遲度在相同區域的平均值為 20 毫秒，透過單一連線使用單一執行緒可達到的最大輸送量平均為 50 TPS。

*水平擴展*意指增加訊息生產者 (提出 `[SendMessage](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_SendMessage.html)` 請求) 及消費者 (提出 `[ReceiveMessage](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_ReceiveMessage.html)` 和 `[DeleteMessage](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_DeleteMessage.html)` 請求) 的數目，藉以提高佇列整體的傳輸量。水平擴展的方式有三種：
+ 增加每個用戶端的執行緒數目
+ 增加更多用戶端
+ 增加每個用戶端的執行緒數目並增加更多用戶端

增加更多用戶端之後，基本上佇列傳輸量會獲得線性增益。例如，若用戶端數目加倍，傳輸量也會翻倍。

## 動作批次處理
<a name="request-batching"></a>

*批次處理*可在每次往返服務期間處理更多工作 (例如，透過單次 `SendMessageBatch` 請求傳送多則訊息)。Amazon SQS 批次動作包括 `[SendMessageBatch](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_SendMessageBatch.html)`、`[DeleteMessageBatch](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_DeleteMessageBatch.html)` 和 `[ChangeMessageVisibilityBatch](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_ChangeMessageVisibilityBatch.html)`。若要在不變動生產者或消費者的情況下利用批次處理功能，您可以使用 [Amazon SQS 緩衝非同步用戶端](sqs-client-side-buffering-request-batching.md)。

**注意**  
由於 `[ReceiveMessage](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_ReceiveMessage.html)` 一次可處理 10 則訊息，也就不必有 `ReceiveMessageBatch` 動作。

批次處理會將批次動作的延遲度分散到批次請求中的多則訊息，而非接受單則訊息 (例如 `[SendMessage](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_SendMessage.html)` 請求) 的所有延遲。由於每次往返所執行的工作較多，批次請求可以有效率地運用執行緒和連線，進而提高傳輸量。

您可以結合批次處理與水平擴展來提供傳輸量，所需的執行緒、連線和請求的數目會比單獨的訊息請求所需的量更少。您可以使用批次的 Amazon SQS 動作一次傳送、接收、刪除多達 10 則訊息。由於 Amazon SQS 收費是以請求數為準，批次處理可大幅降低您的成本。

批次處理可能會給您的應用程式帶來一些複雜性 (例如，您的應用程式必須將訊息累積起來後再傳送出去，或者有時候必須花更久的時間等待回應)。但是，批次處理在以下情況仍然頗具效益：
+ 應用程式會在短時間內產生許多訊息，所以絕不會延遲太久。
+ 訊息消費者自行從佇列擷取訊息，有別於典型的訊息生產者需要傳送訊息來回應其無法控制的事件。

**重要**  
即使批次中的個別訊息失敗，批次請求也可能會成功。提出批次請求之後，務必確認個別訊息是否出現失敗情況，必要時重試動作。

## 單次操作和批次請求實際可行的 Java 範例
<a name="working-java-example-batch-requests"></a>

### 先決條件
<a name="batch-request-java-example-prerequisites"></a>

新增 `aws-java-sdk-sqs.jar`、`aws-java-sdk-ec2.jar`，以及 `commons-logging.jar` 套件到您的 Java 建置類別路徑。以下範例顯示 Maven 專案 `pom.xml` 檔案中的此等依存關係。

```
<dependencies>
    <dependency>
        <groupId>com.amazonaws</groupId>
        <artifactId>aws-java-sdk-sqs</artifactId>
        <version>LATEST</version>
    </dependency>
    <dependency>
        <groupId>com.amazonaws</groupId>
        <artifactId>aws-java-sdk-ec2</artifactId>
        <version>LATEST</version>
    </dependency>
    <dependency>
        <groupId>commons-logging</groupId>
        <artifactId>commons-logging</artifactId>
        <version>LATEST</version>
    </dependency>
</dependencies>
```

### SimpleProducerConsumer.java
<a name="batch-request-java-example-code"></a>

以下 Java 程式碼範例實作單純的生產者-消費者模式。主要的執行緒會產生數個生產者和消費者執行緒，負責在指定時間處理 1 KB 的訊息。此範例包括提出單次操作請求的生產者和消費者，以及提出批次請求的生產者和消費者。

```
/*
 * Copyright 2010-2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 *  https://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file is distributed
 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 *
 */

import com.amazonaws.AmazonClientException;
import com.amazonaws.ClientConfiguration;
import com.amazonaws.services.sqs.AmazonSQS;
import com.amazonaws.services.sqs.AmazonSQSClientBuilder;
import com.amazonaws.services.sqs.model.*;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.Scanner;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Start a specified number of producer and consumer threads, and produce-consume
 * for the least of the specified duration and 1 hour. Some messages can be left
 * in the queue because producers and consumers might not be in exact balance.
 */
public class SimpleProducerConsumer {

    // The maximum runtime of the program.
    private final static int MAX_RUNTIME_MINUTES = 60;
    private final static Log log = LogFactory.getLog(SimpleProducerConsumer.class);

    public static void main(String[] args) throws InterruptedException {

        final Scanner input = new Scanner(System.in);

        System.out.print("Enter the queue name: ");
        final String queueName = input.nextLine();

        System.out.print("Enter the number of producers: ");
        final int producerCount = input.nextInt();

        System.out.print("Enter the number of consumers: ");
        final int consumerCount = input.nextInt();

        System.out.print("Enter the number of messages per batch: ");
        final int batchSize = input.nextInt();

        System.out.print("Enter the message size in bytes: ");
        final int messageSizeByte = input.nextInt();

        System.out.print("Enter the run time in minutes: ");
        final int runTimeMinutes = input.nextInt();

        /*
         * Create a new instance of the builder with all defaults (credentials
         * and region) set automatically. For more information, see Creating
         * Service Clients in the AWS SDK for Java Developer Guide.
         */
        final ClientConfiguration clientConfiguration = new ClientConfiguration()
                .withMaxConnections(producerCount + consumerCount);

        final AmazonSQS sqsClient = AmazonSQSClientBuilder.standard()
                .withClientConfiguration(clientConfiguration)
                .build();

        final String queueUrl = sqsClient
                .getQueueUrl(new GetQueueUrlRequest(queueName)).getQueueUrl();

        // The flag used to stop producer, consumer, and monitor threads.
        final AtomicBoolean stop = new AtomicBoolean(false);

        // Start the producers.
        final AtomicInteger producedCount = new AtomicInteger();
        final Thread[] producers = new Thread[producerCount];
        for (int i = 0; i < producerCount; i++) {
            if (batchSize == 1) {
                producers[i] = new Producer(sqsClient, queueUrl, messageSizeByte,
                        producedCount, stop);
            } else {
                producers[i] = new BatchProducer(sqsClient, queueUrl, batchSize,
                        messageSizeByte, producedCount,
                        stop);
            }
            producers[i].start();
        }

        // Start the consumers.
        final AtomicInteger consumedCount = new AtomicInteger();
        final Thread[] consumers = new Thread[consumerCount];
        for (int i = 0; i < consumerCount; i++) {
            if (batchSize == 1) {
                consumers[i] = new Consumer(sqsClient, queueUrl, consumedCount,
                        stop);
            } else {
                consumers[i] = new BatchConsumer(sqsClient, queueUrl, batchSize,
                        consumedCount, stop);
            }
            consumers[i].start();
        }

        // Start the monitor thread.
        final Thread monitor = new Monitor(producedCount, consumedCount, stop);
        monitor.start();

        // Wait for the specified amount of time then stop.
        Thread.sleep(TimeUnit.MINUTES.toMillis(Math.min(runTimeMinutes,
                MAX_RUNTIME_MINUTES)));
        stop.set(true);

        // Join all threads.
        for (int i = 0; i < producerCount; i++) {
            producers[i].join();
        }

        for (int i = 0; i < consumerCount; i++) {
            consumers[i].join();
        }

        monitor.interrupt();
        monitor.join();
    }

    private static String makeRandomString(int sizeByte) {
        final byte[] bs = new byte[(int) Math.ceil(sizeByte * 5 / 8)];
        new Random().nextBytes(bs);
        bs[0] = (byte) ((bs[0] | 64) & 127);
        return new BigInteger(bs).toString(32);
    }

    /**
     * The producer thread uses {@code SendMessage}
     * to send messages until it is stopped.
     */
    private static class Producer extends Thread {
        final AmazonSQS sqsClient;
        final String queueUrl;
        final AtomicInteger producedCount;
        final AtomicBoolean stop;
        final String theMessage;

        Producer(AmazonSQS sqsQueueBuffer, String queueUrl, int messageSizeByte,
                 AtomicInteger producedCount, AtomicBoolean stop) {
            this.sqsClient = sqsQueueBuffer;
            this.queueUrl = queueUrl;
            this.producedCount = producedCount;
            this.stop = stop;
            this.theMessage = makeRandomString(messageSizeByte);
        }

        /*
         * The producedCount object tracks the number of messages produced by
         * all producer threads. If there is an error, the program exits the
         * run() method.
         */
        public void run() {
            try {
                while (!stop.get()) {
                    sqsClient.sendMessage(new SendMessageRequest(queueUrl,
                            theMessage));
                    producedCount.incrementAndGet();
                }
            } catch (AmazonClientException e) {
                /*
                 * By default, AmazonSQSClient retries calls 3 times before
                 * failing. If this unlikely condition occurs, stop.
                 */
                log.error("Producer: " + e.getMessage());
                System.exit(1);
            }
        }
    }

    /**
     * The producer thread uses {@code SendMessageBatch}
     * to send messages until it is stopped.
     */
    private static class BatchProducer extends Thread {
        final AmazonSQS sqsClient;
        final String queueUrl;
        final int batchSize;
        final AtomicInteger producedCount;
        final AtomicBoolean stop;
        final String theMessage;

        BatchProducer(AmazonSQS sqsQueueBuffer, String queueUrl, int batchSize,
                      int messageSizeByte, AtomicInteger producedCount,
                      AtomicBoolean stop) {
            this.sqsClient = sqsQueueBuffer;
            this.queueUrl = queueUrl;
            this.batchSize = batchSize;
            this.producedCount = producedCount;
            this.stop = stop;
            this.theMessage = makeRandomString(messageSizeByte);
        }

        public void run() {
            try {
                while (!stop.get()) {
                    final SendMessageBatchRequest batchRequest =
                            new SendMessageBatchRequest().withQueueUrl(queueUrl);

                    final List<SendMessageBatchRequestEntry> entries =
                            new ArrayList<SendMessageBatchRequestEntry>();
                    for (int i = 0; i < batchSize; i++)
                        entries.add(new SendMessageBatchRequestEntry()
                                .withId(Integer.toString(i))
                                .withMessageBody(theMessage));
                    batchRequest.setEntries(entries);

                    final SendMessageBatchResult batchResult =
                            sqsClient.sendMessageBatch(batchRequest);
                    producedCount.addAndGet(batchResult.getSuccessful().size());

                    /*
                     * Because SendMessageBatch can return successfully, but
                     * individual batch items fail, retry the failed batch items.
                     */
                    if (!batchResult.getFailed().isEmpty()) {
                        log.warn("Producer: retrying sending "
                                + batchResult.getFailed().size() + " messages");
                        for (int i = 0, n = batchResult.getFailed().size();
                             i < n; i++) {
                            sqsClient.sendMessage(new
                                    SendMessageRequest(queueUrl, theMessage));
                            producedCount.incrementAndGet();
                        }
                    }
                }
            } catch (AmazonClientException e) {
                /*
                 * By default, AmazonSQSClient retries calls 3 times before
                 * failing. If this unlikely condition occurs, stop.
                 */
                log.error("BatchProducer: " + e.getMessage());
                System.exit(1);
            }
        }
    }

    /**
     * The consumer thread uses {@code ReceiveMessage} and {@code DeleteMessage}
     * to consume messages until it is stopped.
     */
    private static class Consumer extends Thread {
        final AmazonSQS sqsClient;
        final String queueUrl;
        final AtomicInteger consumedCount;
        final AtomicBoolean stop;

        Consumer(AmazonSQS sqsClient, String queueUrl, AtomicInteger consumedCount,
                 AtomicBoolean stop) {
            this.sqsClient = sqsClient;
            this.queueUrl = queueUrl;
            this.consumedCount = consumedCount;
            this.stop = stop;
        }

        /*
         * Each consumer thread receives and deletes messages until the main
         * thread stops the consumer thread. The consumedCount object tracks the
         * number of messages that are consumed by all consumer threads, and the
         * count is logged periodically.
         */
        public void run() {
            try {
                while (!stop.get()) {
                    try {
                        final ReceiveMessageResult result = sqsClient
                                .receiveMessage(new
                                        ReceiveMessageRequest(queueUrl));

                        if (!result.getMessages().isEmpty()) {
                            final Message m = result.getMessages().get(0);
                            sqsClient.deleteMessage(new
                                    DeleteMessageRequest(queueUrl,
                                    m.getReceiptHandle()));
                            consumedCount.incrementAndGet();
                        }
                    } catch (AmazonClientException e) {
                        log.error(e.getMessage());
                    }
                }
            } catch (AmazonClientException e) {
                /*
                 * By default, AmazonSQSClient retries calls 3 times before
                 * failing. If this unlikely condition occurs, stop.
                 */
                log.error("Consumer: " + e.getMessage());
                System.exit(1);
            }
        }
    }

    /**
     * The consumer thread uses {@code ReceiveMessage} and {@code
     * DeleteMessageBatch} to consume messages until it is stopped.
     */
    private static class BatchConsumer extends Thread {
        final AmazonSQS sqsClient;
        final String queueUrl;
        final int batchSize;
        final AtomicInteger consumedCount;
        final AtomicBoolean stop;

        BatchConsumer(AmazonSQS sqsClient, String queueUrl, int batchSize,
                      AtomicInteger consumedCount, AtomicBoolean stop) {
            this.sqsClient = sqsClient;
            this.queueUrl = queueUrl;
            this.batchSize = batchSize;
            this.consumedCount = consumedCount;
            this.stop = stop;
        }

        public void run() {
            try {
                while (!stop.get()) {
                    final ReceiveMessageResult result = sqsClient
                            .receiveMessage(new ReceiveMessageRequest(queueUrl)
                                    .withMaxNumberOfMessages(batchSize));

                    if (!result.getMessages().isEmpty()) {
                        final List<Message> messages = result.getMessages();
                        final DeleteMessageBatchRequest batchRequest =
                                new DeleteMessageBatchRequest()
                                        .withQueueUrl(queueUrl);

                        final List<DeleteMessageBatchRequestEntry> entries =
                                new ArrayList<DeleteMessageBatchRequestEntry>();
                        for (int i = 0, n = messages.size(); i < n; i++)
                            entries.add(new DeleteMessageBatchRequestEntry()
                                    .withId(Integer.toString(i))
                                    .withReceiptHandle(messages.get(i)
                                            .getReceiptHandle()));
                        batchRequest.setEntries(entries);

                        final DeleteMessageBatchResult batchResult = sqsClient
                                .deleteMessageBatch(batchRequest);
                        consumedCount.addAndGet(batchResult.getSuccessful().size());

                        /*
                         * Because DeleteMessageBatch can return successfully,
                         * but individual batch items fail, retry the failed
                         * batch items.
                         */
                        if (!batchResult.getFailed().isEmpty()) {
                            final int n = batchResult.getFailed().size();
                            log.warn("Producer: retrying deleting " + n
                                    + " messages");
                            for (BatchResultErrorEntry e : batchResult
                                    .getFailed()) {

                                sqsClient.deleteMessage(
                                        new DeleteMessageRequest(queueUrl,
                                                messages.get(Integer
                                                        .parseInt(e.getId()))
                                                        .getReceiptHandle()));

                                consumedCount.incrementAndGet();
                            }
                        }
                    }
                }
            } catch (AmazonClientException e) {
                /*
                 * By default, AmazonSQSClient retries calls 3 times before
                 * failing. If this unlikely condition occurs, stop.
                 */
                log.error("BatchConsumer: " + e.getMessage());
                System.exit(1);
            }
        }
    }

    /**
     * This thread prints every second the number of messages produced and
     * consumed so far.
     */
    private static class Monitor extends Thread {
        private final AtomicInteger producedCount;
        private final AtomicInteger consumedCount;
        private final AtomicBoolean stop;

        Monitor(AtomicInteger producedCount, AtomicInteger consumedCount,
                AtomicBoolean stop) {
            this.producedCount = producedCount;
            this.consumedCount = consumedCount;
            this.stop = stop;
        }

        public void run() {
            try {
                while (!stop.get()) {
                    Thread.sleep(1000);
                    log.info("produced messages = " + producedCount.get()
                            + ", consumed messages = " + consumedCount.get());
                }
            } catch (InterruptedException e) {
                // Allow the thread to exit.
            }
        }
    }
}
```

### 監控範本執行階段的數量指標
<a name="batch-request-java-example-monitoring-metrics"></a>

Amazon SQS 會自動為傳送、接收及刪除的訊息產生數量指標。您可以透過佇列的**監控**索引標籤或 [CloudWatch 主控台](https://console.aws.amazon.com/cloudwatch/home)存取這類指標和其他項目。

**注意**  
可能要在佇列開始執行達 15 分鐘後方可取得指標。

# 搭配 SDK 使用 Amazon SQS AWS
<a name="sdk-general-information-section"></a>

AWS 軟體開發套件 (SDKs) 適用於許多熱門的程式設計語言。每個 SDK 都提供 API、程式碼範例和說明文件，讓開發人員能夠更輕鬆地以偏好的語言建置應用程式。


| SDK 文件 | 代碼範例 | 
| --- | --- | 
| [適用於 C\$1\$1 的 AWS SDK](https://docs.aws.amazon.com/sdk-for-cpp) | [適用於 C\$1\$1 的 AWS SDK 程式碼範例](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/cpp) | 
| [AWS CLI](https://docs.aws.amazon.com/cli) | [AWS CLI 程式碼範例](https://docs.aws.amazon.com/code-library/latest/ug/cli_2_code_examples.html) | 
| [適用於 Go 的 AWS SDK](https://docs.aws.amazon.com/sdk-for-go) | [適用於 Go 的 AWS SDK 程式碼範例](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/gov2) | 
| [適用於 Java 的 AWS SDK](https://docs.aws.amazon.com/sdk-for-java) | [適用於 Java 的 AWS SDK 程式碼範例](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/javav2) | 
| [適用於 JavaScript 的 AWS SDK](https://docs.aws.amazon.com/sdk-for-javascript) | [適用於 JavaScript 的 AWS SDK 程式碼範例](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/javascriptv3) | 
| [適用於 Kotlin 的 AWS SDK](https://docs.aws.amazon.com/sdk-for-kotlin) | [適用於 Kotlin 的 AWS SDK 程式碼範例](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/kotlin) | 
| [適用於 .NET 的 AWS SDK](https://docs.aws.amazon.com/sdk-for-net) | [適用於 .NET 的 AWS SDK 程式碼範例](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/dotnetv3) | 
| [適用於 PHP 的 AWS SDK](https://docs.aws.amazon.com/sdk-for-php) | [適用於 PHP 的 AWS SDK 程式碼範例](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/php) | 
| [AWS Tools for PowerShell](https://docs.aws.amazon.com/powershell) | [AWS Tools for PowerShell 程式碼範例](https://docs.aws.amazon.com/code-library/latest/ug/powershell_5_code_examples.html) | 
| [適用於 Python (Boto3) 的 AWS SDK](https://docs.aws.amazon.com/pythonsdk) | [適用於 Python (Boto3) 的 AWS SDK 程式碼範例](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/python) | 
| [適用於 Ruby 的 AWS SDK](https://docs.aws.amazon.com/sdk-for-ruby) | [適用於 Ruby 的 AWS SDK 程式碼範例](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/ruby) | 
| [適用於 Rust 的 AWS SDK](https://docs.aws.amazon.com/sdk-for-rust) | [適用於 Rust 的 AWS SDK 程式碼範例](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/rustv1) | 
| [適用於 SAP ABAP 的 AWS SDK](https://docs.aws.amazon.com/sdk-for-sapabap) | [適用於 SAP ABAP 的 AWS SDK 程式碼範例](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/sap-abap) | 
| [適用於 Swift 的 AWS SDK](https://docs.aws.amazon.com/sdk-for-swift) | [適用於 Swift 的 AWS SDK 程式碼範例](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/swift) | 

**可用性範例**  
找不到所需的內容嗎？ 請使用本頁面底部的**提供意見回饋**連結申請程式碼範例。