执行和调用 Lambda 函数


本章将详细讲解Lambda函数的执行和调用过程及其涉及的步骤。

AWS Lambda 执行模型

AWS 执行取决于为 AWS Lambda Function 添加的配置详细信息。创建函数时,会分配内存时间,用于执行 AWS Lambda 函数。

借助配置详细信息,AWS Lambda 创建执行上下文。执行上下文是一个临时的运行时环境,它已准备好任何外部依赖项,例如数据库连接、http 端点、第三方库等(如果有)。

当第一次调用 AWS Lambda 函数或更新 Lambda 函数时,由于执行上下文设置,几乎不会增加延迟。但是,与第一个调用相比,后续调用速度更快。如果调用 Lambda 函数所需的时间较短,AWS Lambda 会尝试再次重用执行上下文。

执行上下文的重用具有以下含义 -

  • 如果为执行 Lambda 建立了任何数据库连接,则会维护该连接以供重用。因此,Lambda 代码必须首先检查连接 - 是否存在并重用;否则我们将不得不建立新的连接。

  • 执行上下文在/tmp目录中维护 500MB 的磁盘空间。所需的数据缓存在该目录中。您可以在代码中进行额外检查以查看数据是否存在。

  • 如果调用 Lambda 函数时回调或某些后台进程未完成,则再次调用 Lambda 函数时将开始执行。如果您不需要发生这样的事情,请确保在函数执行完成时正确结束您的进程。

您应该使用执行上下文和存储在 tmp 目录中的数据。在创建新的数据之前,您必须在代码中添加必要的检查,以查看所需的数据是否存在。这将节省执行时间并使其更快。

调用AWS Lambda函数

我们可以使用aws cli手动调用 AWS 。我们已经了解了如何使用cli创建和部署 AWS Lambda 。在这里,我们将首先使用aws cli创建一个函数并调用它。

使用 AWS CLI 创建 AWS Lambda 函数

您可以使用以下命令使用aws cli创建 AWS Lambda 函数-

命令

create-function 
--function-name <value>
--runtime <value>
--role <value>
--handler <value>
[--code <value>] 
[--description <value>] 
[--timeout <value>] 
[--memory-size <value>] 
[--environment <value>] 
[--kms-key-arn <value>] 
[--tags <value>] 
[--zip-file <value>] 
[--cli-input-json <value>]

带值的命令

aws lambda create-function 
--function-name "lambdainvoke" 
--runtime "nodejs8.10" 
--role "arn:aws:iam::625297745038:role/lambdaapipolicy" 
--handler "index.handler" 
--timeout 5 
--memory-size 256 
--zip-file "fileb://C:\nodeproject\index.zip"

输出如下所示 -

带值的命令

在AWS控制台中创建的函数如下所示 -

函数已创建

代码输入类型 现有角色

现在,您可以使用以下命令调用该函数:invoke

--function-name <value>
[--invocation-type <value>]
[--log-type <value>]
[--client-context <value>]
[--payload <value>]
[--qualifier <value>]
outfile <value>

选项

--function-name - 指定要调用的函数的名称。

--invokation-type(string) -默认情况下,invokation-type 是requestresponse。可与 invokation-type 一起使用的值为RequestResponse、EventDryRun

  • 事件调用类型用于异步响应。

  • 当您想要验证 Lambda 函数而不需要执行它时,可以使用 DryRun。

--log-type -如果调用类型是RequestResponse,则为Tail 。它提供最后 4KB Base64 编码的日志数据。可能的值为TailNone

--client-context -您可以将客户端特定详细信息传递给 Lambda 函数。clientcontext 必须采用 json 格式并进行 base64 编码。最大文件大小为 3583 字节。

--payload - lambda 函数的 json 格式输入。

--qualifier -您可以指定 Lambda 函数版本或别名。如果您传递函数版本,则 api 将使用合格的函数 arn 来调用 Lambda 函数。如果您指定别名,则 api 使用别名 ARN 来调用 Lambda 函数。

outfile -这是将保存内容的文件名。

