使用 AWS Step Functions 實作無伺服器傳奇模式 - AWS 方案指引

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

使用 AWS Step Functions 實作無伺服器傳奇模式

由虎斑病房(AWS),羅漢·梅赫塔(AWS)和雲紋特瓦尼(AWS)創建

環境:PoC 或試點

技術:現代化、無伺服器、雲端原生

工作負載:開源

AWS 服務:Amazon API Gateway;Amazon DynamoDB;AWS Lambda;Amazon SNS;AWS Step Functions

Summary

在微服務架構中,主要目標是建立分離且獨立的元件,以提升應用程式的敏捷性、彈性和更快的上市時間。解耦的結果是,每個微服務元件都有自己的資料持續性層。在分散式架構中,商業交易可以跨越多個微服務。由於這些微服務不能使用單個原子性,一致性,隔離性,耐久性(ACID)事務,因此您最終可能會得到部分事務。在這種情況下,需要一些控制邏輯來復原已經處理的交易。分佈式傳奇模式通常用於此目的。 

saga 模式是一種失敗管理模式,可協助建立分散式應用程式的一致性,並協調多個微服務之間的交易,以維持資料一致性。當您使用 saga 模式時,每個執行交易的服務都會發佈觸發後續服務的事件,以執行鏈結中的下一個交易。這會持續到鏈結中的最後一個交易完成為止。如果商業交易失敗,saga 會協調一系列補償交易,這些交易會復原先前交易所做的變更。

此模式示範如何使用 AWS 步驟函數、AWS Lambda 和 Amazon DynamoDB 等無伺服器技術,自動化範例應用程式 (用於處理旅行預訂) 的設定和部署。範例應用程式還使用 Amazon API Gateway 和亞馬遜簡單通知服務 (Amazon SNS) 來實作傳奇執行協調器。您可以使用基礎設施即程式碼 (IaC) 架構來部署該模式,例如 AWS Cloud Development Kit (AWS CDK)、AWS Serverless Application Model (AWS SAM) 或地形。

如需傳奇模式和其他資料持續性模式的詳細資訊,請參閱 AWS Prescriptive Guidance 網站上的啟用微型服務中的資料持續性指南。

先決條件和限制

先決條件

  • 作用中的 AWS 帳戶

  • 建立 AWS CloudFormation 堆疊的許可。如需詳細資訊,請參閱 CloudFormation 文件中的控制存取

  • 您選擇的 IaC 框架 (AWS CDK、AWS SAM 或 Terraform) 使用您的 AWS 帳戶設定,以便您可以使用框架 CLI 部署應用程式。

  • NodeJS,用於構建應用程序並在本地運行它。

  • 您選擇的代碼編輯器(例如視覺工作室代碼,崇高或原子)。

產品版本

限制

事件來源是在微服務架構中實現 saga 協調流程模式的一種自然方式,其中所有組件都鬆散耦合,並且彼此沒有直接知識。如果您的交易涉及少量步驟(三到五個),那麼傳奇模式可能非常適合。然而,複雜性隨著微服務的數量和步驟的數量而增加。 

當您使用此設計時,測試和偵錯可能會變得困難,因為您必須讓所有服務都執行,才能模擬交易模式。

 

架構

目標架構

提議的架構使用 AWS Step Functions 建立傳奇模式來預訂航班、預訂租車和處理假期付款。

以下工作流程圖說明了旅行預訂系統的典型流程。該工作流程包括預訂航空旅行(「ReserveFlight」),預訂汽車(「ReserveCarRental」),處理付款(「ProcessPayment」),確認航班預訂(「ConfirmFlight」)以及確認汽車租賃(「ConfirmCarRental」),然後在完成這些步驟時發出成功通知。但是,如果系統在運行任何這些事務時遇到任何錯誤,它開始向後失敗。例如,付款處理錯誤 (「ProcessPayment」) 會觸發退款 (「RefundPayment」),然後觸發取消租車和航班 (「CancelRentalReservation」和「CancelFlightReservation」),結束整筆交易並顯示失敗訊息。

