aws(学习笔记第二十四课)
- 使用
sam
开发step functions
学习内容:
- 生成
sam
的step functions
实例程序 - 什么是
SAM amazon Serverless Application Model
SAM
程序结构SAM
执行程序
1. 生成sam
的step functions
实例程序
- 参照文档
这里参照AWS
的官方文档SAM amazon Serverless Application Model
- 什么是
SAM amazon Serverless Application Model
- 整体架构
SAM
就是一个基于Cloudformation
的应用程序框架,主要目的正如名字(Serverless Application Model
),方便进行Serverless Application
的开发。
开发的一般步骤如下:- 开发
lambda
等serverless application
。 - 利用
step functions
等serverless application
。当然,其中可以调用lambda
。 - 之后利用上面的
serverless application
,进行Cloudformation
的template
定义。 - 最后经过
sam build
和sam deploy
部署到AWS
的环境中。
- 开发
- 整体架构
3. SAM
程序结构
- 开始使用
SAM
-
这里使用
SAM
提供的实例程序进行练习HourlyTradingSchedule
是一个AWS EventBridge
的规则,这里定义了股票投资程序的调用周期。类似于linux
的cron job
。StockTradingStateMachine
就是股票交易的StateMachine
。- 股票交易的
StateMachine
里面包括三个lambda
StockCheckerFunction
这里随机产生股票的价格(进行简单的股票市场的模拟)- 中间其实有一个
choice state
,进行判断。这里没有画出来 - 之后根据判断,如果股票高过某个固定价格,那么进行
StockBuyerFunction
的调用 - 如果股票高过某个固定价格,那么进行
StockSellerFunction
的调用 - 最后,不管买还是卖的操作,都进行
TransactionTable
的写入(使用DynamoDB
记录交易)
-
进行实际代码的实验
- 实验环境
这里还是使用非常给力的工具CloudShell
。
- 构建代码
-
创建代码的父路径
shellmkdir demo-sam cd demo-sam
-
使用
sam
生成股票实例代码(这个代码是sam
自带的)
之后进行一些runtime
的相关设定。
到这里,代码就会被生成出来,而且cloudformation
的template
文件都是yaml
格式的。
-
- 实验环境
-
将
cloudshell
环境中的代码通过S3
取到本地-
创建传输文件的
S3 bucket
因为cloudshell
不是很容易和本地传输文件,所以使用S3 bucket
。
-
将
SAM
代码打包,copy
到S3 bucket
shelltar zcvf demo-sam.tar.gz demo-sam/ aws s3 cp demo-sam.tar.gz s3://finlay-cloudshell/
-
将
SAM init
生成的实例程序代码,下载到本地
本地文件夹如下所示。
-
将
SAM init
生成的实例程序代码使用vscode
打开(这里单纯的可以更加容易编辑代码)-
template
文件yamlAWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 Description: | demo-sam Sample SAM Template for demo-sam Resources: StockTradingStateMachine: Type: AWS::Serverless::StateMachine # More info about State Machine Resource: https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-statemachine.html Properties: DefinitionSubstitutions: StockCheckerFunctionArn: !GetAtt StockCheckerFunction.Arn StockSellerFunctionArn: !GetAtt StockSellerFunction.Arn StockBuyerFunctionArn: !GetAtt StockBuyerFunction.Arn DDBPutItem: !Sub arn:${AWS::Partition}:states:::dynamodb:putItem DDBTable: !Ref TransactionTable Events: HourlyTradingSchedule: Type: Schedule # More info about Schedule Event Source: https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-property-statemachine-schedule.html Properties: Description: Schedule to run the stock trading state machine every hour Enabled: false # This schedule is disabled by default to avoid incurring charges. Schedule: rate(1 hour) Policies: # Find out more about SAM policy templates: https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-policy-templates.html - LambdaInvokePolicy: FunctionName: !Ref StockCheckerFunction - LambdaInvokePolicy: FunctionName: !Ref StockSellerFunction - LambdaInvokePolicy: FunctionName: !Ref StockBuyerFunction - DynamoDBWritePolicy: TableName: !Ref TransactionTable DefinitionUri: statemachine/stock_trader.asl.json StockCheckerFunction: Type: AWS::Serverless::Function # More info about Function Resource: https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-function.html Properties: CodeUri: functions/stock_checker/ Handler: app.lambda_handler Runtime: python3.9 Architectures: - x86_64 StockSellerFunction: Type: AWS::Serverless::Function Properties: CodeUri: functions/stock_seller/ Handler: app.lambda_handler Runtime: python3.9 Architectures: - x86_64 StockBuyerFunction: Type: AWS::Serverless::Function Properties: CodeUri: functions/stock_buyer/ Handler: app.lambda_handler Runtime: python3.9 Architectures: - x86_64 TransactionTable: Type: AWS::Serverless::SimpleTable # More info about SimpleTable Resource: https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-simpletable.html Properties: PrimaryKey: Name: Id Type: String ProvisionedThroughput: ReadCapacityUnits: 1 WriteCapacityUnits: 1 ApplicationResourceGroup: Type: AWS::ResourceGroups::Group Properties: Name: !Sub ApplicationInsights-SAM-${AWS::StackName} ResourceQuery: Type: CLOUDFORMATION_STACK_1_0 ApplicationInsightsMonitoring: Type: AWS::ApplicationInsights::Application Properties: ResourceGroupName: !Ref ApplicationResourceGroup AutoConfigurationEnabled: 'true' Outputs: # StockTradingStateMachineHourlyTradingSchedule is an implicit Schedule event rule created out of Events key under Serverless::StateMachine # Find out more about other implicit resources you can reference within SAM # https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-specification-generated-resources.html StockTradingStateMachineArn: Description: Stock Trading State machine ARN Value: !Ref StockTradingStateMachine StockTradingStateMachineRoleArn: Description: IAM Role created for Stock Trading State machine based on the specified SAM Policy Templates Value: !GetAtt StockTradingStateMachineRole.Arn
使用
vscode
打开template
文件,可以看到AWS service
的图形化结构。
-
stock_checker
文件 随机产生stock
的价格pythonfrom random import randint def lambda_handler(event, context): """Sample Lambda function which mocks the operation of checking the current price of a stock. For demonstration purposes this Lambda function simply returns a random integer between 0 and 100 as the stock price. Parameters ---------- event: dict, required Input event to the Lambda function context: object, required Lambda Context runtime methods and attributes Returns ------ dict: Object containing the current price of the stock """ # Check current price of the stock stock_price = randint( 0, 100 ) # Current stock price is mocked as a random integer between 0 and 100 return {"stock_price": stock_price}
-
stock_buyer
文件 如果价格低,选择买进pythonfrom datetime import datetime from random import randint from uuid import uuid4 def lambda_handler(event, context): """Sample Lambda function which mocks the operation of buying a random number of shares for a stock. For demonstration purposes, this Lambda function does not actually perform any actual transactions. It simply returns a mocked result. Parameters ---------- event: dict, required Input event to the Lambda function context: object, required Lambda Context runtime methods and attributes Returns ------ dict: Object containing details of the stock buying transaction """ # Get the price of the stock provided as input stock_price = event["stock_price"] # Mocked result of a stock buying transaction transaction_result = { "id": str(uuid4()), # Unique ID for the transaction "price": str(stock_price), # Price of each share "type": "buy", # Type of transaction (buy/sell) "qty": str( randint(1, 10) ), # Number of shares bought/sold (We are mocking this as a random integer between 1 and 10) "timestamp": datetime.now().isoformat(), # Timestamp of the when the transaction was completed } return transaction_result
-
stock_seller
文件 如果价格高,选择抛出pythonfrom datetime import datetime from random import randint from uuid import uuid4 def lambda_handler(event, context): """Sample Lambda function which mocks the operation of selling a random number of shares for a stock. For demonstration purposes, this Lambda function does not actually perform any actual transactions. It simply returns a mocked result. Parameters ---------- event: dict, required Input event to the Lambda function context: object, required Lambda Context runtime methods and attributes Returns ------ dict: Object containing details of the stock selling transaction """ # Get the price of the stock provided as input stock_price = event["stock_price"] # Mocked result of a stock selling transaction transaction_result = { "id": str(uuid4()), # Unique ID for the transaction "price": str(stock_price), # Price of each share "type": "sell", # Type of transaction (buy/sell) "qty": str( randint(1, 10) ), # Number of shares bought/sold (We are mocking this as a random integer between 1 and 10) "timestamp": datetime.now().isoformat(), # Timestamp of the when the transaction was completed } return transaction_result
-
step functions
文件 将上面的lambda
函数穿插起来,形成一个工作流程编排json{ "Comment": "A state machine that does mock stock trading.", "StartAt": "Check Stock Value", "States": { "Check Stock Value": { "Type": "Task", "Resource": "${StockCheckerFunctionArn}", "Retry": [ { "ErrorEquals": [ "States.TaskFailed" ], "IntervalSeconds": 15, "MaxAttempts": 5, "BackoffRate": 1.5 } ], "Next": "Buy or Sell?" }, "Buy or Sell?": { "Type": "Choice", "Choices": [ { "Variable": "$.stock_price", "NumericLessThanEquals": 50, "Next": "Buy Stock" } ], "Default": "Sell Stock" }, "Sell Stock": { "Type": "Task", "Resource": "${StockSellerFunctionArn}", "Retry": [ { "ErrorEquals": [ "States.TaskFailed" ], "IntervalSeconds": 2, "MaxAttempts": 3, "BackoffRate": 1 } ], "Next": "Record Transaction" }, "Buy Stock": { "Type": "Task", "Resource": "${StockBuyerFunctionArn}", "Retry": [ { "ErrorEquals": [ "States.TaskFailed" ], "IntervalSeconds": 2, "MaxAttempts": 3, "BackoffRate": 1 } ], "Next": "Record Transaction" }, "Record Transaction": { "Type": "Task", "Resource": "${DDBPutItem}", "Parameters": { "TableName": "${DDBTable}", "Item": { "Id": { "S.$": "$.id" }, "Type": { "S.$": "$.type" }, "Price": { "N.$": "$.price" }, "Quantity": { "N.$": "$.qty" }, "Timestamp": { "S.$": "$.timestamp" } } }, "Retry": [ { "ErrorEquals": [ "States.TaskFailed" ], "IntervalSeconds": 20, "MaxAttempts": 5, "BackoffRate": 10 } ], "End": true } } }
检查
vscode
的sam
预览功能
-
-
-
回到
cloudshell
执行sam build
和sam deploy
部署到AWS
shellsam build sam deploy
可以看到,本质上这个
sam application
还是使用Cloudformation
进行部署。
查看Cloudformation
进一步验证了想定结果。
-
4. 执行sam
的step functions
实例程序
-
打开默认的
aws eventbridge
的规则设置默认是禁用的,编辑这里,打开禁用。
-
查看执行结果
可以看出,已经成功执行一次
股票价格为2,执行了
buy stock lambda