带值的命令

aws lambda invoke --function-name "lambdainvoke" --log-type 
Tail C:\nodeproject\outputfile.txt

命令值

您可以使用有效负载选项以 json 格式将虚拟事件发送到 lambda 函数,如下所示。

相关的AWS Lambda代码如下 -

exports.handler = async (event, callback) => {
   console.log("Hello => "+ event.name);
   console.log("Address =>"+ event.addr);
   callback(null, 'Hello '+event.name +" and address is "+ event.addr);
};

请注意,在代码中,我们有 console event.nameevent.addr。现在,让我们使用 aws cli 中的有效负载选项来发送具有名称和地址的事件,如下所示 -

aws lambda invoke --function-name "lambdainvoke" --log-type 
Tail --payload file://C:\clioutput\input.txt C:\clioutput\outputfile.txt

然后payload 将输入作为文件路径,其中包含 json 输入,如下所示 -

{"name":"Roy Singh", "addr":"Mumbai"}

相应的输出如下所示 -

对应输出

输出存储在文件C:\clioutput\outputfile.txt中,如下所示 -

"Hello Roy Singh and address is Mumbai"

示例事件

您可以通过传递示例事件来测试 AWS Lambda 函数。本部分提供了 AWS 服务的一些示例事件。您可以使用invoke命令来测试任何服务触发时的输出。请遵守下面给出的相应示例事件的代码 -

Amazon S3 Put 示例事件

{
  "Records": [{
      "eventVersion": "2.0",
      "eventTime": "1970-01-01T00:00:00.000Z",
      "requestParameters": {
         "SourceIPAddress": "127.0.0.1"
      },
      "s3": {
         "configurationId": "testConfigRule",
         "object": {
            "eTag": "0123456789abcdef0123456789abcdef",
            "sequencer": "0A1B2C3D4E5F678901",
            "key": "HappyFace.jpg",
            "size": 1024
         },
         "bucket": { 
            "arn": bucketarn,
            "name": "Sourcebucket",
            "ownerIdentity": {
               "principalId": "EXAMPLE"
            }
         },
         "s3SchemaVersion": "1.0"
      },
      "responseElements": {
         "x-amz-id-2": "EXAMPLE123/5678abcdefghijklambdaisawesome/mnopqrstuvwxyzABCDEFGH",
         "x-amz-request-id": "EXAMPLE123456789"
      },
      "awsRegion": "us-east-1",
      "eventName": "ObjectCreated:Put",
      "userIdentity": {
         "principalId": "EXAMPLE"
      },
      "eventSource": "aws:s3"
   }]
}

要从 s3 put 事件获取文件的详细信息,您可以使用以下命令 -

event.Records[0].s3.object.key   //will display the name of the file

获取存储桶名称,您可以使用以下命令 -

event.Records[0].s3.bucket.name  //will give the name of the bucket.

查看 EventName,您可以使用以下命令 -

event.Records[0].eventName    // will display the eventname

Amazon S3 删除示例事件

{
   "Records": [{
      "eventVersion": "2.0",
      "eventTime": "1970-01-01T00:00:00.000Z",
      "requestParameters": {
         "SourceIPAddress": "127.0.0.1"
      },
      "s3": {
         "configurationId": "testConfigRule",
         "object": {
            "sequencer": "0A1B2C3D4E5F678901",
            "key": "HappyFace.jpg"
         },
         "bucket": {
            "arn": bucketarn,
            "name": "Sourcebucket",
            "ownerIdentity": {
               "principalId": "EXAMPLE"
            }
         },
        "s3SchemaVersion": "1.0"
      },
      "responseElements": {
         "x-amz-id-2": "EXAMPLE123/5678abcdefghijklambdaisawesome/mnopqrstuvwxyzABCDEFGH",
         "x-amz-request-id": "EXAMPLE123456789"
      },
      "awsRegion": "us-east-1",
      "eventName": "ObjectRemoved:Delete",
      "userIdentity": {
         "principalId": "EXAMPLE"
      },
      "eventSource": "aws:s3"
   }]
} 

