在雲端架構中,訊息傳遞和通知扮演著至關重要的角色。本文將示範如何利用 AWS Lambda、SNS 和 SQS 構建一個高效的訊息處理系統。首先,我們會使用 CloudFormation 建立 SNS 主題,並透過 AWS CLI 建立 SMS 和 Email 訂閱。接著,我們將探討如何使用 Java SDK 在 Lambda 函式中釋出訊息到 SNS 主題,並示範如何使用 AWS CLI 佈署和測試 Lambda 函式。最後,我們將介紹如何使用 SNS 事件觸發 Lambda 函式,並提供完整的程式碼範例和逐步操作。此架構能讓開發者更有效率地處理訊息,並確保訊息的可靠傳遞和通知。
使用 SQS 和 SNS 進行訊息傳遞和通知(第六章)
建立 SNS 主題與訂閱
在前面的章節中,我們已經瞭解瞭如何使用 AWS CLI 和 CloudFormation 建立 SNS 主題。本文將探討如何建立 SNS 主題、建立訂閱以及發布訊息至該主題。
使用 CloudFormation 建立 SNS 主題
以下是一個 CloudFormation 範本,用於建立 SNS 主題並輸出其 ARN 和名稱:
Resources:
SNSTopic:
Type: 'AWS::SNS::Topic'
Properties:
TopicName: !Sub 'my-first-sns-topic-${AWS::Region}'
Outputs:
SNSTopicARN:
Value: !Ref SNSTopic
Export:
Name: "SNSTopicARN"
SNSTopicName:
Value: !GetAtt SNSTopic.TopicName
Export:
Name: "SNSTopicName"
此範本建立了一個 SNS 主題,並將其 ARN 和名稱作為輸出,以便在其他堆積疊中使用。
建立 SMS 和電子郵件訂閱
使用 AWS CLI 可以建立 SMS 和電子郵件訂閱,如下所示:
SMS 訂閱
aws sns subscribe \
--topic-arn arn:aws:sns:us-east-1:<account id>:my-first-sns-topic \
--protocol sms \
--notification-endpoint +917411174114 \
--profile admin
此命令建立了一個 SMS 訂閱,將訊息傳送至指定的手機號碼。
電子郵件訂閱
aws sns subscribe \
--topic-arn arn:aws:sns:us-east-1:<account id>:my-first-sns-topic \
--protocol email \
--notification-endpoint serverlesscookbook@gmail.com \
--profile admin
此命令建立了一個電子郵件訂閱,將訊息傳送至指定的電子郵件地址。
發布訊息至 SNS 主題
使用以下命令可以發布訊息至 SNS 主題:
aws sns publish \
--topic-arn arn:aws:sns:us-east-1:<account id>:my-first-sns-topic \
--message "sending message to both mobile and email" \
--profile admin
此命令發布了一則訊息至 SNS 主題,該訊息將被傳送至所有訂閱者。
使用 Java SDK 發布訊息至 SNS 主題
在前面的章節中,我們瞭解瞭如何使用 AWS CLI 發布訊息至 SNS 主題。本文將介紹如何使用 Java SDK 發布訊息至 SNS 主題。
Lambda 專案程式碼(Java)
首先,建立一個 Java Lambda 專案,並在 pom.xml 檔案中新增以下相依性:
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-sns</artifactId>
<version>${aws.sdk.version}</version>
</dependency>
接下來,建立一個 Request 類別,用於接收輸入 JSON:
@Data
public class Request {
private String topicArn;
private String message;
}
然後,建立一個 LambdaSnsPublishHandler 類別,用於處理 Lambda 請求:
public class LambdaSnsPublishHandler {
private final AmazonSNS snsClient;
public LambdaSnsPublishHandler() {
this.snsClient = AmazonSNSClientBuilder.standard()
.withRegion(System.getenv("AWS_REGION"))
.build();
}
public String handleRequest(final Request request, final Context context) {
final PublishResult result;
try {
PublishRequest publishRequest = new PublishRequest(request.getTopicArn(), request.getMessage());
result = snsClient.publish(publishRequest);
} catch (Exception e) {
return "Exception occurred: " + e.getMessage();
}
// ...
}
}
在此範例中,我們使用 AmazonSNSClientBuilder 建立了一個 SNS 使用者端,並使用 publish 方法發布訊息至 SNS 主題。
程式碼解析
- 建立 SNS 使用者端:使用
AmazonSNSClientBuilder建立了一個 SNS 使用者端,並設定了區域。 - 發布訊息:使用
publish方法發布訊息至 SNS 主題,並傳遞了PublishRequest物件。 - 錯誤處理:捕捉了例外狀況,並傳回錯誤訊息。
使用 SQS 和 SNS 進行訊息傳遞與通知(第六章)
使用 Java SDK 釋出訊息至 SNS 主題
本章節將介紹如何使用 Java SDK 在 Lambda 函式中釋出訊息至 SNS 主題。首先,我們需要建立一個 Java Lambda 專案,並在 pom.xml 檔案中加入 AWS Java SDK 的依賴。
Lambda 專案程式碼(Java)
public class LambdaSnsPublishHandler {
public String handleRequest(Map<String, String> input, Context context) {
// 初始化 SNS Client
AmazonSNS snsClient = AmazonSNSClientBuilder.standard()
.withRegion(System.getenv("AWS_REGION"))
.build();
// 釋出訊息至 SNS 主題
PublishRequest publishRequest = new PublishRequest(
input.get("topicArn"),
input.get("message")
);
PublishResult result = snsClient.publish(publishRequest);
// 傳回訊息 ID
return "Message Id: " + result.getMessageId();
}
}
內容解密:
- 初始化 SNS Client:使用
AmazonSNSClientBuilder建立 SNS Client,並指定 AWS 區域。 - 釋出訊息至 SNS 主題:建立
PublishRequest物件,指定 SNS 主題的 ARN 和要釋出的訊息。 - 傳回訊息 ID:釋出訊息後,傳回訊息的 ID。
使用 AWS CLI 佈署和測試 Lambda 函式
步驟如下:
- 封裝 Lambda 專案:執行
mvn clean package命令,將專案封裝成 Uber JAR。 - 上傳 Uber JAR 至 S3:使用 AWS CLI 將 Uber JAR 上傳至 S3 Bucket。
aws s3 cp target/lambda-sns-publish-with-sdk-0.0.1-SNAPSHOT.jar s3://serverless-cookbook/lambda-sns-publish-with-sdk-0.0.1-SNAPSHOT.jar --profile admin
- 建立 Lambda 執行角色:建立一個 IAM 角色,並附加必要的許可權。
- 建立 Lambda 函式:使用 AWS CLI 建立 Lambda 函式,並指定執行角色和處理程式。
aws lambda create-function --function-name lambda-sns-publish-with-sdk --runtime java8 --role arn:aws:iam::855923912133:role/lambda-sns-publish-with-sdk-role --handler tech.heartin.books.serverlesscookbook.LambdaSnsPublishHandler::handleRequest --code S3Bucket=serverless-cookbook,S3Key=lambda-sns-publish-with-sdk-0.0.1-SNAPSHOT.jar --timeout 15 --memory-size 512 --region us-east-1 --profile admin
- 測試 Lambda 函式:使用 AWS CLI 呼叫 Lambda 函式,並傳遞測試資料。
aws lambda invoke --invocation-type RequestResponse --function-name lambda-sns-publish-with-sdk --log-type Tail --payload file://payload.json --region us-east-1 --profile admin outputfile.txt
內容解密:
- 封裝和上傳 Lambda 專案:將專案封裝成 Uber JAR,並上傳至 S3 Bucket。
- 建立和組態 Lambda 函式:建立 Lambda 函式,並指定執行角色、處理程式和必要的組態。
- 測試 Lambda 函式:呼叫 Lambda 函式,並驗證其是否正確執行。
使用 SNS 事件呼叫 Lambda 函式(Java)
本章節將介紹如何使用 SNS 事件呼叫 Lambda 函式。首先,我們需要建立一個 Java Lambda 專案,並在 pom.xml 檔案中加入 AWS Java SDK 的依賴。
Lambda 專案程式碼(Java)
public class LambdaSnsEventHandler {
private final AmazonSQS sqsClient;
public LambdaSnsEventHandler() {
this.sqsClient = AmazonSQSClientBuilder.standard()
.withRegion(System.getenv("AWS_REGION"))
.build();
}
public Boolean handleRequest(final SNSEvent snsEvent, final Context context) {
context.getLogger().log("Received SQS event: " + snsEvent);
final SnsService snsService = new SnsServiceImpl(this.sqsClient);
return snsService.processEvent(snsEvent, System.getenv("SPC_OUTPUT_QUEUE_URL"), context.getLogger());
}
}
內容解密:
- 初始化 SQS Client:使用
AmazonSQSClientBuilder建立 SQS Client,並指定 AWS 區域。 - 處理 SNS 事件:建立
SnsService物件,並呼叫其processEvent方法處理 SNS 事件。 - 傳回處理結果:傳回處理結果的布林值。
使用 SQS 和 SNS 進行訊息傳遞與通知(第六章)
使用 AWS CLI 組態 Lambda
要佈署並呼叫 Lambda,請按照以下步驟進行:
建立 Uber JAR 檔案:在 Lambda 專案的根資料夾中執行
mvn clean package以建立 Uber JAR。將 Uber JAR 上傳到 S3:
aws s3 cp \ target/lambda-invoke-sns-event-0.0.1-SNAPSHOT.jar \ s3://serverless-cookbook/lambda-invoke-sns-event-0.0.1-SNAPSHOT.jar \ --profile admin為 Lambda 建立角色:使用適當的信任關係定義建立角色。
aws iam create-role \ --role-name lambda-invoke-sns-event-role \ --assume-role-policy-document file://iam-role-trust-relationship.txt \ --profile admin建立基本日誌記錄許可權的策略並將其附加到角色。
建立所需的 SQS 許可權策略並將其附加到角色。所需的 SQS 許可權策略如下:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "sqs:SendMessage", "sqs:SendMessageBatch" ], "Resource": [ "arn:aws:sqs:*:*:*" ] } ] }內容解密:
- 此策略允許 Lambda 向 SQS 佇列傳送訊息。
sqs:SendMessage和sqs:SendMessageBatch是必要的動作,因為 Lambda 需要將接收到的訊息寫入佇列。
建立 Lambda 函式:
aws lambda create-function \ --function-name lambda-invoke-sns-event \ --runtime java8 \ --role arn:aws:iam::<account id>:role/lambda-invoke-sns-event-role \ --handler tech.heartin.books.serverlesscookbook.LambdaSnsEventHandler::handleRequest \ --code S3Bucket=serverless-cookbook,S3Key=lambda-invoke-sns-event-0.0.1-SNAPSHOT.jar \ --environment Variables={SPC_OUTPUT_QUEUE_URL='https://queue.amazonaws.com/855923912133/my-output-queue'} \ --timeout 15 \ --memory-size 512 \ --region us-east-1 \ --profile admin內容解密:
- 此命令建立了一個名為
lambda-invoke-sns-event的 Lambda 函式。 - 指定了執行角色、處理程式、程式碼位置、環境變數、超時和記憶體大小。
- 此命令建立了一個名為
將 Lambda 訂閱到佇列:
aws sns subscribe --topic-arn arn:aws:sns:us-east-1:<account id>:lambda-invoke-sns-topic \ --protocol lambda \ --notification-endpoint arn:aws:lambda:us-east-1:<account id>:function:lambda-invoke-sns-event \ --profile admin內容解密:
- 此命令將 Lambda 函式訂閱到指定的 SNS 主題。
測試 Lambda(使用 AWS CLI)
- 向主題傳送訊息。
- 透過從輸出佇列檢索訊息來驗證呼叫:
aws sqs receive-message \ --queue-url https://queue.amazonaws.com/<account id>/my-output-queue \ --max-number-of-messages 5 \ --profile admin內容解密:
- 此命令從指定的 SQS 佇列接收訊息,以驗證 Lambda 函式是否正確處理了 SNS 事件。
更多資訊
SNS 可以將訊息扇出到多個 SQS 佇列,用於平行處理等場景。這種模式通常被稱為扇出模式。