

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

# 教學課程：使用 Lambda 函數來存取 Amazon RDS 資料庫
<a name="rds-lambda-tutorial"></a>

在本教學課程中，您會透過 RDS Proxy 使用 Lambda 函數將資料寫入 [Amazon Relational Database Service](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Welcome.html) (Amazon RDS) 資料庫。每當有訊息新增，您的 Lambda 函數就會從 Amazon Simple Queue Service (Amazon SQS) 佇列中讀取記錄，然後將新項目寫入資料庫中的資料表。在此範例中，您可以使用 AWS 管理主控台 手動將訊息新增至佇列。下圖顯示您用來完成教學課程 AWS 的資源。

![\[\]](http://docs.aws.amazon.com/zh_tw/AmazonRDS/latest/UserGuide/images/TUT_Lambda_1.png)


透過 Amazon RDS，您可以使用常見的資料庫產品 (如 Microsoft SQL Server、MariaDB、MySQL、Oracle 資料庫和 PostgreSQL) 在雲端中執行受管關聯式資料庫。透過使用 Lambda 存取您的資料庫，您可以讀取和寫入資料以回應事件，例如在您網站上註冊的新客戶。您的函數、資料庫執行個體和代理也會自動擴展，以滿足高需求的期間。

請完成下列任務以完成本教學課程：

1. 在 AWS 帳戶預設 VPC 中啟動 RDS for MySQL 資料庫執行個體和代理。

1. 建立並測試 Lambda 函數，用於在資料庫中建立新資料表並將資料寫入。

1. 建立 Amazon SQS 佇列並將其設定為在新增訊息時調用 Lambda 函數。

1. 使用 將訊息新增至佇列 AWS 管理主控台 ，並使用 CloudWatch Logs 監控結果，以測試完整的設定。

完成這些步驟的過程中，您將了解：
+ 如何使用 Amazon RDS 建立資料庫執行個體和代理，以及將 Lambda 函數連線至代理。
+ 如何使用 Lambda 在 Amazon RDS 資料庫上執行建立和讀取操作。
+ 如何使用 Amazon SQS 調用 Lambda 函數。

您可以使用 AWS 管理主控台 或 AWS Command Line Interface () 完成本教學課程AWS CLI。

## 先決條件
<a name="vpc-rds-prereqs"></a>

在開始之前，請先完成下節所含步驟：
+ [註冊 AWS 帳戶](CHAP_SettingUp.md#sign-up-for-aws)
+ [建立具有管理存取權的使用者](CHAP_SettingUp.md#create-an-admin)

## 建立 Amazon RDS 資料庫執行個體
<a name="vpc-rds-create-RDS-instance"></a>

![\[\]](http://docs.aws.amazon.com/zh_tw/AmazonRDS/latest/UserGuide/images/TUT_Lambda_step1.png)


Amazon RDS 資料庫執行個體是在 AWS 雲端中執行的隔離資料庫環境。執行個體可以包含一或多個使用者建立的資料庫。除非您另有指定，否則 Amazon RDS 會在 中包含的預設 VPC 中建立新的資料庫執行個體 AWS 帳戶。如需 Amazon VPC 的詳細資訊，請參閱[《Amazon Virtual Private Cloud 使用者指南》](https://docs.aws.amazon.com/vpc/latest/userguide/what-is-amazon-vpc.html)。

在本教學課程中，您會 AWS 帳戶在預設 VPC 中建立新的執行個體，並在該執行個體`ExampleDB`中建立名為 的資料庫。您可以使用 AWS 管理主控台 或 建立資料庫執行個體和資料庫 AWS CLI。

**建立資料庫執行個體**

1. 開啟 Amazon RDS 主控台並選擇**建立資料庫**。

1. 保持選取**標準建立**選項，然後在**引擎選項**中選擇**MySQL**。

1. 在**範本**中，選擇**免費方案**或**沙盒**。免費方案帳戶會顯示**免費方案**。付費方案帳戶的**沙盒**隨即顯示。

1. 在 **設定** 中，在 **資料庫執行個體識別碼** 輸入 **MySQLForLambda**。

1. 執行以下操作以設定您的使用者名稱和密碼：

   1. 在**憑證設定**中，將**主要使用者名稱**設為 `admin`。

   1. 在**主要密碼**輸入並確認用於存取資料庫的密碼。

1. 執行下列操作以指定資料庫名稱：
   + 保持選取所有剩餘的預設選項，並向下捲動至**其他組態**部分。
   + 展開此區段並在**初始資料庫名稱**輸入 **ExampleDB**。

1. 保持選取所有剩餘的預設選項，然後選擇**建立資料庫**。

## 建立 Lambda 函數和代理
<a name="auto-create-Lambda"></a>

![\[\]](http://docs.aws.amazon.com/zh_tw/AmazonRDS/latest/UserGuide/images/TUT_Lambda_step2.png)


您可以使用 RDS 主控台在與資料庫相同的 VPC 中建立 Lambda 函數和代理。

**注意**  
只有當資料庫已完成建立並處於**可用**狀態時，才能建立這些關聯的資源。

**建立關聯的函數和代理**

1. 從**資料庫**頁面中，檢查您的資料庫是否處於**可用**狀態。若是，則請繼續下一個步驟。否則，請等待您的資料庫直到為可用狀態。

1. 選取您的資料庫並從**動作**選擇**設定 Lambda 連線**。

1. 在**設定 Lambda 連線**頁面上，選擇**建立新函數**。

   將**新的 Lambda 函數名稱**設定為 **LambdaFunctionWithRDS**。

1. 在 **RDS Proxy** 區段中，選取**使用 RDS Proxy 連線**選項。進一步選擇**建立新的代理**。
   + 針對**資料庫憑證**，選擇**資料庫使用者名稱和密碼**。
   + 針對**使用者名稱**，指定 `admin`。
   + 針對**密碼**，輸入資料庫執行個體的密碼。

1. 選取**設定**以完成代理和 Lambda 函數的建立。

精靈會完成設定，並提供 Lambda 主控台的連結，以檢閱您的新功能。切換至 Lambda 主控台之前，請注意代理端點。

## 建立函數執行角色
<a name="vpc-rds-create-execution-role"></a>

![\[\]](http://docs.aws.amazon.com/zh_tw/AmazonRDS/latest/UserGuide/images/TUT_Lambda_step3.png)


建立 Lambda 函數之前須先建立執行角色，為函數提供必要的許可。在本教學課程中，Lambda 需要許可，才能管理與包含資料庫執行個體之 VPC 的網路連線，以及輪詢來自 Amazon SQS 佇列的訊息。

為了提供 Lambda 函數所需的許可，本教學課程使用 IAM 受管政策。這些政策會授予適用於許多常見使用案例的許可，並可在您的 AWS 帳戶中取用。如需使用受管政策的詳細資訊，請參閱：[政策最佳實務](security_iam_id-based-policy-examples.md#security_iam_service-with-iam-policy-best-practices)。

**建立 Lambda 執行角色**

1. 開啟 IAM 主控台的[角色](https://console.aws.amazon.com/iamv2/home#/roles)頁面，然後選擇 **建立角色**。

1. **信任的實體類型**請選擇 **AWS 服務**，而針對**使用案例**，請選擇 **Lambda**。

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

1. 執行下列操作以新增 IAM 受管政策：

   1. 使用政策搜尋方塊，搜尋 **AWSLambdaSQSQueueExecutionRole**。

   1. 在結果清單中，選取角色旁的核取方塊，然後選擇**清除篩選條件**。

   1. 使用政策搜尋方塊，搜尋 **AWSLambdaVPCAccessExecutionRole**。

   1. 在結果清單中，選取角色旁的核取方塊，然後選擇**下一步**。

1. 在 **角色名稱** 輸入 **lambda-vpc-sqs-role**，然後選擇 **建立角色**。

在教學課程的後續階段中，需用到您剛才建立的執行角色之 Amazon Resource Name (ARN)。

**尋找執行角色 ARN 的方式**

1. 開啟 IAM 主控台的[角色](https://console.aws.amazon.com/iamv2/home#/roles)頁面，然後選擇您的角色 (`lambda-vpc-sqs-role`)。

1.  複製 **ARN** 區段中顯示的**摘要**。

## 建立 Lambda 部署套件
<a name="vpc-rds-create-deployment-package"></a>

![\[\]](http://docs.aws.amazon.com/zh_tw/AmazonRDS/latest/UserGuide/images/TUT_Lambda_step4.png)


下面的範例 Python 程式碼使用 [PyMySQL](https://pymysql.readthedocs.io/en/latest/) 套件開啟與資料庫的連線。您第一次調用函數時，它還會建立一個名為 `Customer` 的新資料表。該資料表使用以下結構描述，其中 `CustID` 是主索引鍵：

```
Customer(CustID, Name)
```

函數也會使用 PyMySQL 將記錄新增到此資料表。函數會使用您要新增至 Amazon SQS 佇列的訊息中指定的客戶 ID 和名稱以新增記錄。

程式碼會在處理常式函數之外建立與資料庫的連線。在初始化程式碼中建立連線，允許後續的函數調用重複使用連線並提高效能。在生產應用程式中，您也可以使用[佈建並行](https://docs.aws.amazon.com/lambda/latest/dg/provisioned-concurrency.html)初始化請求的資料庫連線數目。只要函數調用後就可以使用這些連線。

```
import sys
import logging
import pymysql
import json
import os

# rds settings
user_name = os.environ['USER_NAME']
password = os.environ['PASSWORD']
rds_proxy_host = os.environ['RDS_PROXY_HOST']
db_name = os.environ['DB_NAME']

logger = logging.getLogger()
logger.setLevel(logging.INFO)

# create the database connection outside of the handler to allow connections to be
# re-used by subsequent function invocations.
try:
        conn = pymysql.connect(host=rds_proxy_host, user=user_name, passwd=password, db=db_name, connect_timeout=5)
except pymysql.MySQLError as e:
    logger.error("ERROR: Unexpected error: Could not connect to MySQL instance.")
    logger.error(e)
    sys.exit(1)

logger.info("SUCCESS: Connection to RDS for MySQL instance succeeded")

def lambda_handler(event, context):
    """
    This function creates a new RDS database table and writes records to it
    """
    message = event['Records'][0]['body']
    data = json.loads(message)
    CustID = data['CustID']
    Name = data['Name']

    item_count = 0
    sql_string = f"insert into Customer (CustID, Name) values(%s, %s)"

    with conn.cursor() as cur:
        cur.execute("create table if not exists Customer ( CustID  int NOT NULL, Name varchar(255) NOT NULL, PRIMARY KEY (CustID))")
        cur.execute(sql_string, (CustID, Name))
        conn.commit()
        cur.execute("select * from Customer")
        logger.info("The following items have been added to the database:")
        for row in cur:
            item_count += 1
            logger.info(row)
    conn.commit()

    return "Added %d items to RDS for MySQL table" %(item_count)
```

**注意**  
在此範例中，您的資料庫存取憑證會儲存為環境變數。在生產應用程式中，我們建議您將 [AWS Secrets Manager](https://docs.aws.amazon.com/secretsmanager/latest/userguide/intro.html) 用作更安全的選項。請注意，如果您的 Lambda 函數在 VPC 中，若要連線到 Secrets Manager，您需要建立 VPC 端點。請參閱 [How to connect to Secrets Manager service within a Virtual Private Cloud](https://aws.amazon.com/blogs/security/how-to-connect-to-aws-secrets-manager-service-within-a-virtual-private-cloud/)，以了解更多內容。

 若要在函數程式碼中包含 PyMySQL 相依性，請建立 .zip 部署套件。下列指令適用於 Linux、macOS 或 Unix：

**建立 .zip 部署套件的方式**

1. 將程式碼範例儲存為名為 `lambda_function.py` 的檔案。

1. 在您建立 `lambda_function.py` 檔案的同一個目錄中，建立名為 `package` 的新目錄並安裝 PyMySQL 程式庫。

   ```
   mkdir package
   pip install --target package pymysql
   ```

1. 建立一個包含應用程式程式碼和 PyMySQL 程式庫的 zip 檔案。在 Linux 或 MacOS 中，執行下列 CLI 命令。在 Windows 中，使用您偏好的 zip 工具建立 `lambda_function.zip` 檔案。您的 `lambda_function.py` 原始程式碼檔案和包含相依項的資料夾必須安裝在 .zip 檔案的根目錄中。

   ```
   cd package
   zip -r ../lambda_function.zip .
   cd ..
   zip lambda_function.zip lambda_function.py
   ```

   您也可以使用 Python 虛擬環境建立部署套件。請參閱[使用 .zip 封存檔部署 Python Lambda 函數](https://docs.aws.amazon.com/lambda/latest/dg/python-package.html#python-package-create-package-with-dependency)

## 更新 Lambda 函數
<a name="vpc-rds-update-function"></a>

現在您可以使用剛才建立的 .zip 套件，使用 Lambda 主控台更新 Lambda 函數。若要讓函數存取資料庫，還需要使用存取憑證來設定環境變數。

**更新 Lambda 函數**

1. 開啟 Lambda 主控台的[函數](https://console.aws.amazon.com/lambda/home#/functions)頁面，然後選擇您的函數 `LambdaFunctionWithRDS`。

1. 在**執行階段設定**索引標籤中選取**編輯**，將函數的**執行階段**變更為 **Python 3.10**。

1. 將**處理器**變更為 `lambda_function.lambda_handler`。

1. 在**程式碼**標籤中，選擇**上傳來源**，然後選擇 **.zip 檔案**。

1. 選取您在上一個階段建立的 `lambda_function.zip` 檔案，然後選擇**儲存**。

現在，請使用您先前建立的執行角色設定函數。這會授予函數存取資料庫執行個體和輪詢 Amazon SQS 佇列所需的許可。

**函數的執行角色。**

1. 在 Lambda 主控台的[函數](https://console.aws.amazon.com/lambda/home#/functions)頁面中，選取**組態**索引標籤，然後選擇**許可**。

1. 在**執行角色**中，選擇**編輯**。

1. 在**現有角色**中，選擇您的執行角色 (`lambda-vpc-sqs-role`)。

1. 選擇**儲存**。

**設定函數的環境變數**

1. 在 Lambda 主控台的[函數](https://console.aws.amazon.com/lambda/home#/functions)頁面中，選取**組態**索引標籤，然後選擇**環境變數**。

1. 選擇**編輯**。

1. 若要新增資料庫存取憑證，請執行下列動作：

   1. 選擇**新增環境變數**，然後針對**索引鍵**輸入 **USER\$1NAME**，針對**值**輸入 **admin**。

   1. 選擇**新增環境變數**，然後針對**索引鍵**輸入 **DB\$1NAME**，針對**值**輸入 **ExampleDB**。

   1. 選擇**新增環境變數**，然後針對**索引鍵**輸入 **PASSWORD**，針對**值**輸入您在建立資料庫時選擇的密碼。

   1. 選擇**新增環境變數**，然後針對**索引鍵**輸入 **RDS\$1PROXY\$1HOST**，針對**值**輸入您先前備註的 RDS Proxy 端點。

   1. 選擇**儲存**。

## 在主控台中測試您的 Lambda 函數
<a name="vpc-rds-test-function"></a>

![\[\]](http://docs.aws.amazon.com/zh_tw/AmazonRDS/latest/UserGuide/images/TUT_Lambda_step5.png)


您現在可使用 Lambda 主控台來測試您的函數。請建立一個測試事件，該事件會模擬您在教學課程的最後階段中，使用 Amazon SQS 調用函數時會接收到的資料。測試事件會包含一個 JSON 物件，指定要新增到函數所建立 `Customer` 資料表中的客戶 ID 和客戶名稱。

**測試 Lambda 函數**

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

1. 選擇**測試**區段。

1. 選擇**建立新活動**並輸入 **myTestEvent** 對於事件的名稱。

1. 將下列程式碼複製到**事件 JSON** 中，然後選擇**儲存**。

   ```
   {
     "Records": [
       {
         "messageId": "059f36b4-87a3-44ab-83d2-661975830a7d",
         "receiptHandle": "AQEBwJnKyrHigUMZj6rYigCgxlaS3SLy0a...",
         "body": "{\n     \"CustID\": 1021,\n     \"Name\": \"Martha Rivera\"\n}",
         "attributes": {
           "ApproximateReceiveCount": "1",
           "SentTimestamp": "1545082649183",
           "SenderId": "AIDAIENQZJOLO23YVJ4VO",
           "ApproximateFirstReceiveTimestamp": "1545082649185"
         },
         "messageAttributes": {},
         "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3",
         "eventSource": "aws:sqs",
         "eventSourceARN": "arn:aws:sqs:us-west-2:123456789012:my-queue",
         "awsRegion": "us-west-2"
       }
     ]
   }
   ```

1. 選擇**測試**。

在**執行結果**索引標籤中，您應該會看到類似**函數日誌**中顯示的結果：

```
[INFO] 2023-02-14T19:31:35.149Z bdd06682-00c7-4d6f-9abb-89f4bbb4a27f The following items have been added to the database:
[INFO] 2023-02-14T19:31:35.149Z bdd06682-00c7-4d6f-9abb-89f4bbb4a27f (1021, 'Martha Rivera')
```

## 建立 Amazon SQS 佇列
<a name="vpc-rds-create-queue"></a>

![\[\]](http://docs.aws.amazon.com/zh_tw/AmazonRDS/latest/UserGuide/images/TUT_Lambda_step6.png)


您已成功測試 Lambda 函數和 Amazon RDS 資料庫執行個體的整合。現在請建立 Amazon SQS 佇列，用於在教學課程的最後階段調用您的 Lambda 函數。

**建立 Amazon SQS 佇列的方式 (主控台)**

1. 開啟 Amazon SQS 主控台的[佇列](https://console.aws.amazon.com/sqs/v2/home#/queues)頁面，然後選取**建立佇列**。

1. 將**類型**保留為**標準**，然後在佇列名稱輸入 **LambdaRDSQueue**。

1. 保持選取所有預設選項，然後選擇**建立佇列**。

## 建立事件來源映射以調用 Lambda 函數
<a name="vpc-rds-create-event-source-mapping"></a>

![\[\]](http://docs.aws.amazon.com/zh_tw/AmazonRDS/latest/UserGuide/images/TUT_Lambda_step7.png)


[事件來源映射](https://docs.aws.amazon.com/lambda/latest/dg/invocation-eventsourcemapping.html)是一種 Lambda 資源，它可從串流或佇列中讀取項目並調用 Lambda 函數。設定事件來源映射時，您可以指定批次大小，以便將串流或佇列中的記錄批次處理成單一承載。在此範例中，您將批次大小設定為 1，以便在每次傳送訊息到佇列時都調用 Lambda 函數。您可以使用 AWS CLI 或 Lambda 主控台來設定事件來源映射。

**建立事件來源映射的方式 (主控台)**

1. 開啟 Lambda 主控台的[函數](https://console.aws.amazon.com/lambda/home#/functions)頁面，然後選擇您的函數 (`LambdaFunctionWithRDS`)。

1. 在**函數概觀**區段中，選擇**新增觸發條件**。

1. 來源請選取 **Amazon SQS**，然後選取佇列的名稱 (`LambdaRDSQueue`)。

1. **批次大小**請輸入 **1**。

1. 將所有其他選項設定保留為預設值，然後選擇**新增**。

您現在可以透過將訊息新增至 Amazon SQS 佇列以測試完整的設定。

## 測試和監控設定
<a name="vpc-rds-test-setup"></a>

![\[\]](http://docs.aws.amazon.com/zh_tw/AmazonRDS/latest/UserGuide/images/TUT_Lambda_step8.png)


若要測試完整的設定，請使用主控台將訊息新增至 Amazon SQS 佇列。然後您可以使用 CloudWatch Logs 確認 Lambda 函數正如預期將記錄寫入資料庫。

**測試和監控設定的方式**

1. 開啟 Amazon SQS 主控台的[佇列](https://console.aws.amazon.com/sqs/v2/home#/queues)頁面，然後選取您的佇列 (`LambdaRDSQueue`)。

1. 選擇**傳送和接收訊息**，然後將以下 JSON 貼到**傳送訊息**區段裡的**訊息內文**中。

   ```
   {
       "CustID": 1054,
       "Name": "Richard Roe"
   }
   ```

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

   將訊息傳送至佇列會導致 Lambda 透過事件來源映射調用您的函數。若要確認 Lambda 已如預期調用您的函數，請使用 CloudWatch Logs 確認函數是否已將客戶名稱和 ID 寫入您的資料庫資料表中。

1. 開啟 CloudWatch 主控台的[日誌群組](https://console.aws.amazon.com/cloudwatch/home#logsV2:log-groups)頁面，然後為您的函數選取日誌群組 (`/aws/lambda/LambdaFunctionWithRDS`)。

1. 在**日誌串流**區段中，選擇最新的日誌串流。

   您的資料表應該會包含兩個客戶記錄，分別來自您的函數的每次調用。在日誌串流中，您應該會看到類似以下的訊息：

   ```
   [INFO] 2023-02-14T19:06:43.873Z 45368126-3eee-47f7-88ca-3086ae6d3a77 The following items have been added to the database:
   [INFO] 2023-02-14T19:06:43.873Z 45368126-3eee-47f7-88ca-3086ae6d3a77 (1021, 'Martha Rivera')
   [INFO] 2023-02-14T19:06:43.873Z 45368126-3eee-47f7-88ca-3086ae6d3a77 (1054, 'Richard Roe')
   ```

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

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

**若要刪除 Lambda 函數**

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

1. 選擇您建立的函數。

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

1. 選擇 **Delete** (刪除)。

**若要刪除執行角色**

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

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

1. 選擇 **Delete role** (刪除角色)。

1. 選擇 **Yes, delete (是，刪除)**。

**刪除 MySQL 資料庫執行個體**

1. 在 Amazon RDS 主控台開啟 [Databases (資料庫) 頁面](https://console.aws.amazon.com//rds/home#databases:)。

1. 選取您建立的資料庫。

1. 選擇 **動作**、**刪除**。

1. 取消勾選 **建立最終快照** 核取方塊。

1. 在文字方塊中輸入 **delete me**。

1. 選擇 **刪除** 。

**刪除 Amazon SQS 佇列**

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

1. 選取您建立的佇列。

1. 選擇 **刪除** 。

1. 在文字方塊中輸入 **delete**。

1. 選擇**刪除**。