亚马逊动态数据库

当 DynamoDB 表发生更改时,Amazon DynamoDB 可以成为 AWS Lambda 上的事件。我们可以执行从 DynamodDB 表中添加条目、更新和删除记录等操作。

此处显示了 DynamoDB 添加、插入和删除事件的示例事件 -

{
  "Records": [{
      "eventID": "1",
      "eventVersion": "1.0",
      "dynamodb": {
         "Keys": {
            "Id": {
               "N": "101"
            }
         },
         "NewImage": {
            "Message": {
               "S": "New item!"
            },
            "Id": {
               "N": "101"
            }
         },
         "StreamViewType": "NEW_AND_OLD_IMAGES",
         "SequenceNumber": "111",
         "SizeBytes": 26
      },
      "awsRegion": "us-west-2",
      "eventName": "INSERT",
      "eventSourceARN": eventSourcearn,
      "eventSource": "aws:dynamodb"
   },
   {
      "eventID": "2",
      "eventVersion": "1.0",
      "dynamodb": {
         "OldImage": {
            "Message": {
               "S": "New item!"
            },
            "Id": {
               "N": "101"
            }
         },
        "SequenceNumber": "222",
        "Keys": {
            "Id": {
               "N": "101"
            }
         },
        "SizeBytes": 59,
        "NewImage": {
            "Message": {
               "S": "This item has changed"
            },
            "Id": {
				   "N": "101"
            }
         },
         "StreamViewType": "NEW_AND_OLD_IMAGES"
      },
      "awsRegion": "us-west-2",
      "eventName": "MODIFY",
      "eventSourceARN": Sourcearn,
      "eventSource": "aws:dynamodb"
   },
   {      
   "eventID": "3",
      "eventVersion": "1.0",
      "dynamodb": {
         "Keys": {
            "Id": {
               "N": "101"
            }
         },
         "SizeBytes": 38,
         "SequenceNumber": "333",
         "OldImage": {
            "Message": {
               "S": "This item has changed"
            },
            "Id": {
               "N": "101"
            }
         },
         "StreamViewType": "NEW_AND_OLD_IMAGES"
      },      "awsRegion": "us-west-2",
      "eventName": "REMOVE",
      "eventSourceARN": Sourcearn,
      "eventSource": "aws:dynamodb"    
   }]
}

亚马逊简单通知服务

AWS Lambda 有助于处理简单通知服务 (SNS)中创建的通知。每当 SNS 中发布消息时,都可以通过 SNS 事件触发 Lambda 函数,其中包含消息的详细信息。该消息可以在 Lambda 函数内部进行处理,并可以根据要求进一步发送到其他服务。

输入消息后,SNS 将触发 Lambda 函数。如果尝试调用 Lambda 函数时出现任何错误,SNS 将重试调用 Lambda 函数最多 3 次。

Amazon SNS 示例事件

下面显示了一个示例事件,其中包含 AWS Lambda 函数中可用于执行进一步流程的所有详细信息 -

{
  "Records": [{
      "EventVersion": "1.0",
      "EventSubscriptionArn": eventsubscriptionarn,
      "EventSource": "aws:sns",
      "Sns": {
         "SignatureVersion": "1",
         "Timestamp": "1970-01-01T00:00:00.000Z",
         "Signature": "EXAMPLE",
         "SigningCertUrl": "EXAMPLE",
         "MessageId": "95df01b4-ee98-5cb9-9903-4c221d41eb5e",
         "Message": "Hello from SNS!",
         "MessageAttributes": {
            "Test": {
               "Type": "String",
               "Value": "TestString"
            },
            "TestBinary": {
               "Type": "Binary",
               "Value": "TestBinary"
            }
         },
         "Type": "Notification",
         "UnsubscribeUrl": "EXAMPLE",
         "TopicArn": topicarn,
         "Subject": "TestInvoke"
      }
   }]
}

亚马逊简单邮件服务

Amazon Simple Mail Service 可用于发送消息,也可用于接收消息。收到消息后,可以在 Simple Mail Service 上调用 AWS Lambda 函数。