此模式會為圖中反白顯示的每個任務部署個別的 Lambda 函數,以及三個用於航班、汽車租賃和付款的 DynamoDB 表。每個 Lambda 函數會建立、更新或刪除個別 DynamoDB 表格中的資料列,具體取決於交易是否已確認或回復。該模式使用 Amazon SNS 向訂閱者傳送文字 (SMS) 訊息,通知他們交易失敗或成功。 

自動化和規模

您可以使用其中一個 IaC 框架來創建此架構的配置。使用以下鏈接之一為您首選的 IaC。

工具

AWS 服務

  • AWS Step Functions 是一種無伺服器協調服務,可讓您結合 AWS Lambda 函數和其他 AWS 服務來建立關鍵業務應用程式。透過 Step Functions 圖形化主控台,您可以將應用程式的工作流程視為一系列事件驅動的步驟。

  • Amazon DynamoDB 是全受管的 NoSQL 資料庫服務,可提供快速且可預測的效能以及無縫的可擴展性。您可以使用 DynamoDB 建立資料庫資料表,藉此存放和擷取任意數量的資料,並為任何層級的請求流量提供服務。

  • AWS Lambda 是一種運算服務,可讓您執行程式碼,而無需佈建或管理伺服器。Lambda 只有在需要時才會執行程式碼,可自動從每天數項請求擴展成每秒數千項請求。

  • Amazon API Gateway 是一種 AWS 服務,用於建立、發佈、維護、監控和保護任何規模的 REST、HTTP 和 WebSocket API。

  • Amazon Simple Notification Service (Amazon SNS) 是一種受管服務,可提供從發佈者傳送訊息給訂閱者的訊息。

  • AWS Cloud Development Kit (AWS CDK) 是一種軟體開發架構,可使用熟悉的程式設計語言 (例如 TypeScript、Python JavaScript、Java 和 C#/.net) 來定義雲端應用程式資源。

  • AWS Serverless Application Model (AWS SAM) 是用來建置無伺服器應用程式的開放原始碼架構。它提供速記語法來表示函數、API、資料庫和事件來源對應。

Code

示範傳奇模式的範例應用程式程式程式碼,包括 IaC 範本 (AWS CDK、AWS SAM 或地形)、Lambda 函數和 DynamoDB 表格,可在下列連結中找到。請按照第一部史詩中的說明進行安裝。

史诗

任務描述所需技能

安裝 NPM 套件。

建立新目錄、瀏覽至終端機中的該目錄,然後從此模式稍早的程式區段複製您選擇的 GitHub 存放庫。

在具有package.json檔案的根資料夾中,執行下列命令,以下載並安裝所有節點 Package 件管理員 (NPM) 套件:

npm install
雲端架構師開發人員

編譯腳本。

在根資料夾中,執行下列命令以指示 TypeScript 轉譯器建立所有必要 JavaScript 的檔案:

npm run build
雲端架構師開發人員

注意更改並重新編譯。

在根資料夾中,在個別的終端機視窗中執行下列命令以監視程式碼變更,並在偵測到變更時編譯程式碼:

npm run watch
雲端架構師開發人員

執行單元測試 (僅限 AWS CDK)。

如果您使用的是 AWS CDK,請在根文件夾中運行以下命令來執行 Jest 單元測試:

npm run test
雲端架構師開發人員
任務描述所需技能

將示範堆疊部署到 AWS。

重要:此應用程式與 AWS 區域無關。如果您使用設定檔,則必須在 AWS Command Line Interface (AWS CLI) (AWS CLI) 設定檔或透過 AWS CLI 環境變數明確宣告區域。

在根資料夾中,執行下列命令以建立部署組件,並將其部署到預設 AWS 帳戶和區域。

AWS 磁碟機:

cdk bootstrap cdk deploy

AWS 山姆:

sam build sam deploy --guided

地形:

terraform init terraform apply

此步驟可能需要幾分鐘才能完成。此命令使用針對 AWS CLI 設定的預設登入資料。

請注意部署完成後顯示在主控台上的 API Gateway URL。您將需要此信息來測試傳奇執行流程。

雲端架構師開發人員

將已部署的堆疊與目前狀態進行比較。

在根資料夾中,執行下列命令,在對原始程式碼進行變更後,將已部署的堆疊與目前狀態進行比較:

AWS 磁碟機:

cdk diff

AWS 山姆:

sam deploy

地形:

terraform plan
雲端架構師開發人員
任務描述所需技能

測試傳奇執行流程。

導覽至您在部署堆疊時在先前步驟中記下的 API Gateway URL。此 URL 會觸發狀態機啟動。如需有關如何透過傳遞不同 URL 參數來操作狀態機器流程的詳細資訊,請參閱其他資訊一節。

若要檢視結果,請登入 AWS 管理主控台並導覽至 Step Functions 主控台。在這裡,您可以看到傳奇狀態機的每一步。您也可以檢視 DynamoDB 表格,以查看插入、更新或刪除的記錄。如果您經常刷新屏幕,則可以觀察交易狀態從更改pendingconfirmed。 

您可以通過使用手機號碼更新stateMachine.ts文件中的代碼來訂閱 SNS 主題,以便在預訂成功或失敗時接收 SMS 消息。如需詳細資訊,請參閱其他資訊一節中的 Amazon SNS

雲端架構師開發人員
任務描述所需技能

清理資源。

若要清除為此應用程式部署的資源,您可以使用下列命令之一。

AWS 磁碟機:

cdk destroy

AWS 山姆:

sam delete

地形:

terraform destroy
應用程式開發人員、雲端

相關資源

技術論文

AWS 服務文件

教學課程

其他資訊

Code

基於測試目的,此模式會部署 API Gateway 和觸發 Step Functions 函數狀態機器的測試 Lambda 函數。使用 Step Functions,您可以通過傳遞run_type參數來模仿「,」,「」,「」ReserveFlight,「」和「。」中的故障來控制旅行預訂系統的功能ConfirmCarRental。ReserveCarRental ProcessPayment ConfirmFlight

sagaLambda 函數 (sagaLambda.ts) 會從 API Gateway URL 中的查詢參數接收輸入,建立下列 JSON 物件,並將其傳遞至 Step Functions 數以執行:

let input = { "trip_id": tripID, //  value taken from query parameter, default is AWS request ID "depart_city": "Detroit", "depart_time": "2021-07-07T06:00:00.000Z", "arrive_city": "Frankfurt", "arrive_time": "2021-07-09T08:00:00.000Z", "rental": "BMW", "rental_from": "2021-07-09T00:00:00.000Z", "rental_to": "2021-07-17T00:00:00.000Z", "run_type": runType // value taken from query parameter, default is "success" };

您可以通過傳遞以下 URL 參數與 Step Functions 數狀態機的不同流程進行實驗:

  • 成功執行 ─ https://{api 閘道網址}

  • 預訂航班失敗 ─ https://{api 網關網址}? 執行類型 = failFlightsReservation

  • 確認航班失敗 ─ https://{api 網關網址}? 執行類型 = failFlightsConfirmation

  • 保留汽車租賃失敗 ─ https://{api 網關網址}? 執行類型 = 預failCarRental約

  • 確認租車失敗 ─ https://{api 網關網址}? 執行類型 = 確認 failCarRental

  • 處理付款失敗 ─ https://{api 網關網址}? 執行類型 = 失敗付款

  • 通過旅程識別碼 ─ https://{api 網關網址}? TripID = {依預設,行程 ID 將成為 AWS 請求識別碼}

合家歡模板

鏈接的存儲庫包括 IaC 模板,您可以使用它們來創建整個樣本旅行預訂應用程序。

DynamoDB 資料表

以下是航班,租車和付款表的數據模型。

Flight Data Model: var params = { TableName: process.env.TABLE_NAME, Item: { 'pk' : {S: event.trip_id}, 'sk' : {S: flightReservationID}, 'trip_id' : {S: event.trip_id}, 'id': {S: flightReservationID}, 'depart_city' : {S: event.depart_city}, 'depart_time': {S: event.depart_time}, 'arrive_city': {S: event.arrive_city}, 'arrive_time': {S: event.arrive_time}, 'transaction_status': {S: 'pending'} } }; Car Rental Data Model: var params = { TableName: process.env.TABLE_NAME, Item: { 'pk' : {S: event.trip_id}, 'sk' : {S: carRentalReservationID}, 'trip_id' : {S: event.trip_id}, 'id': {S: carRentalReservationID}, 'rental': {S: event.rental}, 'rental_from': {S: event.rental_from}, 'rental_to': {S: event.rental_to}, 'transaction_status': {S: 'pending'} } }; Payment Data Model: var params = { TableName: process.env.TABLE_NAME, Item: { 'pk' : {S: event.trip_id}, 'sk' : {S: paymentID}, 'trip_id' : {S: event.trip_id}, 'id': {S: paymentID}, 'amount': {S: "750.00"}, // hard coded for simplicity as implementing any monetary transaction functionality is beyond the scope of this pattern 'currency': {S: "USD"}, 'transaction_status': {S: "confirmed"} } };

Lambda 函數

將創建以下功能以支持狀態機流和 Step Functions 中執行:

  • 預訂航班:將記錄插入 DynamoDB 航班表格中,並附有transaction_statuspending,以預訂航班。

  • 確認航班:更新 DynamoDB 航班表格中的記錄,以設定transaction_statusconfirmed,以確認航班。

  • 取消航班預訂:刪除 DynamoDB 航班表格中的記錄,以取消擱置的航班。

  • 約租車:將記錄插入 DynamoDB CarRentals 表格中,並附上transaction_statuspending,以預訂租車服務。

  • 確認租車:更新 DynamoDB CarRentals 表格中的記錄,以設定transaction_statusconfirmed,以確認租車。

  • 取消租車預約:刪除 DynamoDB CarRentals 表格中的記錄,以取消待處理的租車。

  • 處理付款:將記錄插入付款的 DynamoDB 付款表格中。

  • 取消付款:從 DynamoDB 付款表中刪除付款的記錄。

Amazon SNS

範例應用程式會建立下列主題和訂閱,以傳送 SMS 訊息,並通知客戶保留成功或失敗。如果您想要在測試範例應用程式時接收簡訊,請使用狀態機器定義檔案中的有效電話號碼更新 SMS 訂閱。

AWS CDK 程式碼片段 (在下列程式碼的第二行新增電話號碼):

const topic = new  sns.Topic(this, 'Topic'); topic.addSubscription(new subscriptions.SmsSubscription('+11111111111')); const snsNotificationFailure = new tasks.SnsPublish(this ,'SendingSMSFailure', { topic:topic, integrationPattern: sfn.IntegrationPattern.REQUEST_RESPONSE, message: sfn.TaskInput.fromText('Your Travel Reservation Failed'), });   const snsNotificationSuccess = new tasks.SnsPublish(this ,'SendingSMSSuccess', { topic:topic, integrationPattern: sfn.IntegrationPattern.REQUEST_RESPONSE, message: sfn.TaskInput.fromText('Your Travel Reservation is Successful'), });

AWS SAM 程式碼片段 (以您的有效電話號碼取代+1111111111字串):

StateMachineTopic11111111111: Type: 'AWS::SNS::Subscription' Properties: Protocol: sms TopicArn: Ref: StateMachineTopic Endpoint: '+11111111111' Metadata: 'aws:sam:path': SamServerlessSagaStack/StateMachine/Topic/+11111111111/Resource

Terraform 片段(用您的有效電話號碼替換+111111111字符串):

resource "aws_sns_topic_subscription" "sms-target" { topic_arn = aws_sns_topic.topic.arn protocol = "sms" endpoint = "+11111111111" }

成功預訂

下列流程說明成功的預約ReserveCarRental,其中包含「,ProcessPayment」、「ConfirmFlight」和「」ConfirmCarRental。ReserveFlight透過傳送給 SNS 主題訂閱者的 SMS 訊息,向客戶收到有關成功預約的通知。

保留失敗

此流程是傳奇模式中失敗的一個例子。如果在預訂航班和租車之後,「ProcessPayment」失敗,步驟將以相反的順序取消。 保留已釋出,並透過傳送給 SNS 主題訂閱者的 SMS 訊息通知客戶失敗。