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

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

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

由塔比沃德(AWS)創建

環境:PoC 或試驗

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

工作負載:開放原始碼

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

Summary

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

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

以下章節將示範如何使用 AWS Cloud Development Kit (AWS CDK) 以及無伺服器技術,例如 AWS Step Functions、AWS Lambda 和 Amazon DynamoDB,自動化設定和部署範例應用程式 (處理差旅預訂)。範例應用程式還使用 Amazon API Gateway 和 Amazon Simple Notification Service (Amazon SNS) 來實作傳奇執行協調器。

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

先決條件和限制

先決條件

  • 具有程式化存取權的作用中 AWS 帳戶 

  • AWS CDK 工具組堆疊,用於從此模式佈建資源,部署到目標 AWS 區域

  • NodeJS,這是 AWS CDK 所需的

  • AWS CDK CLI 搭配 AWS 帳戶組態,以便您可以使用cdk deploy命令

  • 您選擇的代碼編輯器(例如 Visual Studio 代碼,崇高或原子)

產品版本

  • NodeJS 版本 14

  • AWS 光碟辨識卡版本 1.89.0

限制

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

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

 

Architecture

目標架構

建議的架構使用 AWS Step Functions 建立傳奇模式,以預訂航班、預訂汽車租賃和處理度假付款。

下列工作流程圖說明了旅行預訂系統的一般流程。工作流程包括:預訂航空旅行(「預訂航班」)、預訂汽車(「預訂租賃」)、處理付款(「預訂航班」)、確認航班預訂(「確認航班」)、確認租車(「確認租賃」),然後在這些步驟完成後收到成的通知。但是,如果系統在運行任何這些交易時遇到任何錯誤,它開始向後失敗。比方說與付款處理 (「處理付款」) 的錯誤觸發退款 (「退款付款」),然後觸發取消租賃汽車和航班 (「取消預訂」和「取消預訂」),這會結束整個交易失敗訊息。

此模式會針對圖表中醒目提示的每項工作部署個別的 Lambda 函數,以及針對航班、租車和付款的三個 DynamoDB 表格。每個 Lambda 函數都會建立、更新或刪除個別 DynamoDB 表格中的列,這取決於交易是確認還是復原。該模式使用 Amazon SNS 向訂閱者傳送文字 (SMS) 訊息,通知他們交易失敗或成功。 

自動化和擴展

您可以使用 AWS CloudFormation 範本或 AWS CDK 指令碼來建立此架構的組態。請參閱 AWS CDK 腳本的附件,這些腳本是用 TypeScript 編寫的。

Tools

AWS 服務

  • AWS Step Functions— AWS Step Functions 是無伺服器協調服務,可讓您結合 AWS Lambda 功能和其他 AWS 服務,以建置關鍵業務應用程式。透過「Step Functions」圖形主控台,您可以將應用程式的工作流程視為一系列事件導向的步驟。

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

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

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

  • Amazon SNS— Amazon Simple Notification Service (Amazon SNS) 是一項受管服務,可提供從發佈商到訂閱者的訊息傳遞。

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

Code

示範傳奇模式的範例應用程式程式程式碼 (包括 AWS CDK 指令碼、Lambda 函數和 DynamoDB 表格) 會以封存形式附加。請按照第一個史詩中的說明來安裝這些。

Epics

任務描述所需技能
安裝 NPM 套件。

下載並解壓縮附加封存的內容之後,執行下列命令在 /cdk-無伺服器-saga 資料夾下載並安裝所有節點封裝管理員 (NPM) 封裝:

npm install
開發人員、雲端架構師
編譯 AWS CDK 指令碼。

在 /cdk-無伺服器傳遞資料夾中,執行下列命令來指示 TypeScript 轉譯器建立所有必要的 JavaScript 檔案:

npm run build
開發人員、雲端架構師
注意變更並重新編譯。

在 /cdk-lessver-saga 資料夾中,在單獨的終端機視窗中執行下列命令,以監視程式碼變更,並在偵測到變更時編譯程式碼:

npm run watch
開發人員、雲端架構師
執行單元測試。

在 /cdk-無伺服器-aga 資料夾中,執行下列命令來執行 Jest 單元測試:

npm run test
開發人員、雲端架構師
任務描述所需技能
將示範堆疊部署到 AWS。

在 /cdk-無伺服器傳送資料夾中,執行下列命令以建立部署組件,並將其部署到預設 AWS 帳戶和區域:

cdk deploy

此步驟可能需要幾分鐘才能完成。此命令使用為 AWS 命 Command Line Interface (AWS CLI) 設定的預設登入資料。若要指定具名的設定檔認證,請使用下列命令:

cdk deploy --profile <aws_cli_profile_name>

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

開發人員、雲端架構師
將部署的堆疊與目前狀態進行比較。

在 /cdk-無伺服器-aga 資料夾中,執行下列命令來比較已部署的堆疊與目前狀態變更原始程式碼之後的目前狀態:

cdk diff
開發人員、雲端架構師
建立 AWS CloudFormation 範本。

在 /cdk-無伺服器傳遞資料夾中,執行下列命令將堆疊合成 CloudFormation 範本:

cdk synth
開發人員、雲端架構師
任務描述所需技能
測試傳奇執行流程。

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

若要檢視結果,請登入至 AWS 管理主控台,導覽至 Step Functions 主控台。在這裡,你可以看到傳奇狀態機的每一步。您也可以檢視 DynamoDB 表格,以查看插入、更新或刪除的記錄。如果您經常重新整理畫面,您可以查看交易狀態由待處理變更為已確認。 

您可以訂閱 SNS 主題,方法是使用您的手機號碼更新 Statemachine.ts 檔案中的代碼,以便在成功或失敗預訂時接收 SMS 訊息。如需詳細資訊,請參閱「」Amazon SNS中的其他資訊區段。

開發人員、雲端架構師

技術文件

AWS 服務文件

教學課程

其他資訊

Code

為了測試目的,此模式部署 API Gateway 和觸發 Step Functions 狀態機的測試 Lambda 函數。使用 Step Functions 能,您可以通過run_type參數來模仿「預留飛行」、「預留租賃」、「處理付款」、「確認飛行」和「確認租車」中的失敗。

傳奇 Lambda 函式 (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 閘道網址?執行類型 = 失敗航班預訂

  • 確認航班失敗─ https://{api 閘道網址?執行類型 = 失敗迴轉燈確認

  • 預約車輛租賃失敗─ https://{api 閘道網址?執行類型 = 失敗編號保留

  • 確認租車失敗─ https://{api 閘道網址?執行類型 = 失敗編號確認

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

  • 傳遞運送航程識別碼─ https://{api 閘道網址?三角 ={默認情況下,行程 ID 將是 AWS 請求 ID}

AWS CDK 指令碼

附加的存檔包含 AWS CDK 指令碼,您可以用它來建立整個旅行預約範例應用程式。

DynamoDB 資料表

附加的程式碼會建立下列 DynamoDB 表格。這些表格包含航班預訂、租車預訂和付款資訊。 

const flightTable = new dynamodb.Table(this,'Flights',{ partitionKey:{name:'pk', type:dynamodb.AttributeType.STRING}, sortKey:{name:'sk', type: dynamodb.AttributeType.STRING} }) const rentalTable = new dynamodb.Table(this,'Rentals',{ partitionKey:{name:'pk', type:dynamodb.AttributeType.STRING}, sortKey:{name:'sk', type: dynamodb.AttributeType.STRING} }) const paymentTable = new dynamodb.Table(this,'Payments',{ partitionKey:{name:'pk', type:dynamodb.AttributeType.STRING}, sortKey:{name:'sk', type: dynamodb.AttributeType.STRING} }) 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 航班表格中插入交易狀態為待處理的記錄,以預訂航班。

  • 確認航班:更新 DynamoDB 航班表中的記錄,將交易狀態設定為已確認,以確認航班。

  • 取消航班預訂:從 DynamoDB 航班表中刪除記錄,以取消待處理的航班。

  • 預約租車:在 DynamoDB 汽車租賃表中插入交易狀態為待處理的記錄,以預訂汽車租賃。

  • 確認租車:更新 DynamoDB 汽車租賃表中的記錄,將交易狀態設定為確認,以確認汽車租賃。

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

  • 處理付款:在 DynamoDB 付款表中插入記錄以進行付款。

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

let fn = new lambda.Function(scope, id, { runtime: lambda.Runtime.NODEJS_12_X, code: lambda.Code.fromAsset('lambdas'), handler:handler, environment: { TABLE_NAME: table.tableName } });

Amazon SNS

範例應用程式會建立下列主題和訂閱,以傳送 SMS 訊息,並通知客戶有關成功或失敗的預約。如果您想要在測試範例應用程式時接收簡訊,請使用 Statemachine.ts 檔案 (在下列程式碼的第二行) 中的有效電話號碼更新 SMS 訂閱:

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'), });

成功預訂

以下流程說明成功的預訂:「預訂航班」、「預訂租賃」、「處理付款」,後面接著「確認航班」和「確認租車」。透過傳送給 SNS 主題訂閱者的 SMS 訊息,將成功預約通知客戶。

失敗的保留

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

Attachments

attachment.zip