Amazon SES 电子邮件接收示例事件

在 AWS Lambda 中使用时 SES 事件的详细信息如下所示 -

{
  "Records": [{
      "eventVersion": "1.0",
      "ses": {
         "mail": {
            "commonHeaders": {
               "from": [
                  "Jane Doe <janedoe@example.com>"
               ],
            "to": [
               "johndoe@Source.com"
            ],
            "returnPath": "janedoe@example.com",
            "messageId": "<0123456789Source.com>",
            "date": "Wed, 7 Oct 2015 12:34:56 -0700",
            "subject": "Test Subject"
         },
         "example": "janedoe@example.com",
         "timestamp": "1970-01-01T00:00:00.000Z",
         "destination": [
            "johndoe@example.com"
         ],
         "headers": [{
            "name": "Return-Path",
            "value": "<janedoe@example.com>"
         },
         {
            "name": "Received",
            "value": "from mailer.example.com (mailer.example.com [203.0.113.1]) by inbound-smtp.us-west-2.amazonaws.com with SMTP id o3vrnil0e2ic for johndoe@example.com; Wed, 07 Oct 2015 12:34:56 +0000 (UTC)"
         },
         {
            "name": "DKIM-Signature",
            "value": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=example.com; s=example; h=mime-version:from:date:message-id:subject:to:content-type; bh=jX3F0bCAI7sIbkHyy3mLYO28ieDQz2R0P8HwQkklFj4=; b=sQwJ+LMe9RjkesGu+vqU56asvMhrLRRYrWCbV"
         },
         {
            "name": "MIME-Version",
            "value": "1.0"
         },
         {
            "name": "From",
            "value": "Jane Doe <janedoe@example.com>"
         },
         {
            "name": "Date",
            "value": "Wed, 7 Oct 2015 12:34:56 -0700"
         },
         {
            "name": "Message-ID",
            "value": "<0123456789example.com>"
         },
         {
            "name": "Subject",
            "value": "Test Subject"
         },
         {
            "name": "To",
            "value": "johndoe@example.com"
         },
         {
            "name": "Content-Type",
            "value": "text/plain; charset=UTF-8"
         }],
         "headersTruncated": false,
         "messageId": "o3vrnil0e2ic28tr"
      },
      "receipt": {
         "recipients": [
            "johndoe@example.com"
         ],
         "timestamp": "1970-01-01T00:00:00.000Z",
         "spamVerdict": {
            "status": "PASS"
         },
         "dkimVerdict": {
            "status": "PASS"
         },
         "processingTimeMillis": 574,
         "action": {
            "type": "Lambda",
            "invocationType": "Event",
            "functionArn": "arn:aws:lambda:us-west-2:012345678912:function:example"
         },
         "spfVerdict": {
            "status": "PASS"
         },
         "virusVerdict": {
            "status": "PASS"
         }
      }
   },
   "eventexample": "aws:ses"
   }]
}

亚马逊 Cloudwatch 日志

可以使用CloudWatch Logs 订阅从 Amazon CloudWatch Logs 触发 AWS Lambda 。CloudWatch Logs 订阅包含有关日志的实时数据,这些数据可以在 AWS Lambda 内部进行处理和分析,也可以用于加载到其他系统。

Amazon CloudWatch 日志示例事件

{
   "awslogs": {
      "data": "H4sIAAAAAAAAAHWPwQqCQBCGX0Xm7EFtK+smZBEUgXoLCdMhFtKV3akI8d0bLYmibvPPN3wz00CJxmQnTO41whwW
      QRIctmEcB6sQbFC3CjW3XW8kxpOpP+OC22d1Wml1qZkQGtoMsScxaczKN3plG8zlaHIta5KqWsozoTYw3/djzwhpL
      wivWFGHGpAFe7DL68JlBUk+l7KSN7tCOEJ4M3/qOI49vMHj+zCKdlFqLaU2ZHV2a4Ct/an0/ivdX8oYc1UVX860fQ
      DQiMdxRQEAAA=="
   }
}

