

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

# 教學課程：搭配 Amazon SQS 使用 Lambda
<a name="with-sqs-example"></a>

在本教學課程中，您將建立一個 Lambda 函數，該函數取用 [Amazon Simple Queue Service (Amazon SQS)](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/welcome.html) 佇列中的訊息。只要有新訊息加入佇列，Lambda 函數就會執行。函數會將訊息寫入 Amazon CloudWatch Logs 串流。下圖顯示可用來完成教學課程的 AWS 資源。

![\[\]](http://docs.aws.amazon.com/zh_tw/lambda/latest/dg/images/sqs_tut_resources.png)


請執行下列步驟以完成本教學課程：

1. 建立將訊息寫入 CloudWatch Logs 的 Lambda 函數。

1. 建立 Amazon SQS 佇列。

1. 建立 Lambda 事件來源映射。事件來源映射會讀取 Amazon SQS 佇列，並在新增訊息時調用 Lambda 函數。

1. 透過將訊息新增至佇列並監控 CloudWatch Logs 中的結果來測試設定。

## 先決條件
<a name="with-sqs-prepare"></a>

### 安裝 AWS Command Line Interface
<a name="install_aws_cli"></a>

如果您尚未安裝 AWS Command Line Interface，請依照[安裝或更新最新版本的 AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)中的步驟進行安裝。

本教學課程需使用命令列終端機或 Shell 來執行命令。在 Linux 和 macOS 中，使用您偏好的 Shell 和套件管理工具。

**注意**  
在 Windows 中，作業系統的內建終端不支援您常與 Lambda 搭配使用的某些 Bash CLI 命令 (例如 `zip`)。若要取得 Ubuntu 和 Bash 的 Windows 整合版本，請[安裝適用於 Linux 的 Windows 子系統](https://docs.microsoft.com/en-us/windows/wsl/install-win10)。

## 建立執行角色
<a name="with-sqs-create-execution-role"></a>

![\[\]](http://docs.aws.amazon.com/zh_tw/lambda/latest/dg/images/sqs_tut_steps1.png)


[執行角色](lambda-intro-execution-role.md)是授予 Lambda 函數存取 AWS 服務 和資源許可的 AWS Identity and Access Management (IAM) 角色。若要允許函數從 Amazon SQS 中讀取項目，請連接 **AWSLambdaSQSQueueExecutionRole** 許可政策。

**建立執行角色並連接 Amazon SQS 許可政策**

1. 開啟 IAM 主控台中的[角色頁面](https://console.aws.amazon.com/iam/home#/roles)。

1. 選擇 **建立角色**。

1. 針對**信任的實體類型**，請選擇 **AWS 服務**。

1. 針對**使用案例**，請選擇 **Lambda**。

1. 選擇**下一步**。

1. 在**許可政策**搜尋方塊中，輸入 **AWSLambdaSQSQueueExecutionRole**。

1. 選取 **AWSLambdaSQSQueueExecutionRole** 政策，然後選擇**下一步**。

1. 針對**角色詳細資訊**下的**角色名稱**，請輸入 **lambda-sqs-role**，然後選擇**建立角色**。

角色建立後，請記下執行角色的 Amazon Resource Name (ARN)。在後續步驟中會需要用到它。

## 建立函數
<a name="with-sqs-create-function"></a>

![\[\]](http://docs.aws.amazon.com/zh_tw/lambda/latest/dg/images/sqs_tut_steps2.png)


建立 Lambda 函數，它處理 Amazon SQS 訊息。函數程式碼會將 Amazon SQS 的訊息內文記錄到 Amazon CloudWatch Logs。

本教學課程使用 Node.js 24 執行時間，但我們也提供其他執行時間語言的範例程式碼。您可以在下列方塊中選取索引標籤，查看您感興趣的執行期程式碼。此步驟要使用的 JavaScript 程式碼，位於 **JavaScript** 索引標籤中顯示的第一個範例。

------
#### [ .NET ]

**適用於 .NET 的 SDK**  
 GitHub 上提供更多範例。尋找完整範例，並了解如何在[無伺服器範例](https://github.com/aws-samples/serverless-snippets/tree/main/integration-sqs-to-lambda)儲存庫中設定和執行。
使用 .NET 搭配 Lambda 來使用 SQS 事件。  

```
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
﻿using Amazon.Lambda.Core;
using Amazon.Lambda.SQSEvents;


// Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]

namespace SqsIntegrationSampleCode
{
    public async Task FunctionHandler(SQSEvent evnt, ILambdaContext context)
    {
        foreach (var message in evnt.Records)
        {
            await ProcessMessageAsync(message, context);
        }

        context.Logger.LogInformation("done");
    }

    private async Task ProcessMessageAsync(SQSEvent.SQSMessage message, ILambdaContext context)
    {
        try
        {
            context.Logger.LogInformation($"Processed message {message.Body}");

            // TODO: Do interesting work based on the new message
            await Task.CompletedTask;
        }
        catch (Exception e)
        {
            //You can use Dead Letter Queue to handle failures. By configuring a Lambda DLQ.
            context.Logger.LogError($"An error occurred");
            throw;
        }

    }
}
```

------
#### [ Go ]

**SDK for Go V2**  
 GitHub 上提供更多範例。尋找完整範例，並了解如何在[無伺服器範例](https://github.com/aws-samples/serverless-snippets/tree/main/integration-sqs-to-lambda)儲存庫中設定和執行。
使用 Go 搭配 Lambda 來使用 SQS 事件。  

```
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package integration_sqs_to_lambda

import (
	"fmt"
	"github.com/aws/aws-lambda-go/events"
	"github.com/aws/aws-lambda-go/lambda"
)

func handler(event events.SQSEvent) error {
	for _, record := range event.Records {
		err := processMessage(record)
		if err != nil {
			return err
		}
	}
	fmt.Println("done")
	return nil
}

func processMessage(record events.SQSMessage) error {
	fmt.Printf("Processed message %s\n", record.Body)
	// TODO: Do interesting work based on the new message
	return nil
}

func main() {
	lambda.Start(handler)
}
```

------
#### [ Java ]

**SDK for Java 2.x**  
 GitHub 上提供更多範例。尋找完整範例，並了解如何在[無伺服器範例](https://github.com/aws-samples/serverless-snippets/tree/main/integration-sqs-to-lambda)儲存庫中設定和執行。
使用 Java 搭配 Lambda 來使用 SQS 事件。  

```
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.events.SQSEvent;
import com.amazonaws.services.lambda.runtime.events.SQSEvent.SQSMessage;

public class Function implements RequestHandler<SQSEvent, Void> {
    @Override
    public Void handleRequest(SQSEvent sqsEvent, Context context) {
        for (SQSMessage msg : sqsEvent.getRecords()) {
            processMessage(msg, context);
        }
        context.getLogger().log("done");
        return null;
    }

    private void processMessage(SQSMessage msg, Context context) {
        try {
            context.getLogger().log("Processed message " + msg.getBody());

            // TODO: Do interesting work based on the new message

        } catch (Exception e) {
            context.getLogger().log("An error occurred");
            throw e;
        }

    }
}
```

------
#### [ JavaScript ]

**適用於 JavaScript (v3) 的 SDK**  
 GitHub 上提供更多範例。尋找完整範例，並了解如何在[無伺服器範例](https://github.com/aws-samples/serverless-snippets/blob/main/integration-sqs-to-lambda)儲存庫中設定和執行。
使用 JavaScript 搭配 Lambda 來使用 SQS 事件。  

```
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
exports.handler = async (event, context) => {
  for (const message of event.Records) {
    await processMessageAsync(message);
  }
  console.info("done");
};

async function processMessageAsync(message) {
  try {
    console.log(`Processed message ${message.body}`);
    // TODO: Do interesting work based on the new message
    await Promise.resolve(1); //Placeholder for actual async work
  } catch (err) {
    console.error("An error occurred");
    throw err;
  }
}
```
使用 TypeScript 搭配 Lambda 來使用 SQS 事件。  

```
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
import { SQSEvent, Context, SQSHandler, SQSRecord } from "aws-lambda";

export const functionHandler: SQSHandler = async (
  event: SQSEvent,
  context: Context
): Promise<void> => {
  for (const message of event.Records) {
    await processMessageAsync(message);
  }
  console.info("done");
};

async function processMessageAsync(message: SQSRecord): Promise<any> {
  try {
    console.log(`Processed message ${message.body}`);
    // TODO: Do interesting work based on the new message
    await Promise.resolve(1); //Placeholder for actual async work
  } catch (err) {
    console.error("An error occurred");
    throw err;
  }
}
```

------
#### [ PHP ]

**適用於 PHP 的 SDK**  
 GitHub 上提供更多範例。尋找完整範例，並了解如何在[無伺服器範例](https://github.com/aws-samples/serverless-snippets/tree/main/integration-sqs-to-lambda)儲存庫中設定和執行。
使用 PHP 搭配 Lambda 來使用 SQS 事件。  

```
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
<?php

# using bref/bref and bref/logger for simplicity

use Bref\Context\Context;
use Bref\Event\InvalidLambdaEvent;
use Bref\Event\Sqs\SqsEvent;
use Bref\Event\Sqs\SqsHandler;
use Bref\Logger\StderrLogger;

require __DIR__ . '/vendor/autoload.php';

class Handler extends SqsHandler
{
    private StderrLogger $logger;
    public function __construct(StderrLogger $logger)
    {
        $this->logger = $logger;
    }

    /**
     * @throws InvalidLambdaEvent
     */
    public function handleSqs(SqsEvent $event, Context $context): void
    {
        foreach ($event->getRecords() as $record) {
            $body = $record->getBody();
            // TODO: Do interesting work based on the new message
        }
    }
}

$logger = new StderrLogger();
return new Handler($logger);
```

------
#### [ Python ]

**適用於 Python 的 SDK (Boto3)**  
 GitHub 上提供更多範例。尋找完整範例，並了解如何在[無伺服器範例](https://github.com/aws-samples/serverless-snippets/tree/main/integration-sqs-to-lambda)儲存庫中設定和執行。
使用 Python 搭配 Lambda 來使用 SQS 事件。  

```
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
def lambda_handler(event, context):
    for message in event['Records']:
        process_message(message)
    print("done")

def process_message(message):
    try:
        print(f"Processed message {message['body']}")
        # TODO: Do interesting work based on the new message
    except Exception as err:
        print("An error occurred")
        raise err
```

------
#### [ Ruby ]

**SDK for Ruby**  
 GitHub 上提供更多範例。尋找完整範例，並了解如何在[無伺服器範例](https://github.com/aws-samples/serverless-snippets/tree/main/integration-sqs-to-lambda)儲存庫中設定和執行。
使用 Ruby 搭配 Lambda 來使用 SQS 事件。  

```
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
def lambda_handler(event:, context:)
  event['Records'].each do |message|
    process_message(message)
  end
  puts "done"
end

def process_message(message)
  begin
    puts "Processed message #{message['body']}"
    # TODO: Do interesting work based on the new message
  rescue StandardError => err
    puts "An error occurred"
    raise err
  end
end
```

------
#### [ Rust ]

**適用於 Rust 的 SDK**  
 GitHub 上提供更多範例。尋找完整範例，並了解如何在[無伺服器範例](https://github.com/aws-samples/serverless-snippets/tree/main/integration-sqs-to-lambda)儲存庫中設定和執行。
使用 Rust 搭配 Lambda 來使用 SQS 事件。  

```
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
use aws_lambda_events::event::sqs::SqsEvent;
use lambda_runtime::{run, service_fn, Error, LambdaEvent};

async fn function_handler(event: LambdaEvent<SqsEvent>) -> Result<(), Error> {
    event.payload.records.iter().for_each(|record| {
        // process the record
        tracing::info!("Message body: {}", record.body.as_deref().unwrap_or_default())
    });

    Ok(())
}

#[tokio::main]
async fn main() -> Result<(), Error> {
    tracing_subscriber::fmt()
        .with_max_level(tracing::Level::INFO)
        // disable printing the name of the module in every log line.
        .with_target(false)
        // disabling time is handy because CloudWatch will add the ingestion time.
        .without_time()
        .init();

    run(service_fn(function_handler)).await
}
```

------

**若要建立 Node.js Lambda 函數**

1. 建立專案的目錄，然後切換至該目錄。

   ```
   mkdir sqs-tutorial
   cd sqs-tutorial
   ```

1. 將範例 JavaScript 程式碼複製到名為 `index.js` 的新檔案。

1. 使用以下 `zip` 命令建立部署套件。

   ```
   zip function.zip index.js
   ```

1. 使用 [create-function](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/create-function.html) AWS CLI 命令建立 Lambda 函數。針對 `role` 參數，輸入您之前建立的執行角色 ARN。
**注意**  
該 Lambda 函數和 Amazon SQS 佇列必須位於相同的 AWS 區域。

   ```
   aws lambda create-function --function-name ProcessSQSRecord \
   --zip-file fileb://function.zip --handler index.handler --runtime nodejs24.x \
   --role arn:aws:iam::111122223333:role/lambda-sqs-role
   ```

## 測試函數
<a name="with-sqs-create-test-function"></a>

![\[\]](http://docs.aws.amazon.com/zh_tw/lambda/latest/dg/images/sqs_tut_steps3.png)


使用 `invoke` AWS CLI 命令和範例 Amazon SQS 事件手動叫用 Lambda 函數。

**使用範例事件調用 Lambda 函數**

1. 將下面的 JSON 儲存為名為 `input.json` 的檔案。此 JSON 會模擬 Amazon SQS 可能傳送至 Lambda 函數的事件，其中 `"body"` 包含佇列中的實際訊息。在此範例中，訊息為 `"test"`。  
**Example Amazon SQS 事件**  

   這是測試事件，您不需要變更訊息或帳號。

   ```
   {
       "Records": [
           {
               "messageId": "059f36b4-87a3-44ab-83d2-661975830a7d",
               "receiptHandle": "AQEBwJnKyrHigUMZj6rYigCgxlaS3SLy0a...",
               "body": "test",
               "attributes": {
                   "ApproximateReceiveCount": "1",
                   "SentTimestamp": "1545082649183",
                   "SenderId": "AIDAIENQZJOLO23YVJ4VO",
                   "ApproximateFirstReceiveTimestamp": "1545082649185"
               },
               "messageAttributes": {},
               "md5OfBody": "098f6bcd4621d373cade4e832627b4f6",
               "eventSource": "aws:sqs",
               "eventSourceARN": "arn:aws:sqs:us-east-1:111122223333:my-queue",
               "awsRegion": "us-east-1"
           }
       ]
   }
   ```

1. 執行下列[叫用](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/invoke.html) AWS CLI 命令。此命令在回應中傳回 CloudWatch 日誌。如需擷取日誌的詳細資訊，請參閱[使用 存取日誌 AWS CLI](monitoring-cloudwatchlogs-view.md#monitoring-cloudwatchlogs-cli)。

   ```
   aws lambda invoke --function-name ProcessSQSRecord --payload file://input.json out --log-type Tail \
   --query 'LogResult' --output text --cli-binary-format raw-in-base64-out | base64 --decode
   ```

   如果您使用的是第 2 AWS CLI 版，則需要 **cli-binary-format**選項。若要讓此成為預設的設定，請執行 `aws configure set cli-binary-format raw-in-base64-out`。若要取得更多資訊，請參閱*《AWS Command Line Interface 使用者指南第 2 版》*中 [AWS CLI 支援的全域命令列選項](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-options.html#cli-configure-options-list)。

1. 在回應中查找 `INFO` 日誌。這是 Lambda 函數記錄訊息內文的位置。您應該會看到類似以下內容的輸出：

   ```
   2023-09-11T22:45:04.271Z	348529ce-2211-4222-9099-59d07d837b60	INFO	Processed message test
   2023-09-11T22:45:04.288Z	348529ce-2211-4222-9099-59d07d837b60	INFO	done
   ```

## 建立 Amazon SQS 佇列
<a name="with-sqs-configure-sqs"></a>

![\[\]](http://docs.aws.amazon.com/zh_tw/lambda/latest/dg/images/sqs_tut_steps4.png)


建立 Lambda 函數可用作事件來源的 Amazon SQS 佇列。該 Lambda 函數和 Amazon SQS 佇列必須位於相同的 AWS 區域。

**建立佇列**

1. 開啟 [Amazon SQS 主控台](https://console.aws.amazon.com/sqs)。

1. 選擇**建立佇列**。

1. 輸入佇列的名稱。將所有其他選項保留為預設值。

1. 選擇**建立佇列**。

建立佇列後，請記下其 ARN。在下個步驟中，將佇列與您的 Lambda 函數建立關聯時會需要用到它。

## 設定事件來源
<a name="with-sqs-attach-notification-configuration"></a>

![\[\]](http://docs.aws.amazon.com/zh_tw/lambda/latest/dg/images/sqs_tut_steps5.png)


透過建立[事件來源映射](invocation-eventsourcemapping.md)，將 Amazon SQS 佇列連線至 Lambda 函數。事件來源映射會讀取 Amazon SQS 佇列，並在新增訊息時調用 Lambda 函數。

若要在 Amazon SQS 佇列和 Lambda 函數之間建立映射，請使用 [create-event-source-mapping](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/create-event-source-mapping.html) AWS CLI 命令。範例：

```
aws lambda create-event-source-mapping --function-name ProcessSQSRecord  --batch-size 10 \
--event-source-arn arn:aws:sqs:us-east-1:111122223333:my-queue
```

若要獲取事件來源映射清單，請使用 [list-event-source-mappings](https://awscli.amazonaws.com/v2/documentation/api/2.1.29/reference/lambda/list-event-source-mappings.html) 命令。範例：

```
aws lambda list-event-source-mappings --function-name ProcessSQSRecord
```

## 傳送測試訊息
<a name="with-sqs-test-message"></a>

![\[\]](http://docs.aws.amazon.com/zh_tw/lambda/latest/dg/images/sqs_tut_steps6.png)


**將 Amazon SQS 訊息傳送至 Lambda 函數**

1. 開啟 [Amazon SQS 主控台](https://console.aws.amazon.com/sqs)。

1. 選擇您稍早建立的佇列。

1. 選擇**傳送及接收訊息**。

1. 在**訊息內文**下，輸入測試訊息，例如「這是測試訊息」。

1. 選擇**傳送訊息**。

Lambda 輪詢佇列以查看是否有更新。當有新訊息時，Lambda 會使用佇列中的此新事件資料來叫用您的函數。如果函數處理常式傳回而無例外情況，則 Lambda 會認為訊息已成功處理，並開始讀取佇列中的新訊息。成功處理訊息之後，Lambda 從佇列中自動刪除它。如果處理常式擲出例外情況，Lambda 會認為訊息批次未成功處理，並且 Lambda 會調用具有相同訊息批次的函數。

## 檢查 CloudWatch 日誌
<a name="with-sqs-check-logs"></a>

![\[\]](http://docs.aws.amazon.com/zh_tw/lambda/latest/dg/images/sqs_tut_steps7.png)


**確認函數已處理訊息**

1. 開啟 Lambda 主控台中的[函數頁面](https://console.aws.amazon.com/lambda/home#/functions)。

1. 選擇 **ProcessSQSRecord** 函數。

1. 選擇**監控**。

1. 選擇**檢視 CloudWatch 日誌**。

1. 在 CloudWatch 主控台中，選擇函數的**日誌串流**。

1. 查找 `INFO` 日誌。這是 Lambda 函數記錄訊息內文的位置。應能看到您從 Amazon SQS 佇列傳送的訊息。範例：

   ```
   2023-09-11T22:49:12.730Z b0c41e9c-0556-5a8b-af83-43e59efeec71 INFO Processed message this is a test message.
   ```

## 清除您的資源
<a name="cleanup"></a>

除非您想要保留為此教學課程建立的資源，否則您現在便可刪除。透過刪除您不再使用 AWS 的資源，您可以避免不必要的 費用 AWS 帳戶。

**刪除執行角色**

1. 開啟 IAM 主控台中的 [角色頁面](https://console.aws.amazon.com/iam/home#/roles) 。

1. 選取您建立的執行角色。

1. 選擇**刪除**。

1. 在文字輸入欄位中輸入角色的名稱，然後選擇 **刪除** 。

**若要刪除 Lambda 函數**

1. 開啟 Lambda 主控台中的 [函數頁面](https://console.aws.amazon.com/lambda/home#/functions)。

1. 選擇您建立的函數。

1. 選擇 **Actions** (動作)、**Delete** (刪除)。

1. 在文字輸入欄位中輸入 **confirm**，然後選擇 **刪除** 。

**刪除 Amazon SQS 佇列**

1. 登入 AWS 管理主控台 並開啟位於 https：//[https://console.aws.amazon.com/sqs/](https://console.aws.amazon.com/sqs/) 的 Amazon SQS 主控台。

1. 選取您建立的佇列。

1. 選擇 **刪除** 。

1. 在文字輸入欄位中輸入 **confirm**。

1. 選擇 **刪除** 。