无服务器
AWS Lambda函数性能:带有boto3和aioboto3的python中的并行性
异步或不异步的问题是
2018年6月12日,星期二
AWS Greengrass使您可以在喜欢的边缘设备(如Raspberry Pi)上运行Lambda函数,同时保持与AWS云中资源的无缝集成。如果您觉得这很复杂,那您就没错。官方的草丛 入门指南 涵盖六个模块,并且需要在设备和云中进行大量手动配置。
一些工具开始出现,这些工具消除了一些Greengrass部署难题。 一位云大师发布了 AWS Greengrass:缺少的手册 和相关的 格林戈 部署工具。我们在IOPipe的朋友刚刚发布了名为Pi的Greengrass图片 草bian。 AWS在其中也提供了一些Lambda部署示例 原始的Greengrass演示应用.
但是所有这些示例都调用Lambda API。那不是我们想要部署Lambda函数的方式!我们希望使用类似的框架,以与处理任何其他无服务器代码相同的方式来管理Greengrass Lambda。 AWS SAM(无服务器应用程序模型).
那么SAM如何帮助我们将代码推送到Greengrass?
为了在Greengrass中推出对Lambda代码的更新,我们需要:
在AWS控制台中点击了很多。让我们看看AWS SAM如何使用下面的模板使此操作更容易。
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: Device Lambda
Parameters:
GroupName:
Default: my-group
Type: String
FunctionAlias:
Default: prod
Type: String
Resources:
LambdaRole:
Type: AWS::IAM::Role
Properties:
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AWSGreengrassResourceAccessRolePolicy
- arn:aws:iam::aws:policy/AWSGreengrassFullAccess
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action: sts:AssumeRole
DeviceCoreFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: device/
Handler: device.function_handler
Runtime: python2.7
Role: !GetAtt LambdaRole.Arn
AutoPublishAlias: !Ref FunctionAlias
CustomFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: custom/
Handler: custom.function_handler
Runtime: python2.7
Role: !GetAtt LambdaRole.Arn
Environment:
Variables:
GROUP_NAME: !Ref GroupName
CustomResource:
Type: Custom::CustomResource
DependsOn: DeviceCoreFunction
Properties:
ServiceToken: !GetAtt 'CustomFunction.Arn'
ParameterOne: Parameter to pass into Custom Lambda Function
该SAM模板中发生了什么?我们正在创建两个Lambda函数,一个关联的IAM角色和一个自定义资源。让我们分别细分这些部分。
LambdaRole包含您在边缘设备上的功能与AWS Greengrass服务进行交互所需的托管策略。 (如果您的功能需要访问其他AWS资源,您也可以向这些角色添加这些权限。)
LambdaRole:
Type: AWS::IAM::Role
Properties:
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AWSGreengrassResourceAccessRolePolicy
- arn:aws:iam::aws:policy/AWSGreengrassFullAccess
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action: sts:AssumeRole
DeviceCoreFunction是要在Greengrass上运行的Lambda函数。
DeviceCoreFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: device/
Handler: device.function_handler
Runtime: python2.7
Role: !GetAtt LambdaRole.Arn
AutoPublishAlias: !Ref FunctionAlias
Assuming we have some code in device.py, the magic here is the AutoPublishAlias
property. This amazing line of config singlehandedly creates an alias for the function, publishes a new version, points the alias to the version, and points 所有 event sources to the alias, any time your function code changes. (In fact, 这只是SAM出色的Lambda部署功能的表面)
That takes care of steps 1 and 2 on our list of Greengrass deployment steps. Now we just need to update the Greengrass deployment itself. Unfortunately, Greengrass does not yet have CloudFormation support. Instead, we can use a Lambda-backed custom CloudFormation resource in our SAM template, here called CustomResource
:
CustomFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: custom/
Handler: custom.function_handler
Runtime: python2.7
Role: !GetAtt LambdaRole.Arn
Environment:
Variables:
GROUP_NAME: !Ref GroupName
CustomResource:
Type: Custom::CustomResource
DependsOn: DeviceCoreFunction
Properties:
ServiceToken: !GetAtt 'CustomFunction.Arn'
The CustomFunction will run our Greengrass deployment code in custom.py
:
import boto3
import json
import os
from urllib2 import build_opener, HTTPHandler, Request
client = boto3.client('greengrass')
def deploy_greengrass_group(group_name):
group = [ group for group in client.list_groups()['Groups'] if group['Name'] == group_name ][0]
client.create_deployment(
DeploymentType='NewDeployment',
GroupId=group['Id'],
GroupVersionId=group['LatestVersion']
)
def function_handler(event, context):
if event['RequestType'] == 'Create' or event['RequestType'] == 'Update':
deploy_greengrass_group(os.environ['GROUP_NAME'])
sendResponse(event, context, "SUCCESS", { "Message": "Resource update successful!" })
else:
sendResponse(event, context, "FAILED", { "Message": "Unexpected event received from CloudFormation" })
def sendResponse(event, context, responseStatus, responseData):
responseBody = json.dumps({
"Status": responseStatus,
"Reason": "See the details in CloudWatch Log Stream: " + context.log_stream_name,
"PhysicalResourceId": context.log_stream_name,
"StackId": event['StackId'],
"RequestId": event['RequestId'],
"LogicalResourceId": event['LogicalResourceId'],
"Data": responseData
})
opener = build_opener(HTTPHandler)
request = Request(event['ResponseURL'], data=responseBody)
request.add_header('Content-Type', '')
request.add_header('Content-Length', len(responseBody))
request.get_method = lambda: 'PUT'
response = opener.open(request)
Most of the code above is boilerplate that takes care of sending the custom resource response back to CloudFormation. The function of interest is deploy_greengrass_group
, which retrieves the group identifiers based on its name and then creates a new deployment using the Greengrass SDK for Python. (Note that urllib2
is used to avoid the extra step of packaging the requests
module with our Lambda code.)
All that's left now is to deploy the SAM template, replacing [YOUR_BUCKET]
with an S3 bucket in your environment (SAM CLI安装说明):
sam package --template-file device.template --s3-bucket [YOUR_BUCKET] --output-template-file packaged.yaml
sam deploy --template-file ./packaged.yaml --stack-name gg-device --capabilities CAPABILITY_IAM
现在,您可以在更改代码时多次部署SAM模板,并且应该自动将代码推送到Greengrass组中的所有Lambda函数中!说到部署,看起来栅栏SAM上的草确实更绿了。