亚马逊 API 网关

可以在https url上调用 AWS Lambda 函数。可以通过GET、POST、PUT来完成。当调用 https url 时,也会触发 AWS Lambda 函数,并且可以在 AWS Lambda 内部使用使用 get/post 传递到 https 的数据,以用于插入 DynamoDB 或发送邮件等。

API网关代理请求事件

{
   "path": "/test/hello",
   "headers": {
      "Accept":  "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
      "Accept-Encoding": "gzip, deflate, lzma, sdch, br",
      "Accept-Language": "en-US,en;q=0.8",
      "CloudFront-Forwarded-Proto": "https",
      "CloudFront-Is-Desktop-Viewer": "true",
      "CloudFront-Is-Mobile-Viewer": "false",
      "CloudFront-Is-SmartTV-Viewer": "false",
      "CloudFront-Is-Tablet-Viewer": "false",
      "CloudFront-Viewer-Country": "US",
      "Host": "wt6mne2s9k.execute-api.us-west-2.amazonaws.com",
      "Upgrade-Insecure-Requests": "1",
      "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.82 Safari/537.36 OPR/39.0.2256.48",
      "Via": "1.1 fb7cca60f0ecd82ce07790c9c5eef16c.cloudfront.net (CloudFront)",
      "X-Amz-Cf-Id": "nBsWBOrSHMgnaROZJK1wGCZ9PcRcSpq_oSXZNQwQ10OTZL4cimZo3g==",
      "X-Forwarded-For": "192.168.100.1, 192.168.1.1",
      "X-Forwarded-Port": "443",
      "X-Forwarded-Proto": "https"
   },
   "pathParameters": {
      "proxy": "hello"
   },
   "requestContext": {
      "accountId": "123456789012",
      "reexampleId": "us4z18",
      "stage": "test",
      "requestId": "41b45ea3-70b5-11e6-b7bd-69b5aaebc7d9",
	   "identity": {
         "cognitoIdentityPoolId": "",
         "accountId": "",
         "cognitoIdentityId": "",
         "caller": "",
         "apiKey": "",
         "exampleIp": "192.168.100.1",
         "cognitoAuthenticationType": "",
         "cognitoAuthenticationProvider": "",
         "userArn": "",
         "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.82 Safari/537.36 OPR/39.0.2256.48",
         "user": ""
      },
      "reexamplePath": "/{proxy+}",
      "httpMethod": "GET",
      "apiId": "wt6mne2s9k"
   },
   "reexample": "/{proxy+}",
   "httpMethod": "GET",
   "queryStringParameters": {
      "name": "me"
   },
   "stageVariables": {
      "stageVarName": "stageVarValue"
   }
}

API网关代理响应事件

{
   "statusCode": 200,
   "headers": {
      "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
      "Accept-Encoding": "gzip, deflate, lzma, sdch, br",
      "Accept-Language": "en-US,en;q=0.8",
      "CloudFront-Forwarded-Proto": "https",
      "CloudFront-Is-Desktop-Viewer": "true",
      "CloudFront-Is-Mobile-Viewer": "false",
      "CloudFront-Is-SmartTV-Viewer": "false",
      "CloudFront-Is-Tablet-Viewer": "false",
      "CloudFront-Viewer-Country": "US",
      "Host": "wt6mne2s9k.execute-api.us-west-2.amazonaws.com",
      "Upgrade-Insecure-Requests": "1",
      "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.82 Safari/537.36 OPR/39.0.2256.48",
      "Via": "1.1 fb7cca60f0ecd82ce07790c9c5eef16c.cloudfront.net (CloudFront)",
      "X-Amz-Cf-Id": "nBsWBOrSHMgnaROZJK1wGCZ9PcRcSpq_oSXZNQwQ10OTZL4cimZo3g==",
      "X-Forwarded-For": "192.168.100.1, 192.168.1.1",
      "X-Forwarded-Port": "443",
      "X-Forwarded-Proto": "https"
   },
   "body": "Hello World"
}