本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。
您可以直接或透過 Amazon RDS Proxy 將 Lambda 函數連線到 Amazon Relational Database Service (Amazon RDS)。直接連線適用於簡單的案例,生產環境則建議使用代理。資料庫代理管理許多共用資料庫連線,讓函數在不耗盡資料庫連線的情況下達到高並行層級。
我們建議將 Amazon RDS Proxy 用於 Lambda 函數,這些函數會頻繁進行短資料庫連線,或是開啟和關閉大量資料庫連線。如需詳細資訊,請參閱《Amazon Relational Database Service 開發人員指南》中的 Automatically connecting a Lambda function and a DB instance 一節。
提示
若要將 Lambda 函數快速連線至 Amazon RDS 資料庫,您可以使用主控台內引導式精靈。若要開啟精靈,請執行下列動作:
開啟 Lambda 主控台中的函數頁面
。 -
選取您要連接資料庫的函數。
-
在組態索引標籤上,選取 RDS 資料庫。
-
選擇連線至 RDS 資料庫。
將函數連線至資料庫之後,您可以選擇新增代理來建立代理。
設定函數以使用 RDS 資源
在 Lambda 主控台中,您可以佈建和設定 Amazon RDS 資料庫執行個體和代理資源。您可以在組態索引標籤下導覽至 RDS 資料庫來執行此操作。或者,您也可以在 Amazon RDS 主控台中建立與設定 Lambda 函數的連線。設定 RDS 資料庫執行個體以與 Lambda 搭配使用時,請注意以下條件:
-
若要連線到資料庫,您的函數必須位於資料庫執行所在的相同 Amazon VPC 內。
-
您可以搭配 MySQL、MariaDB、PostgreSQL 或 Microsoft SQL Server 引擎,使用 Amazon RDS 資料庫。
-
您也可以搭配 MySQL 或 PostgreSQL 引擎,使用 Aurora DB 叢集。
-
您需要提供 Secrets Manager 秘密以用於資料庫身分驗證。
-
IAM 角色必須提供使用秘密的許可,而受信任的政策必須允許 Amazon RDS 擔任該角色。
-
使用主控台設定 Amazon RDS 資源,並將其連線至函數的 IAM 主體必須具有下列許可:
注意
只有在您設定 Amazon RDS Proxy 來管理資料庫連線集區時,才需要這些 Amazon RDS Proxy 許可。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ec2:CreateSecurityGroup",
"ec2:DescribeSecurityGroups",
"ec2:DescribeSubnets",
"ec2:DescribeVpcs",
"ec2:AuthorizeSecurityGroupIngress",
"ec2:AuthorizeSecurityGroupEgress",
"ec2:RevokeSecurityGroupEgress",
"ec2:CreateNetworkInterface",
"ec2:DeleteNetworkInterface",
"ec2:DescribeNetworkInterfaces"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"rds-db:connect",
"rds:CreateDBProxy",
"rds:CreateDBInstance",
"rds:CreateDBSubnetGroup",
"rds:DescribeDBClusters",
"rds:DescribeDBInstances",
"rds:DescribeDBSubnetGroups",
"rds:DescribeDBProxies",
"rds:DescribeDBProxyTargets",
"rds:DescribeDBProxyTargetGroups",
"rds:RegisterDBProxyTargets",
"rds:ModifyDBInstance",
"rds:ModifyDBProxy"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"lambda:CreateFunction",
"lambda:ListFunctions",
"lambda:UpdateFunctionConfiguration"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"iam:AttachRolePolicy",
"iam:AttachPolicy",
"iam:CreateRole",
"iam:CreatePolicy"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"secretsmanager:GetResourcePolicy",
"secretsmanager:GetSecretValue",
"secretsmanager:DescribeSecret",
"secretsmanager:ListSecretVersionIds",
"secretsmanager:CreateSecret"
],
"Resource": "*"
}
]
}
Amazon RDS 會按資料庫執行個體大小收取代理程式的小時費率,請參閱 RDS 代理定價
Amazon RDS 連線的 SSL/TLS 要求
若要對 Amazon RDS 資料庫執行個體進行安全的 SSL/TLS 連線,您的 Lambda 函數必須使用信任的憑證驗證資料庫伺服器的身分。Lambda 會根據您的部署套件類型,以不同的方式處理這些憑證:
-
.zip 檔案封存:Lambda 的受管執行期包括憑證授權機構 (CA) 憑證和連線到 Amazon RDS 資料庫執行個體所需的憑證。Amazon RDS 憑證最多可能需要 4 週 AWS 區域 才能將新的 新增至 Lambda 受管執行期。
-
容器映像: AWS 基礎映像僅包含 CA 憑證。如果您的 函數連線到 Amazon RDS 資料庫執行個體,您必須在容器映像中包含適當的憑證。在 Dockerfile 中,下載與您託管資料庫 AWS 區域 的 對應的憑證套件。範例:
RUN curl
https://truststore.pki.rds.amazonaws.com/us-east-1/us-east-1-bundle.pem
-o/us-east-1-bundle.pem
此命令會下載 Amazon RDS 憑證套件,並將其儲存在/us-east-1-bundle.pem
容器根目錄中的絕對路徑。在函數程式碼中設定資料庫連線時,您必須參考此確切路徑。範例:
因為 Node.js 資料庫用戶端需要記憶體中的實際憑證內容,而不只是憑證檔案的路徑,所以需要 readFileSync
函數。如果沒有 readFileSync
,用戶端會將路徑字串解譯為憑證內容,導致「憑證鏈中的自我簽署憑證」錯誤。
範例 OCI 函數的 Node.js 連線組態
import { readFileSync } from 'fs';
// ...
let connectionConfig = {
host: process.env.ProxyHostName,
user: process.env.DBUserName,
password: token,
database: process.env.DBName,
ssl: {
ca: readFileSync('/us-east-1-bundle.pem')
// Load RDS certificate content from file into memory
}
};
連線至 Lambda 函數中的 Amazon RDS 資料庫
下列程式碼範例示範如何實作連線至 Amazon RDS 資料庫的 Lambda 函數。該函數會提出簡單的資料庫請求並傳回結果。
- 適用於 .NET 的 SDK
-
注意
GitHub 上提供更多範例。尋找完整範例,並了解如何在無伺服器範例
儲存庫中設定和執行。 使用 .NET 連接到 Lambda 函數中的 Amazon RDS 資料庫。
using System.Data; using System.Text.Json; using Amazon.Lambda.APIGatewayEvents; using Amazon.Lambda.Core; using MySql.Data.MySqlClient; // 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 aws_rds; public class InputModel { public string key1 { get; set; } public string key2 { get; set; } } public class Function { /// <summary> // Handles the Lambda function execution for connecting to RDS using IAM authentication. /// </summary> /// <param name="input">The input event data passed to the Lambda function</param> /// <param name="context">The Lambda execution context that provides runtime information</param> /// <returns>A response object containing the execution result</returns> public async Task<APIGatewayProxyResponse> FunctionHandler(APIGatewayProxyRequest request, ILambdaContext context) { // Sample Input: {"body": "{\"key1\":\"20\", \"key2\":\"25\"}"} var input = JsonSerializer.Deserialize<InputModel>(request.Body); /// Obtain authentication token var authToken = RDSAuthTokenGenerator.GenerateAuthToken( Environment.GetEnvironmentVariable("RDS_ENDPOINT"), Convert.ToInt32(Environment.GetEnvironmentVariable("RDS_PORT")), Environment.GetEnvironmentVariable("RDS_USERNAME") ); /// Build the Connection String with the Token string connectionString = $"Server={Environment.GetEnvironmentVariable("RDS_ENDPOINT")};" + $"Port={Environment.GetEnvironmentVariable("RDS_PORT")};" + $"Uid={Environment.GetEnvironmentVariable("RDS_USERNAME")};" + $"Pwd={authToken};"; try { await using var connection = new MySqlConnection(connectionString); await connection.OpenAsync(); const string sql = "SELECT @param1 + @param2 AS Sum"; await using var command = new MySqlCommand(sql, connection); command.Parameters.AddWithValue("@param1", int.Parse(input.key1 ?? "0")); command.Parameters.AddWithValue("@param2", int.Parse(input.key2 ?? "0")); await using var reader = await command.ExecuteReaderAsync(); if (await reader.ReadAsync()) { int result = reader.GetInt32("Sum"); //Sample Response: {"statusCode":200,"body":"{\"message\":\"The sum is: 45\"}","isBase64Encoded":false} return new APIGatewayProxyResponse { StatusCode = 200, Body = JsonSerializer.Serialize(new { message = $"The sum is: {result}" }) }; } } catch (Exception ex) { Console.WriteLine($"Error: {ex.Message}"); } return new APIGatewayProxyResponse { StatusCode = 500, Body = JsonSerializer.Serialize(new { error = "Internal server error" }) }; } }
處理來自 Amazon RDS 的事件通知
您可以使用 Lambda 來處理 Amazon RDS 資料庫的事件通知。Amazon RDS 會將通知傳送到 Amazon Simple Notification Service (Amazon SNS) 主題,您可以進行設定,透過該主題叫用 Lambda 函數。Amazon SNS 會將來自 Amazon RDS 的訊息包裝在自己的事件文件中,並將其傳送到函數。
如需設定 Amazon RDS 資料庫以傳送通知的詳細資訊,請參閱使用 Amazon RDS 事件通知。
範例 Amazon SNS 事件中的 Amazon RDS 訊息
{ "Records": [ { "EventVersion": "1.0", "EventSubscriptionArn": "arn:aws:sns:us-east-2:123456789012:rds-lambda:21be56ed-a058-49f5-8c98-aedd2564c486", "EventSource": "aws:sns", "Sns": { "SignatureVersion": "1", "Timestamp": "2023-01-02T12:45:07.000Z", "Signature": "tcc6faL2yUC6dgZdmrwh1Y4cGa/ebXEkAi6RibDsvpi+tE/1+82j...65r==", "SigningCertUrl": "https://sns.us-east-2.amazonaws.com/SimpleNotificationService-ac565b8b1a6c5d002d285f9598aa1d9b.pem", "MessageId": "95df01b4-ee98-5cb9-9903-4c221d41eb5e", "Message":
"{\"Event Source\":\"db-instance\",\"Event Time\":\"2023-01-02 12:45:06.000\",\"Identifier Link\":\"https://console.aws.amazon.com/rds/home?region=eu-west-1#dbinstance:id=dbinstanceid\",\"Source ID\":\"dbinstanceid\",\"Event ID\":\"http://docs.amazonwebservices.com/AmazonRDS/latest/UserGuide/USER_Events.html#RDS-EVENT-0002\",\"Event Message\":\"Finished DB Instance backup\"}",
"MessageAttributes": {}, "Type": "Notification", "UnsubscribeUrl": "https://sns.us-east-2.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:us-east-2:123456789012:test-lambda:21be56ed-a058-49f5-8c98-aedd2564c486", "TopicArn":"arn:aws:sns:us-east-2:123456789012:sns-lambda", "Subject": "RDS Notification Message" } } ] }
完成 Lambda 和 Amazon RDS 教學課程
-
使用 Lambda 函數來存取 Amazon RDS:在《Amazon RDS 誰用著指南》中,學習如何使用 Lambda 函數並透過 Amazon RDS Proxy 將資料寫入 Amazon RDS 資料庫。每當新增訊息,您的 Lambda 函數將從 Amazon SQS 佇列中讀取記錄,然後將新項目寫入資料庫中的資料表。