learn-aws-lambda, 了解如何使用 AWS Lambda轻松创建无限可伸缩的Web服务

分享于 

86分钟阅读

GitHub

  繁體 雙語
Learn to use AWS Lambda to create scalable micro-services
  • 源代码名称:learn-aws-lambda
  • 源代码网址:http://www.github.com/dwyl/learn-aws-lambda
  • learn-aws-lambda源代码文档
  • learn-aws-lambda源代码下载
  • Git URL:
    git://www.github.com/dwyl/learn-aws-lambda.git
    Git Clone代码到本地:
    git clone http://www.github.com/dwyl/learn-aws-lambda
    Subversion代码到本地:
    $ svn co --depth empty http://www.github.com/dwyl/learn-aws-lambda
    Checked out revision 1.
    $ cd repo
    $ svn up trunk
    
    知识库

    aws lambda intro image

    了解在 LESS 时间和成本范围内使用 AWS Lambda创建可以扩展的微型服务比基于服务器的应用程序运行的成本高。

    Codeshipcodecov.iodependencies StatusdevDependencies Statuscontributions welcome

    电子邮件内容

    什么是 Lambda?

    Amazon使用 Web服务,Java,Java,without,Having,,Amazon,Amazon,Amazon,Amazon,Amazon,Amazon,Amazon,Amazon,Amazon,Amazon,等。

    AWS是有效的中断 他们的( 自己的 ) 他们的服务with与Lambda的业务。 AWS在固定增量的情况下,使用复杂的应用程序监控/扩展来构建 EC2,而不是强迫我们支付固定的应用程序监控/缩放,这是构建微服务系统的简单方法。

    此外,Lambda Platform-as-a-Service (",Google App Engine,Azure,Modulus,Modulus,Modulus,Lambda,Lambda,Lambda,Lambda,Lambda,Lambda,Lambda,Lambda,Lambda等。

    的Lambda特性

    临时存储

    不能访问 文件系统 或者内存持久性( 比如。 因此,你不能存储数据或者操作的result,因为本地计算机上没有。

    使用AWS数据存储服务

    Lambda Having low persistence persistence low persistence persistence persistence persistence local local local local local local local local local local local local ,RDS,( 基于 NoSQL ssd的数据库),RDS ( 关系数据库 ),然而,有一个重要的( 而且可能是昂贵的昂贵的产品) 捕获: 对所有AWS数据存储的PUT/POST/GET 请求收费为免费 ! 尽管每个运行周期的成本很小,但是在每次执行周期中,如果你对S3进行了操作,那么你可以 !

    创建并测试你自己的AWS Lambda函数

    'Hello World'示例( 内联) !

    下面是一个用于帮助你启动 AWS Lambda的示例的简单示例:

    如果你还没有这么做,请在这里创建一个免费的AWS帐户

    登录AWS管理控制台,选择右上角的区域,然后打开AWS控制台。

    选择'立即开始',然后从选项选项板列表中选择'hello世界'蓝图。

    在'配置功能'页面上,编辑现有的inline 代码以创建你的函数。 AWS期望我们导出一个对象,该对象有一个名为handler的属性。 下面是我们的示例:

    Configure Function

    属性的值是一个接受两个参数,事件和上下文的函数。 事件由我们创建,上下文由by提供的运行时信息组成。 它们都采用JSON对象的形式。

    • 在函数下面,你必须指定处理程序以及你希望为它的提供的角色。 ( 角色是自动AWS标识,具有确定标识可以或者不能在AWS中执行的操作的权限策略。 有关角色的详细信息,请单击这里的 ) )。 我们选择了'lambda_basic_execution'角色,因为我们的函数非常简单:

    Handler and Roles

    在'高级设置'部分中,你可以指定每个AWS的Lambda实例应该分配的内存数量。 注意:通过增加内存,这也增加了函数运行时的成本 !

    • 单击'下一步'查看代码,如果你高兴,请单击'创建函数'。 然后你将被带到AWS的Lambda函数中,你应该看到刚才创建的函数。

    Test

    • 然后,我们可以通过点击左边的蓝色'测试'按钮来测试我们的函数。 在这里,我们可以指定传递给函数的事件的有效负载。 将有一个现有的事件模板,但我们更改了 key-value 对,如下所示:

    event object

    单击'保存和测试'按钮测试你的函数。

    • 在你的函数下面,你现在应该能够看到你的测试结果。 以下是我们的示例的结果:

    test results

    你可以随时重新配置你的测试。 单击'测试'按钮旁边的'操作'按钮并选择'配置测试事件'选项。

    'Hello World'示例(。zip ) !

    另一种基于文本的方法是创建 AWS Lambda函数,在文本编辑器中编写它,压缩它,然后将它上传。 以下是操作方法:

    如果你还没有创建AWS帐户,请按照前一示例的前两步执行。

    因为我们将创建自己的'选择蓝图'页面,所以在页面上点击'跳过'按钮。

    在'配置功能'页面上,给Lambda函数一个 NAME,然后选择'上传. zip 文件'单选按钮。 然后它会提示你上传一个文件。

    zip file upload

    • 打开你的文本编辑器,如果你正在写入 inline 函数,然后将它的保存为 .js file:。

    function code

    • 通过在 命令行 中键入以下内容来压缩这个文件。 命令包含第一个文件名,即要创建 ( 用你喜欢的. zip 叫什么)的压缩文件,然后是要压缩的文件。 在我们的示例中,你可以看到前面创建的.js 文件的NAME:

    $ zip -r hello-world.zip hello-world.js

    
    You should now be able to see a ```.ZIP``` file alongside your ```.js``` file. 
    
    
    **NOTE: If your function has any dependencies then you must include your ```node_modules``` file within your. ZIP file. Simply add ```node_modules``` after the files you wish to zip up!**
    
    
    
    

    返回'配置功能'页面并单击'上载'按钮并选择刚刚创建的. zip 文件。

    下一步选择Lambda函数处理程序和角色。 处理程序是包含你的函数的.js 文件的NAME,后面跟你要导出的处理程序的NAME。 我们已经选择了基本执行角色,就像前面的示例一样:

    handler and role

    • 前面的示例一样,单击'下一步',如果你对函数满意,单击'创建函数'。 你的新函数现在应该显示在 AWS Lambda函数列表中:

    function list

    现在可以用与 inline 示例相同的方法来测试这个函数。

    'Hello World'示例( API网关) !

    via的另一个很酷的事情是,可以通过web端点 换句话说,调用Lambda函数,它们可以通过HTTP调用触发。 你可以直接从 AWS Lambda控制台配置这些端点:

    打开AWS控制台并单击你希望为它的创建端点的函数。 ( 如果还没有创建Lambda函数,则可以通过以下示例之一进行操作) !

    在此页上选择'API终结点'选项卡,然后单击'+ 添加API端点':

    add api endpoint

    • 配置你的API端点设置:
    • API端点类型:API网关

    • API NAME: whatever-you-like ( 我们推荐 Having 所有小写字母以破折号分隔,以提高可读性)

    • 资源 NAME:/yourlambdafunctionname

    • 方法:GET/POST/PUT/DELETE...

    • 部署阶段:定义可以通过它的访问API部署的*path

    • 安全性:定义函数的调用方式

      *The 路径将是以>> .../deploymentStage/ResourceName 结尾的URI。

    api endpoint settings

    由于这是一个更常见的用例示例,我们将'安全'设置为'使用访问键打开'。 可以按照蓝色框中的链接来配置这些键。 以为代价的示例URI将以>> .../prod/Concatenate

    如果你对Lambda函数配置满意,请单击'提交'。

    • 现在你应该能够看到在 AWS Lambda生成的URL中列出的函数。

    api url

    • 现在测试端点,看看我们的Lambda函数是否被调用。 转到AWS控制台,然后在应用程序服务下单击'api网关'。 这将带你到你的api列表,在那里你应该看到我们刚刚创建的。 点击标题。

    api list

    • 点击你的Lambda函数下面的方法,在我们的例子中,它是'POST'。 然后点击'测试'下面的闪电螺栓:

    POST method

    • 输入API期望的输入值,然后点击右侧的蓝色'测试'按钮。 然后,响应 body 应返回你的Lambda函数的结果:

    test api

    :如何通过API网关访问Lambda函数

    默认情况下,如果你尝试访问/访问前一部分,则无法访问你刚才创建的API网关的端点,这意味着如果你试图访问/访问该函数,就不能访问。

    如果你还没有查看网关,请从你的AWS控制台菜单中选择它: aws01-aws-dashboard-select-api-gateway

    在AWS控制台的Amazon Amazon网关中创建一个API密钥: aws02-api-key-create

    创建一个新的 API密钥: aws03-api-key-create0ew

    将你的密钥命名为启用并单击 Save 按钮: aws03-api-key-create-new-specify

    启用API键后,一个部分就会出现,创建表单允许你将新的API键分配给你的API的一个 API。 选择 API &阶段( 在我们的例子中,API是 LambdaMicroservice ,并且舞台是),然后单击 Add 按钮: aws04-api-key-create-assign-to-stage 现在,你应该会看到,对于你的阶段,你已经启用了API密钥: aws05-api-key-associated

    这个屏幕上有英镑的API API API API,并将它保存到你的记事本中。 aws05-copy-the-api-key

    返回你的台控制台,并选择收费。 这将显示你的Lambda函数列表。 选择前面创建的Concatenate Lambda函数。 aws06-list-of-lambda-functions

    viewing viewing tab,选择 API Endpoints Endpoints tab tab API API API API API API API API aws07-view-api-endpoints-and-copy-the-link

    复制端点URL和API密钥后,你现在可以在终端中运行 cURL 命令来访问端点:

    curl --header "x-api-key: LhGU6jr5C19QrT8yexCNoaBYeYHy9iwa5ugZlRzm" https://r09u5uw11g.execute-api.eu-west-1.amazonaws.com/prod/Concatenate

    aws-lambda-curl-with-api-key-works

    注意:我稍微修改了Lambda函数返回时间戳以便我知道什么时候执行了函数:

    exports.handler=function(event, context) {
     console.log('Received event:', JSON.stringify(event, null, 2));
     console.log('context:', JSON.stringify(context, null, 2));
     event.key1=event.key1||'Hello'; // set default valuesevent.key2=event.key2||'World!';
     console.log('value1 =', event.key1);
     console.log('value2 =', event.key2);
     var date =newDate();
     var time =date.toString();
     context.succeed(event.key1+''+event.key2+'>> '+ time );
    };

    例如在AWS上,关于启用 API API的API键的更多步骤,请参见: http://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-api-keys.html


    使用Lambda函数创建一个 API,使用Lambda函数从DynamoDB表检索/更新记录。

    • 首先,我们需要在DynamoDB中创建一个 table。 转到DynamoDB控制台and然后单击'创建表格'按钮。 给你的table 一个 NAME ( 把它命名为 DynamoDB table 将保存的数据类型)。 我们已经调用了'用户'。'主键'是由'分区键'( 散列键) 和可选的'排序关键字'组成的。 ( 分区键用于跨主机分区数据,以实现可伸缩性和可用性):

    create table

    table name

    对于'表格设置',选中'使用默认设置'复选框,然后单击蓝色'创建'按钮:

    table setup

    • 创建 table 之后,单击'闹钟'选项卡,然后在创建基本警报时单击 delete:

    alarms

    然后单击'容量'选项卡,然后将'读取'和'写入'容量单位指定为 3,然后单击'保存':

    capacity

    • 接下来我们必须创建一个策略,允许AWS函数访问Cloudwatch日志以及你刚创建的table。 转到IAM控制台,选择'角色',然后选择'创建新角色'。 我们已经把我们的'apigatewaylambdaexecrole'叫做

    create role

    选择'自动气象站'角色:

    lambda role

    然后单击'下一步'跳过'附加策略'部分:

    skip attach policy

    在'审阅'部分中,单击蓝色'创建角色'按钮以完成:

    review role

    单击刚才创建的角色的标题,然后单击'内联策略'的向下箭头。 按照链接创建 inline 策略:

    inline policies

    单击'自定义策略'单选按钮,然后单击'选择':

    custom policy

    向自定义策略提供一个 NAME ( 我们叫我们的'loganddynamodbaccess'),然后在'策略文档'部分输入以下内容。 确定是使用还是设置为"资源",而第二个"sid"设置为"_yourtablename_dynamodbreadwrite"。 ( 可以在你的'表详细信息'去你的DynamoDB控制台,点击你的桌子。):

    
    {
    
    
    "Version":"2012-10-17",
    
    
    "Statement": [
    
    
     {
    
    
    "Sid":"AccessCloudwatchLogs",
    
    
    "Action": [
    
    
    "logs:*"
    
    
     ],
    
    
    "Effect":"Allow",
    
    
    "Resource":"arn:aws:logs:*:*:*"
    
    
     },
    
    
     {
    
    
    "Sid":"UsersDynamoDBReadWrite",
    
    
    "Effect":"Allow",
    
    
    "Action": [
    
    
    "dynamodb:DeleteItem",
    
    
    "dynamodb:GetItem",
    
    
    "dynamodb:PutItem",
    
    
    "dynamodb:UpdateItem"
    
    
     ],
    
    
    "Resource": [
    
    
    "arn:aws:dynamodb:eu-west-1:655240720487:table/Users"
    
    
     ]
    
    
     }
    
    
     ]
    
    
    }
    
    
    
    
    • 现在我们需要创建用于向 table ( 我们将在文本编辑器中创建和检索数据)的Lambda函数( 我们将在文本编辑器中创建函数,然后将它们上传到 Lambda。 按照前面的'Hello World'. zip 示例中的说明执行这里操作: !

    创建一个新的.js 文件,该文件包含我们的第一个Lambda函数。 这个函数将从 DynamoDB table 获取信息。 我们已经把文件 getUserInfo.js。 下面是代码:

    varAWS=require('aws-sdk');varDOC=require('dynamodb-doc');var dynamo =newDOC.DynamoDB();exports.handler=function(event, context) {
     varcallback=function(err, data) {
     if (err) {
     console.log('error on getUserInfo: ', err);
     context.done('Unable to retrieve user information', null);
     } else {
     if(data.Item&&data.Item.users) {
     context.done(null, data.Item.users);
     } else {
     context.done(null, {});
     }
     }
     };
     dynamo.getItem({TableName:"Users", Key:{username:"default"}}, callback);
    };

    压缩文件,然后将它的上载到 Lambda:

    zip -r getUserInfo.zip getUserInfo.js

    getuserinfo

    对于角色,请选择我们先前创建的角色。 然后单击'下一步',然后单击'创建函数':

    role

    单击'测试'以测试函数。 结果应该返回空的OBJEXT {}

    创建一个包含第二个Lambda函数的第二个 .js 文件。 这里函数将更新 DynamoDB table 中的信息。 我们已经把文件 updateUserInfo.js。 下面是代码:

    varAWS=require('aws-sdk');varDOC=require('dynamodb-doc');var dynamo =newDOC.DynamoDB();exports.handler=function(event, context) {
     var item = { username:"default",
     users:event.users|| {}
     };
     varcallback=function(err, data) {
     if (err) {
     console.log(err);
     context.fail('unable to update users at this time');
     } else {
     console.log(data);
     context.done(null, data);
     }
     };
     dynamo.putItem({TableName:"Users", Item:item}, callback);
    };

    再次压缩文件,然后将它的上载到 Lambda: zip -r updateUserInfo.zip updateUserInfo.js

    按照前面的步骤创建第二个函数,以创建第二个函数,使它的具有相同的角色。 它们都应该出现在你的函数部分中:

    functions

    使用与你的数据相关的示例事件测试函数。 我们创建了以下示例事件:

    
    {
    
    
    "users": [
    
    
     {
    
    
    "id": 1,
    
    
    "name":"John Smith",
    
    
    "location":"London"
    
    
    
     }
    
    
     ]
    
    
    }
    
    
    
    

    你应该看到一个空的obect,就像第一个函数 {}。 返回到GetUserInfo函数,然后再次单击'测试'。 现在,你应该在示例事件中看到一个返回的结果,如下所示:

    
    [
    
    
     {
    
    
    "id": 1,
    
    
    "location":"London",
    
    
    "name":"John Smith"
    
    
     }
    
    
    ]
    
    
    
    
    • 我们还得再创造一个Lambda函数。 它基本上不做任何事情,只是在CORS的OPTIONS ( 跨源资源共享,它是允许从网页请求受限资源的机制)的选择方法required要求。 函数如下所示:
    exports.handler=function(event, context) {
     context.succeed('');
     }

    像前面的Lambda函数一样上传:

    noop

    • 接下来进入Amazon网关控制台,通过单击'创建 API'创建一个新的API。 给它一个 NAME,我们已经调用了我们的API'secureusers':

    api gateway

    回调参数

    为了终止一个lambda函数,你必须使用 context.succeedcontext.fail 或者 context.error。 现在,支持 node v4.3,我们可以利用回调参数来显式返回调用方的信息。

    回调采用以下形式的两个参数 callback(Error error, Object result); 让我们看一个如何实现回调的快速示例。

    让我们编写一个简单的Lambda函数,该函数在通过SNS主题调用后返回一些文本:

    
    exports.handler = function (event, context, callback) {
    
    
     const message = JSON.parse(event.Records[0].Sns.Message);
    
    
     const text = message.content.text;
    
    
    //checking that the text exists
    
    
     if (text && text.length) {
    
    
     return callback(null, `Here is some text: ${text}`);
    
    
     } else {
    
    
    //if no text was found return this message
    
    
     return callback(null, 'No text was found');
    
    
     }
    
    
    }
    
    
    
    

    使用DynamoDB中的事件触发一个Lambda函数

    可以将Lambda函数设置为来自其他AWS服务( 如Dynamo表)的事件触发。 这可以用于生成响应数据修改的应用程序。

    创建一个启用了流的DynamoDB table
    • 在你的AWS控制台上单击DynamoDB选项卡。 然后单击蓝色'创建表格'按钮。

    create table

    在'lambdatest'字段中设置'表名'字段,并在'主键'字段中将'分区键'设置为'字符串'类型的'id'。 然后单击蓝色'创建'按钮。 然后你将被定向到DynamoDB仪表板。

    单击'管理流'按钮,然后在弹出窗口中选择'新建和旧图像'选项。

    Manage Streams

    Manage Streams Options

    现在已经启用了一个 enabled table with。

    创建一个Lambda函数,它将被对DynamoDB表的更改触发。
    • 在导航窗格中选择'表格'选项并选择刚刚创建的table。

    select table

    • 单击'创建新触发器'>'新功能'。 这将打开Lambda控制台。

    Triggers

    • 应该已经填充了'事件源类型'和'dynamodb表'字段。 单击"next"。

    New trigger name

    • 在'配置功能'部分,在'姓名'字段中给lambda函数一个 NAME。 比如'dynamodblambda'应将'运行时'设置为'node.js',并且'说明'已经被填充。

    'lambda函数代码'部分中已经存在一些缺省代码。 你可以将代码保留原样。 它只是记录来自DynamoDB事件中每个数据行的数据,以及操作 比如'插入','修改'。 我们将在以后的步骤中看到这些日志的输出。

    console.log('Loading function');exports.handler=function(event, context) {
     //console.log('Received event:', JSON.stringify(event, null, 2));event.Records.forEach(function(record) {
     console.log(record.eventID);
     console.log(record.eventName);
     console.log('DynamoDB Record: %j', record.dynamodb);
     });
     context.succeed("Successfully processed "+event.Records.length+" records.");
    };
    • 在'lambda函数处理程序和角色'部分中,选择'dynamodb事件流角色'选项。 这将打开一个新窗口来创建身份和访问管理角色( IAM )。 单击蓝色'允许'按钮以启用角色的创建。 这对于允许DynamoDB调用你的Lambda函数是必要的。

    role

    role name

    然后单击'''

    在 final 审阅页面的'事件源'部分中选择'立即启用'选项。 然后单击'函数''

    enable now option

    在DynamoDB表中创建数据。
    • 返回DynamoDB面板并选择'表格'选项卡>'lambdatest'。 单击'创建项目'这将打开弹出窗口。 为你的数据点输入一个'id'。 这可以是任何你想要的字符串。 然后单击'保存'。

    create data button

    create data save

    • 添加一些项目并执行一些操作来编辑/删除 table 比如 添加属性中的条目,delete 项。 这可以通过选择条目,然后点击'操作'下拉菜单来完成。 我们的Lambda函数将记录这些操作,并在Cloudwatch日志中显示。

    edit data

    edit data 2

    查看Lambda函数的输出,以响应对DynamoDB表的更改

    回到AWS面板打开Lambda控制台并选择刚刚创建的函数。

    选择'监视'选项卡,然后选择'查看CloudWatch中的日志'选项。 选择一个日志流。 应该从lambda函数中看到 console.log 输出,捕获在in表中对数据条目执行的创建。编辑和 delete 操作。

    view output

    view output 2

    现在可以修改lambda函数以执行来自DynamoDB的事件数据的不同操作。

    使用简单通知系统来触发一个Lambda函数

    Amazon SNS是一个发布者/订阅系统。 你可以创建。订阅和发布到'主题',这是消息通道的AWS术语。 Lambda函数可以订阅主题,因这里当发布消息时,将使用发布的消息作为输入参数调用Lambda函数。 Lambda函数可以使用消息中的信息做任何事,包括向同一主题或者其他主题发布进一步的消息。

    创建主题
    • 在 AWS SNS中单击'创建主题'按钮。

    create topic

    • 在弹出的弹出窗口中添加主题 比如'lambda测试'的NAME,然后单击蓝色'创建主题'按钮。 你应该会看到一条消息说'成功创建主题'。

    create topic pop up

    #### 创建一个Lambda函数并订阅一个主题

    按照这里上一节中的说明创建Lambda函数。 在步骤 3的步骤中选择'sns消息'蓝图。 这个功能将只记录推送到SNS主题的消息。

    在'配置事件源'下,你可以选择函数应该订阅的Lambda主题。 选择我们刚刚创建的那个: 'lambdatest'。

    configure sources

    • 为函数提供 NAME 比如'lambdasnstest'。 在Lambda函数代码Code中已经有了默认代码来对消息进行 console.log:
    console.log('Loading function');exports.handler=function(event, context) {
     //console.log('Received event:', JSON.stringify(event, null, 2));var message =event.Records[0].Sns.Message;
     console.log('From SNS:', message);
     context.succeed(message);
    };

    在执行角色部分中选择'基本执行角色'。 在弹出窗口中,启用lambda_basic_execution角色的创建并单击'允许'。

    在 final 审阅页面的'事件源'部分中选择'立即启用'选项。 单击'创建函数'。你应该通过确认messsage重定向回Lambda控制台: '恭喜你的Lambda函数"lambdasnstest"已经通过SNS成功创建和配置: ! LambdaTest作为事件源。"'

    lambda function created

    #### 将消息发布到主题

    • 打开SNS控制台并在左侧菜单中选择'主题'选项卡。 选择在早期步骤中创建的'lambdatest'主题。 然后单击蓝色'发布到主题'按钮。

    Publish to topic

    • 打开消息编辑器。 主题ARN是主题的'amazon资源名称'。 ARNs用于在所有AWS中明确指定资源。 我们不需要为这个例子担心它们 ! 给邮件发送主题并向消息 body 添加一些文本。 将'生存时间'字段留空并单击屏幕右下角的'发布消息'。 你应该被重定向回SNS控制台。

    Publish message

    NB: 使用 JSON Messsage生成器选项,可以为不同的查看平台设置不同的消息格式。 了解更多关于 AWS的SNS文档。

    查看lambda函数的输出
    • 打开Cloudwatch日志。 选择左边菜单中的'日志'选项卡。

    Logs tab

    • 单击LambdaSNSTest选项,然后单击第一个日志流。 它将带你到我们发布的SNS消息的日志输出 !

    Log stream

    Log stream output


    测试Lambda函数

    单元测试
    • 使用Lambda测试Lambda的代价 !

    这个方法使用Lambda本身作为测试平台。 这涉及创建调用测试的Lambda函数的"单位"测试,然后总结它是否成功或者失败以及/或者记录它的输出在内存中。 AWS Lambda有一个'单元和负载测试线束'蓝图,可以用来测试另一个Lambda函数,当它在AWS上运行时。 线束有两种模式: ''还有'负载'也可以执行简单的缩放测试。

    更多信息和一个例子可以在这里找到:。

    • 使用 node.js 断言库 生成 mock 事件和本地测试

    事件和上下文对象可以被模仿,以便在部署之前对lambda函数进行本地测试。 可以在 AWS Lambda控制台中使用'测试'函数,可以查看不同事件对象 比如 DynamoDB事件。SNS通知和其他事件的格式。

    查看一下 mock-events.js 插件以查看一些示例。 这些可以用于创建 helper 函数以生成 mock 事件。

    context对象具有以下形式:

    {
     //methods success,
     done,
     fail,
     getRemainingTimeInMillis,
     //properties functionName,
     functionVersion,
     invokedFunctionArn,
     memoryLimitInMB,
     awsRequestId,
     logGroupName,
     logStreamName,
     identity: {
     cognito_identity_id,
     cognito_identity_pool_id
     },
     clientContext: {
     client: {
     installation_id,
     app_title,
     app_version_name,
     app_version_code,
     app_package_name,
     Custom,
     },
     env: {
     platform_version
     platform,
     make,
     model,
     locale,
     }
     }
    }

    因为方法( successdonefail ) 是异步的,而且必须被模仿,而且在使用承诺的时候已经在 npm MODULE 上完成,这稍微困难了一些。

    它还不考虑不同的调用类型 换句话说,事件或者请求/响应。 有关 context.sucess 函数的AWS文档:

    如果使用事件调用类型( 异步调用) 调用Lambda函数,则该方法将返回"http状态 202,请求被接受"响应。 如果使用请求响应类型( 同步调用) 调用Lambda函数,该方法将返回HTTP状态 200 ( 行),并将响应> body 设置为结果的字符串表示形式。

    下面是使用'mock-context-object'MODULE 和'磁带'断言库的lambda函数和相关测试的示例。

    // very simple lambda functionexports.handler=function(event, context) {
     context.succeed(event.key1); // SUCCESS with message};
    // test set up and simple testvar context =require('aws-lambda-mock-context');var test =require('tape');var lambdaToTest =require('../functions/lambdaTest.js');// creating context objectvar ctx =context();// text event objectvar testEvent = {
     key1:'name'}var response =nullvar error =null;test("Capture response", t=> {
     lambdaToTest.handler(testEvent, ctx);
     //capture the response or errorsctx.Promise. then(resp=> {
     response = resp;
     t.end();
     })
    . catch(err=> {
     error = err;
     t.end();
     })
    })test("Check response", t=> {
     t.equals(response, 'name');
     t.end();
    })

    这里还可以找到在本地测试lambda函数的更多信息,这里可以找到一个通过模拟上下文对象来测试的示例,在这里是。

    • 使用grunt-aws-lambda插件

    Grunt插件拥有在本地运行Lambda函数以及对Lambda函数打包和部署的帮助器。

    更多信息和一个例子,可以找到这里,这里是。

    使用Codeship的 持续集成

    在编写测试之后,下一步是为你的Lambda函数设置 持续集成 ( CI ),因这里每次将代码推到GitHub时,测试都会被部署。 本示例介绍如何使用Codeship设置 CI。

    需要你的项目 repo的一些初始设置。 这涉及 Having 以正确格式的( 使用 exports.handler 函数) 函数文件,以及带有测试事件的data.json 文件。 流程将如下所示:

    • 将代码推送到 GitHub
    • 这触发了 Codeship
    • Codeship运行测试
    • 如果测试通过,Codeship将Lambda函数部署到 AWS,否则生成失败
    • Codeship在AWS上调用Lambda函数以检查活动版本是否按预期工作
    • 如果成功,Codeship报告生成成功 !

    用这个简单的例子进行收费,试着亲自设置过程。

    Codeship 创建一个免费帐户,并连接到你的GitHub帐户

    fork 在Github上使用这里 repo !

    在Codeship中创建一个项目,连接到分支的repo。

    如果步骤 1或者 3有任何问题,请按照 Codeship文档文档中的说明进行操作。

    • 在AWS上创建一个 hello Lambda函数在前面的部分。 在'配置'标签 ,确保处理程序的NAME 从'。索引处理程序'更改为'lambdatest。处理程序'。 'LambdaTest'将是我们通过Codeship上传到AWS的zip文件的NAME。

    还可以记下lambda函数的- 它可以在页面的右上角找到。 它应该具有以下形式: arn:aws:lambda:YOUR_AWS_REGION:YOUR_AWS_ACCOUNT_ID:function:YOUR_FUNCTION_NAME 在Codeship上设置部署脚本时,你将需要它。

    Lambda arn

    • 在AWS中为Codeship创建用户,并获得 AWS'访问键'和'访问密钥'。

    为了更新和调用函数,我们需要让Codeship访问AWS上的lambda函数。 to最佳实践建议创建一个用户可以添加的访问策略的组。

    导航到AWS控制台的'身份和访问管理'部分。

    IAM dashboard

    从左侧菜单中选择'用户'选项卡。 单击蓝色'创建新用户'按钮。 给第一个用户 NAME'codeship'( 我们已经完成了)。 确保'为每个用户生成访问密钥'复选框被选中。 然后单击'创建'。

    create user button

    new user

    在下一个屏幕上,单击'显示用户安全凭据'箭头。 它将向你显示这个用户的'访问键'和'访问密钥'。 把钥匙 ,把它们贴在一个安全的地方。 你将不会再次显示它们。

    下一步选择左侧窗格中的'组'选项卡。 单击蓝色'创建组'按钮。

    Create Group button

    给组 NAME'ci'或者你所选择的任何 NAME。 在'附加策略'下的下一页中,只需单击'下一步'。 我们将添加我们自己的定制策略。

    导航回 Groups tab并单击新创建的组。 选择'用户'选项卡,然后单击蓝色'将用户添加到该组'按钮。 然后你可以添加刚刚创建的用户。

    为了让Codeship访问更新。调用和检索 AWS Lambda函数,你需要添加访问策略。 选择选项卡'权限',然后单击'内联策略'>'新建一个'。

    Add a policy

    选择'自定义策略'选项并单击'选择'。

    Create policy

    在'策略名称'字段中添加'codeship策略'并在'策略文档'中添加以下文本:

     {
     "Version":"2012-10-17",
     "Statement": [
     {
     "Effect":"Allow",
     "Action": [
     "lambda:UpdateFunctionCode",
     "lambda:UpdateFunctionConfiguration",
     "lambda:InvokeFunction",
     "lambda:GetFunction",
     "lambda:CreateFunction",
     ],
     "Resource": [
     "YOUR_LAMBDA_FUNCTION_ARN_HERE" ]
     }
     ]
    }

    然后单击'验证策略',如果验证成功,单击'创建策略'。

    • 将AWS用户 环境变量 添加到Codeship项目中。 使用Codeship中的Environment tab添加'aws_access_key'。'aws_secret_access_key'和'aws_default_region'( 通常是'us-east-1')。 这是为了授权Codeship从aws命令执行命令。

    Environment variables

    • 为Codeship项目设置测试和部署脚本

    单击项目设置中的测试选项卡。

    Setup Commands

    你应该已经看到了下面的缺省代码:

    # We support all major Node.js versions. Please see our documentation for a full list.# https://documentation.codeship.com/basic/languages-frameworks/nodejs/## By default we use the Node.js version specified in your package.json file and fall# back to the latest version from the 0.10 release branch.## You can use nvm to install any Node.js version you require#nvm install 0.10nvm install 0.10

    为了运行测试,我们使用磁带,所以它还需要在虚拟机上全局安装。 在末尾添加此行:

    npm install -g tape
    npm install

    自动气象站( AWS ) 只支持 node 0.10,所以我们的测试( 用es6写的) babel piped,所以它们可以通过babel运行,而无需 node 4.0. 然而,这将不再是必需的。

    在'配置测试管道'下,在'测试命令'选项卡中添加 npm test

    在 Deployment,的'配置部署管道'下,选择要测试的GitHub上的分支的NAME。

    Deployment pipeline

    然后选择'自定义脚本'选项。

    Custom script

    下一页看起来像这样。 我们将在部署命令中添加自己的脚本。

    depoyment script

    我们将首先压缩lambda函数,然后使用 AWS cli更新AWS上的版本,finally 将使用测试事件来调用它。 将以下代码添加到部署命令中:

    pip install awscli
    zip -r LambdaTest.zip -j lambda-testing/functions/LambdaTest.js
    aws lambda update-function-code --function-name LambdaTest --zip-file fileb://LambdaTest.zip
    aws lambda get-function --function-name YOUR_LAMBDA_FUNCTION_ARN_HERE
    aws lambda invoke --function-name YOUR_LAMBDA_FUNCTION_ARN_HERE --payload file://lambda-testing/tests/data.json --log-type Tail lambda_output.txt
    cat lambda_output.txt
    • 做一个更改并向上推到 GitHub ! 尝试修改 LamdaTest.js 文件和/或者 data.json 文件,提交更改并将代码推到 GitHub。 这将触发 Codeship。查看生成日志以确保生成成功并且测试通过。

    Codeship build log

    还可以查看你的Lambda函数控制台中的监视选项卡。 你应该看到Codeship调用函数的一个尖峰。

    AWS monitoring log

    有关Codeship文档的更多信息,请参见:

    在S3中,将Lambda函数上载到an并自动部署到 Lambda ( bash脚本示例)

    在本例中将构建一个脚本,将执行一个必需步骤,将Lambda函数上传到 S3,然后自动部署它。

    我们将编写自己的bash脚本,其中包含一些AWS命令命令的使用。 按照以下说明在本地计算机上如何使用 AWS CLI设置:

    如果你还没有这么做,请在这里设置一个AWS英镑的帐户。

    然后,你需要通过执行以下操作来获取你的'访问密钥 ID'和'秘密访问密钥':

    • 打开IAM控制台
    • 在导航窗格中选择'用户''
    • 单击你的IAM用户名
    • 单击'安全凭据',然后'创建访问键"'
    • 要查看你的访问密钥,请选择Show用户安全凭证"。 你的凭据将类似于以下内容: 访问密钥 ID: AKIAIOSFODNN7EXAMPLE秘密访问密钥: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
    • 单击'下载凭据'并将它们存储在安全位置

    通过你选择的收费方法来安装 AWS CLI:。

    一旦安装完毕,你必须配置它。 在 命令行 中键入 aws configure。 你应该看到类似这样的内容:

    $ aws configure
    AWS Access Key ID [None]: AKIAIOSFODNN7EXAMPLE
    AWS Secret Access Key [None]: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
    Default region name [None]: eu-west-1
    Default output format [None]: ENTER

    输入aws访问密钥,秘密访问密钥和区域,然后在最后一个选项中按Enter键。
    你现在应该go了 !

    下一步在文本编辑器中编写一个Lambda函数,如果还没有。 请查看我们的前一个示例 ,直到第1 步 ( 我们将在这个例子中自动压缩压缩)。

    一旦你完成了这一点,你将想要创建一个新的S3桶,它将存储所有上传的Lambda函数。 单击AWS管理控制台窗口上的S3控制台:

    s3 console

    单击'创建桶'按钮。 给你的S3 Bucket一个 NAME 并选择它的区域。 我们已经把我们的'lambda-function-container'叫做

    s3 create bucket

    • 接下来,你将编写一个bash脚本,该脚本将执行 3个命令。 第一种是创建部署包( 包含你的lambda函数及其依赖关系的. zip 文件)。 第二个将把部署包上载到新创建的S3 Bucket。 第三个将从S3部署你的Lambda函数。

    为此创建一个新文件并将它的命名为任何你想要的,并将它的保存为 .sh 文件。 我们已经调用了'lambda-upload-create。sh'。3命令需要变量作为输入,这就是为什么我们包含 echo & read bash命令,以便暂时保存这些输入:

    echo and read

    我们试图尽可以能少的变量输入,以便在将 margin 输入 命令行 时减少错误。 以下是我们的zip和 AWS CLI命令:

    第一个命令( 邮编) 接受两个输入:要创建的zip文件的NAME 和要压缩的文件的名称。 ( 在我们的例子中,它将是上传和 upload.js,因为我们没有依赖)

    zip -r "$ZipFileName.zip"$FilesToBeZipped

    上传命令'放置对象'采用三个输入( of )的NAME,它是zip文件的文件路径和 body 中的。

    aws s3api put-object --bucket $BucketName --key "./$ZipFileName.zip" --body "./$ZipFileName.zip"

    deployment命令使用五个输入 NAME 函数,zip zip zip runtime zip zip zip zip zip zip'创建函数'role optional role optional optional optional optional optional optional。

    aws lambda create-function --function-name $FunctionName --runtime nodejs 
    --role $Role --handler "$ZipFileName.handler" 
    --code S3Bucket="$BucketName",S3Key="./$ZipFileName.zip" 
    --description $Description
    • 让我们创建将在 package.json 中运行的脚本,这将触发刚刚创建的.sh 文件:

    script link

    为了能够运行我们的脚本,我们必须使它为 可以执行的。 将这里命令键入你的终端:

    chmod +x (filenameOfScript.sh)

    • 在我们运行脚本之前,一个 final 步骤。 回到 AWS,进入IAM控制台,因为你需要添加一些策略,使你能够执行诸如'创建函数'或者'放置对象'之类的某些方法。

    单击组,然后选择'创建组'。 我们创建了一个'public'组,你创建它后,单击它: create group

    单击'附加策略'按钮,然后从列表中选择'iamfullaccess': Attach policy

    单击 inline 策略部分中的'创建组策略': inline policy

    选择'自定义策略',然后按'选择'按钮: custom policy

    创建自定义策略我们已经包含了必要的效果,操作和资源,以便完全访问。 然后单击'应用策略': create custom policy

    创建组之后,你将需要向它的添加用户。 添加到该组的任何用户都具有相同的权限。 如果你还没有创建用户,可以在这里执行以下操作: create user

    返回刚才创建的组,然后单击'将用户添加到组',然后选择要添加的用户。 用户应该是分配给它的访问密钥for和密钥访问密钥的用户。 add users

    我们现在应该可以用我们的脚本进行旋转 !

    • 在 命令行 中,在 package.json 中运行脚本。 我们的如下: $ npm run upload

    这应该首先提示 echoread 命令:

    Enter the name of the files you wish to zip (eg. lambdaFunction.js node_modules): upload.js
    Enter the name of the output zip file (eg. lambdaFunction): upload
    Enter the name of the s3 bucket you wish to upload to: lambda-function-container
    Enter the name of your lambda function: Upload
    Enter the ARN of the role you wish to implement: arn:aws:iam::655240711487:role/lambda_basic_execution

    点击进入后,它应该会返回:

    adding: upload.js (deflated 17%)
    {
     "ETag": ""519e9cfc9a2ee33412ba813c82f33a56fa3"" }
    {
     "CodeSha256": "nbYYHfHKyYSlb09Dpw7vf7wB93F+9V8XEmaTBU=",
     "FunctionName": "Upload",
     "CodeSize": 249,
     "MemorySize": 128,
     "FunctionArn": "arn:aws:lambda:eu-west-1:655240711487:function:Upload",
     "Version": "$LATEST",
     "Role": "arn:aws:iam::655240711487:role/lambda_basic_execution",
     "Timeout": 3,
     "LastModified": "2016-01-28T13:31:28.627+0000",
     "Handler": "upload.handler",
     "Runtime": "nodejs",
     "Description": "Bash Script Tutorial"}
    • 转到S3以检查部署包是否已经上载。 你应该可以看到你的.ZIP file:

    s3 uploaded

    • 转到Lambda以检查你的Lambda函数是否已经启用:

    lambda enabled

    就是这样你现在应该能够使用一个bash脚本上传和部署一个Lambda函数了。

    使用Gulp部署Lambda函数

    可以用于自动压缩。部署和测试AWS上的Lambda函数。 然后可以将Codeship部署脚本简化为单个命令 gulp deploy

    创建新的吞咽任务的语法是"

    gulp.task('name of task', function() {
     return//gulp functions to run})

    有许多插件可以执行操作,如检索。移动和压缩文件。 这些动作也是可以链接的。

    我们将完成一个简单的吞咽脚本,其中包含每个步骤的任务。

    • 在所有相关模块和文件中需要。 我们将使用 aws sdk来部署和调用lambda函数。 我们还需要读取 package.json 文件,以便将 node 模块添加到zip文件中。
    
    ```js
    
    
    var AWS = require('aws-sdk');
    
    
    var gulp = require('gulp');
    
    
    var zip = require('gulp-zip');
    
    
    var install = require('gulp-install');
    
    
    var runSequence = require('run-sequence');
    
    
    var fs = require('fs');
    
    
    
    var packageJson = require('./package.json');
    
    
    ```
    
    
    
    
    • 声明常数。
    
    ```js
    
    
    var region = 'eu-west-1';//AWS region
    
    
    var functionName = 'LambdaTest'; 
    
    
    var outputName = 'LambdaTest.zip';//name to be given to output zip file
    
    
    
    //the ARN of the execution role to be given to the lambda function - change this to a role from your account
    
    
    var IAMRole = 'arn:aws:iam::685330956565:role/lambda_basic_execution';
    
    
    
    //the paths of the files to be added to the zip folder
    
    
    var filesToPack = ['./lambda-testing/functions/LambdaTest.js'];
    
    
    
    ```
    
    
    
    **Make sure the IAM role is changed to the ARN of a role from your AWS account and the region is set to the AWS region you want to deploy the Lambda function to!**
    
    
    
    
    • 创建存档文件夹并添加项目文件
    
    ```js
    
    
    gulp.task('js', function () {
    
    
     return gulp.src(filesToPack, {base: './lambda-testing/functions'})
    
    
    . pipe(gulp.dest('dist/'));
    
    
    });
    
    
    ```
    
    
    
    `gulp.src` takes an array of file paths as the first argument and an options object as the second. If you specify a base file path in the options only the folders/files after the base are copied i.e. in this case, only the LambdaTest.js file is copied into the archive folder (`dist`). 
    
    
    
    
    • 将 node 模块添加到存档文件夹中
    
    ```js
    
    
    gulp.task('node-modules', function () {
    
    
     return gulp.src('./package.json')
    
    
    . pipe(gulp.dest('dist/'))
    
    
    . pipe(install({production: true}));
    
    
    });
    
    
    ```
    
    
    
    In this task, the `package.json` file is copied to the archive folder and the 'gulp-install' module is used to do an `npm install --production` of all the listed dependencies.
    
    
    
    
    • 压缩存档文件夹并保存它。
    
    ```js
    
    
    gulp.task('zip', function () {
    
    
     return gulp.src(['dist/**', '!dist/package.json'])
    
    
    . pipe(zip(outputName))
    
    
    . pipe(gulp.dest('./'));
    
    
    });
    
    
    ```
    
    
    
    All the files in the dist folder apart from the `package.json` file are zipped up using the 'gulp-zip' module and save in the root of the project folder.
    
    
    
    
    • 将压缩文件上载到 AWS。 如果函数已经存在,则更新它,否则创建一个新函数。
    
    We can create an 'upload' task with gulp
    
    
    
    ```js
    
    
    gulp.task('upload', function() {})
    
    
    ```
    
    
    
    Inside the function we first have to do a bit of set up:
    
    
    
    ```js
    
    
    AWS.config.region = region;//this is set to eu-west-1 from the constants declared in step 1
    
    
    var lambda = new AWS.Lambda();
    
    
    var zipFile = './' + outputName;//the outputName has also been set in step 1
    
    
    ```
    
    
    
    First we need to check if the function already exists on AWS before deciding whether to create a function or update a function.
    
    
    
    ```js
    
    
    lambda.getFunction({ FunctionName: functionName }, function(err, data) {
    
    
     if (err) createFunction();
    
    
     else updateFunction();
    
    
    });
    
    
    ```
    
    
    
    We also need a function to retrieve the saved zip file in order to pass it in as a parameter in our create function command.
    
    
    
    ```js
    
    
    function getZipFile (callback) {
    
    
     fs.readFile(zipFile, function (err, data) {
    
    
     if (err) console.log(err);
    
    
     else {
    
    
     callback(data);
    
    
     }
    
    
     });
    
    
    }
    
    
    ```
    
    
    The `getZipFile` function takes a callback which gets called with the file data if the file is read successfully.
    
    
    
    Using the aws-sdk we can then define a function to create a new Lambda function from this zip file.
    
    
    
    ```js
    
    
    function createFunction () {
    
    
    
     getZipFile(function (data) {
    
    
     var params = {
    
    
     Code: {
    
    
     ZipFile: data//buffer with the zip file data
    
    
     },
    
    
     FunctionName: functionName,//functionName was set in the constants in step 1
    
    
     Handler: 'LambdaTest.handler',//need to set this as the name of our lambda function file is LambdaTest.js
    
    
     Role: IAMRole,//IAMRole was set in the constants in step 1
    
    
     Runtime: 'nodejs'
    
    
     };
    
    
    
     lambda.createFunction (params, function (err, data) {
    
    
     if (err) console.error(err);
    
    
     else console.log('Function ' + functionName + ' has been created.');
    
    
     });
    
    
     });
    
    
    
    }
    
    
    ```
    
    
    Similarly we can also define `updateFunction`:
    
    
    
    ```js
    
    
    function updateFunction () {
    
    
    
     getZipFile(function (data) {
    
    
     var params = {
    
    
     FunctionName: functionName,
    
    
     ZipFile: data
    
    
     };
    
    
    
     lambda.updateFunctionCode(params, function(err, data) {
    
    
     if (err) console.error(err);
    
    
     else console.log('Function ' + functionName + ' has been updated.');
    
    
     });
    
    
     });
    
    
    }
    
    
    ```
    
    
    
    
    • 调用带有测试事件的函数来检查活动版本是否按预期工作。
    
    We have to first get the function to make sure it exists and only invoke it if there isn't an error.
    
    
    
    In the parameters for invoking the function, a JSON object can be specified as the 'Payload' and the 'InvocationType' can be specified as 'RequestResponse' if you want to get a response body.
    
    
    
    ```js
    
    
    gulp.task('test-invoke', function() {
    
    
     var lambda = new AWS.Lambda();
    
    
    
     var params = {
    
    
     FunctionName: functionName,
    
    
     InvocationType: 'RequestResponse',
    
    
     LogType: 'Tail',
    
    
     Payload: '{"key1" :"name" }'
    
    
     };
    
    
    
     lambda.getFunction({ FunctionName: functionName }, function(err, data) {
    
    
     if (err) console.log("Function" + functionName +"not found", err);
    
    
     else invokeFunction();
    
    
     });
    
    
    
     function invokeFunction() {
    
    
     lambda.invoke(params, function(err, data) {
    
    
     if (err) console.log(err, err.stack);
    
    
     else console.log(data);
    
    
     })
    
    
     }
    
    
    })
    
    
    ```
    
    
    
    
    • 创建一个部署任务,该任务按正确顺序依次运行所有 上面 任务。
    
    The `runSequence` module takes a comma separated list of gulp task names or a list of arrays with gulp tasks, and ends with a callback. The tasks are run in the order they are specified. To run two tasks in parallel specify them in the same array.
    
    
    
    ```js
    
    
    gulp.task('deploy', function (callback) {
    
    
     return runSequence(
    
    
     ['js', 'node-modules'],
    
    
     ['zip'],
    
    
     ['upload'],
    
    
     ['test-invoke'],
    
    
     callback
    
    
     );
    
    
    });
    
    
    ```
    
    
    
    **In the AWS console you can only view functions by region, so if you can't see the function after it has been created, check you're looking at the correct region (in the dropdown menu in the top right of the console)**
    
    
    
    ![AWSregion](https://cloud.githubusercontent.com/assets/5912647/12677661/75d12846-c692-11e5-878d-990487be9910.png)
    
    
    
    
    • 将部署脚本添加到Codeship或者 package.json
    
    In Codeship just add `gulp-deploy` to your Deployment script and you're good to go!
    
    
    
    **Note: Make sure the Access Policy of the Codeship User in the IAM console on AWS has permissions for all the actions you're trying to execute. i.e. getting, creating, updating and invoking lambda functions.**
    
    
    
    
    上传到S3并使用Gulp部署到 Lambda

    在这里我们将实现上一个示例,将Lambda函数上载到 S3,然后从bucket中部署它。 使用bash脚本的Intead,我们可以使用 Gulp。 我们可以对刚刚创建的Gulp示例进行一些小调整,以便从S3部署。 这是一个延续,因这里请在查看这个之前检查一下:

    我们要创建一个新的Gulp任务,它将上传我们的zip文件。 我们已经调用了任务'upload-to-s3',并在压缩任务之后包含它。

    我们首先要使用 AWS SDK创建一个新的S3实例,因为我们需要访问一些S3方法。 然后声明要上载的zip文件的路径,以用作S3键。 然后创建一个'getzipfile'函数来获取参数的'正文',并环绕'putObject'方法。 然后编写S3方法takes接收参数 ( 对象具有'桶','key body,当返回来自服务的响应时调用一个处理错误的回调函数。

    gulp.task('upload-to-s3', function () {
     var s3 =newAWS.S3();
     var zipFilePath ='./'+ outputName;
     getZipFile(function (data) {
     var params = {
     Bucket:'lambda-function-container',
     Key: zipFilePath,
     Body: data
     };
     s3.putObject(params, function(err, data) {
     if (err) console.log('Object upload unsuccessful!');
     elseconsole.log('Object '+ outputName +' was uploaded!');
     });
     });
     functiongetZipFile (next) {
     fs.readFile(zipFilePath, function (err, data) {
     if (err) console.log(err);
     else {
     next(data);
     }
     });
     }
    });

    接下来,我们需要将新任务添加到我们已经创建的runSequence中的任务列表中。 我们希望它在压缩之后,但在'上载'任务之前:

    gulp.task('deploy', function (callback) {
     returnrunSequence(
     ['js', 'node-mods'],
     ['zip'],
     ['upload-to-s3'],
     ['upload'],
     ['test-invoke']
     callback
     );
    });

    为了从S3部署Lambda函数,我们需要调整我们先前创建的'createfunction'&'updateFunction'Lambda方法。

    我们需要将'代码'参数从 ZipFile: data 更改为:

    functioncreateFunction () {
     var params = {
     Code: {
     S3Bucket: bucketName,
     S3Key: zipFile
     },
     FunctionName: functionName,
     Handler:'LambdaTest.handler',
     Role: IAMRole,
     Runtime:'nodejs' };
     lambda.createFunction (params, function (err, data) {
     if (err) console.error("CREATE ERROR", err);
     elseconsole.log('Function '+ functionName +' has been created.');
     });
    }

    然后,我们需要对'updateFunction'执行同样的操作:

    functionupdateFunction () {
     var params = {
     FunctionName: functionName,
     S3Bucket: bucketName,
     S3Key: zipFile
     };
     lambda.updateFunctionCode(params, function(err, data) {
     if (err) console.error(err);
     elseconsole.log('Function '+ functionName +' has been updated.');
     });
    }

    因为我们添加了一些AWS方法,所以我们需要更新策略以便它支持。 进入你的IAM控制台并添加必要的方法。 这里是我们

    policy 首先,我们包含一个方法来检查对象是否已经被上传。

    functioncheckObject (fn) {
     var params = {
     Bucket: bucketName,
     Key: zipFile
     };
     s3.getObject(params, function (err, data) {
     if (err) console.log('BUCKET ERROR', err);
     elsefn();
     });
    }

    你的剧本应该是好的 ! 一旦你运行了它的S3和Lambda控制台检查你的Lambda函数是否已经上载和部署:

    uploaded

    deployed

    使用我们编写的部署服务器部署你的Lambda函数- npm dpl

    我们决定编写 dpl 来使部署你的Lambda函数非常简单。 下面是实现它的方法。

    • $ npm install dpl --save-dev
    • 配置你的环境变量。你需要 AWS_REGIONAWS_IAM_ROLE
    
    export AWS_REGION=eu-west-1
    
    
    export AWS_IAM_ROLE=arn:aws:iam::123456789:role/LambdaExecRole
    
    
    
    
    • 添加要部署到你的package.json的文件的列表
    "files_to_deploy": [ "package.json", "index.js", "lib/" ]
    • 将部署脚本添加到 package.json
    "scripts": {
     "deploy": "dpl"}
    • 运行脚本 $ npm run deploy

    版本控制和别名Lambda函数

    AWS上可以同时运行一个Lambda函数的多个版本。 每一个都有唯一的。 这允许不同版本在开发工作流 比如 开发。测试。登台。生产 等等 版本的不同阶段都是不可变的。

    别名是指向特定Lambda函数版本的指针。 别名是可变的,可以更改为指向不同的版本。 例如你可能有两个别名'开发'和'产品',分别代表'开发'和'生产'。 可以使用Lambda函数别名在事件源映射中每次更新特定版本的in。 当新版本升级到生产时,只需要更改别名,并且事件源将自动指向正确的版本。 这里工作流还可以轻松回滚到以前版本。

    版本控制

    在创建Lambda函数 比如'helloworld'时,它的版本会自动设置为 $LATEST。 版本是函数的Lambda ARN的最后一部分:

    arn:aws:lambda:aws-region:acct-id:function:helloworld:$LATEST

    如果在控制台中更新了Lambda函数或者使用cli更新了 $LATEST 版本中的代码,则 $LATEST 版本是可以变的换句话说,。

    你还可以从 $LATEST 版本发布新版本。 已经发布版本的将被替换为版本号: 比如 版本 1:

    arn:aws:lambda:aws-region:acct-id:function:helloworld:1

    如果你想更改代码或者配置的任何部分,则发布的版本是不可变的,你必须修改 $LATEST,然后发布新版本。 如果 $LATEST 版本未更改,则无法发布新版本。

    别名

    可以为现有的Lambda函数创建别名。 别名和lambda函数具有不同的ARNS,因为它们是唯一的AWS资源。

    使用别名意味着调用事件源不必知道别名指向的特定Lambda函数版本。 它启用

    • 易于升级或者回滚( 别名可以很容易地映射到不同的函数版本)
    • 更易于事件源映射- 更多控制在开发环境中与特定事件源一起使用的函数版本

    AWS 文档中使用 AWS CLI实现版本管理和别名

    使用Lambda函数创建一个 API,使用Lambda函数从DynamoDB表检索/更新记录。

    • 首先,我们需要在DynamoDB中创建一个 table。 转到DynamoDB控制台and然后单击'创建表格'按钮。 给你的table 一个 NAME ( 把它命名为 DynamoDB table 将保存的数据类型)。 我们已经调用了'用户'。'主键'是由'分区键'( 散列键) 和可选的'排序关键字'组成的。 ( 分区键用于跨主机分区数据,以实现可伸缩性和可用性):

    create table

    table name

    对于'表格设置',选中'使用默认设置'复选框,然后单击蓝色'创建'按钮:

    table setup

    创建 table 之后,单击'闹钟'选项卡,然后在创建基本警报时单击 delete:

    alarms

    然后单击'容量'选项卡,然后将'读取'和'写入'容量单位指定为 3,然后单击'保存':

    capacity

    接下来我们必须创建一个策略,允许AWS函数访问Cloudwatch日志以及你刚创建的table。 转到IAM控制台,选择'角色',然后选择'创建新角色'。 我们已经把我们的'apigatewaylambdaexecrole'叫做

    create role

    选择'自动气象站'角色:

    lambda role

    然后单击'下一步'跳过'附加策略'部分:

    skip attach policy

    在'审阅'部分中,单击蓝色'创建角色'按钮以完成:

    review role

    单击刚才创建的角色的标题,然后单击'内联策略'的向下箭头。 按照链接创建 inline 策略:

    inline policies

    单击'自定义策略'单选按钮,然后单击'选择':

    custom policy

    向自定义策略提供一个 NAME ( 我们叫我们的'loganddynamodbaccess'),然后在'策略文档'部分输入以下内容。 确定是使用还是设置为"资源",而第二个"sid"设置为"_yourtablename_dynamodbreadwrite"。 ( 可以在你的'表详细信息'去你的DynamoDB控制台,点击你的桌子。):

    
    {
    
    
    "Version":"2012-10-17",
    
    
    "Statement": [
    
    
     {
    
    
    "Sid":"AccessCloudwatchLogs",
    
    
    "Action": [
    
    
    "logs:*"
    
    
     ],
    
    
    "Effect":"Allow",
    
    
    "Resource":"arn:aws:logs:*:*:*"
    
    
     },
    
    
     {
    
    
    "Sid":"UsersDynamoDBReadWrite",
    
    
    "Effect":"Allow",
    
    
    "Action": [
    
    
    "dynamodb:DeleteItem",
    
    
    "dynamodb:GetItem",
    
    
    "dynamodb:PutItem",
    
    
    "dynamodb:UpdateItem"
    
    
     ],
    
    
    "Resource": [
    
    
    "arn:aws:dynamodb:eu-west-1:655240720487:table/Users"
    
    
     ]
    
    
     }
    
    
     ]
    
    
    }
    
    
    
    

    现在我们需要创建用于向 table ( 我们将在文本编辑器中创建和检索数据)的Lambda函数( 我们将在文本编辑器中创建函数,然后将它们上传到 Lambda。 按照前面的'Hello World'. zip 示例中的说明执行这里操作: !

    创建一个新的.js 文件,该文件包含我们的第一个Lambda函数。 这个函数将从 DynamoDB table 获取信息。 我们已经把文件 getUserInfo.js。 下面是代码:

    varAWS=require('aws-sdk');varDOC=require('dynamodb-doc');var dynamo =newDOC.DynamoDB();exports.handler=function(event, context) {
     varcallback=function(err, data) {
     if (err) {
     console.log('error on getUserInfo: ', err);
     context.done('Unable to retrieve user information', null);
     } else {
     if(data.Item&&data.Item.users) {
     context.done(null, data.Item.users);
     } else {
     context.done(null, {});
     }
     }
     };
     dynamo.getItem({TableName:"Users", Key:{username:"default"}}, callback);
    };

    压缩文件,然后将它的上载到 Lambda:

    zip -r getUserInfo.zip getUserInfo.js

    getuserinfo

    对于角色,请选择我们先前创建的角色。 然后单击'下一步',然后单击'创建函数':

    role

    单击'测试'以测试函数。 结果应该返回空的OBJEXT {}

    创建一个包含第二个Lambda函数的第二个 .js 文件。 这里函数将更新 DynamoDB table 中的信息。 我们已经把文件 updateUserInfo.js。 下面是代码:

    varAWS=require('aws-sdk');varDOC=require('dynamodb-doc');var dynamo =newDOC.DynamoDB();exports.handler=function(event, context) {
     var item = { username:"default",
     users:event.users|| {}
     };
     varcallback=function(err, data) {
     if (err) {
     console.log(err);
     context.fail('unable to update users at this time');
     } else {
     console.log(data);
     context.done(null, data);
     }
     };
     dynamo.putItem({TableName:"Users", Item:item}, callback);
    };

    再次压缩文件,然后将它的上载到 Lambda: zip -r updateUserInfo.zip updateUserInfo.js

    按照前面的步骤创建第二个函数,以创建第二个函数,使它的具有相同的角色。 它们都应该出现在你的函数部分中:

    functions

    使用与你的数据相关的示例事件测试函数。 我们创建了以下示例事件:

    
    {
    
    
    "users": [
    
    
     {
    
    
    "id": 1,
    
    
    "name":"John Smith",
    
    
    "location":"London"
    
    
    
     }
    
    
     ]
    
    
    }
    
    
    
    

    你应该看到一个空的obect,就像第一个函数 {}。 返回到GetUserInfo函数,然后再次单击'测试'。 现在,你应该在示例事件中看到一个返回的结果,如下所示:

    
    [
    
    
     {
    
    
    "id": 1,
    
    
    "location":"London",
    
    
    "name":"John Smith"
    
    
     }
    
    
    ]
    
    
    
    
    • 我们还得再创造一个Lambda函数。 它基本上不做任何事情,只是在CORS的OPTIONS ( 跨源资源共享,它是允许从网页请求受限资源的机制)的选择方法required要求。 函数如下所示:
    exports.handler=function(event, context) {
     context.succeed('');
     }

    像前面的Lambda函数一样上传:

    noop

    • 接下来进入Amazon网关控制台,通过单击'创建 API'创建一个新的API。 给它一个 NAME,我们已经调用了我们的API'secureusers':

    api gateway

    单击'创建资源'按钮,然后为你的资源提供 NAME。 我们已经把我们的'用户'叫做

    create resource button

    再次单击'创建资源'以确认它:

    create resource config

    • 在左侧,单击刚刚创建的端点。 我们的是 /users。然后单击'创建方法'并将它的设置为'获取':

    GET

    选择'lambda函数'单选按钮,然后将它分配给我们先前创建的获取函数,然后按'保存':

    assign GET function

    单击'测试'你应该在响应正文中看到一个空对象 {}:

    GET test

    • 重复前面的步骤,而不是'获取',将该方法设置为'POST':

    POST

    单击'测试',但这次在请求 body 中添加一些细节。 我们添加了两个用户:

     {"users": [ {"id": 1, "name": "Peter", "surname": "Smith"},
     {"id": 2, "name": "John", "surname": "Walsh"}
     ]
     }
    • 返回到'获取'方法,然后再次单击'测试'。 你现在应该能够看到 table 已经使用你测试的'POST'请求的详细信息进行了更新。

    GET test 2

    完成你现在可以设置Lambda函数,该函数可以在 table 中调用通过API网关调用的信息。

    无服务器框架 ( 以前称为 JAWS )

    自动创建服务器 Serverless Serverless是一个框架,允许你构建在AWS服务器和 AWS API网关上运行的应用程序。

    :为什么使用它

    这个框架使得部署本地机器上的Lambda函数和API网关端点变得非常容易。 它也很简单,很容易地在本地测试你的。 如果你想了解更多信息,请查看无服务器的repo 服务器。

    我们将通过这些步骤来设置它们的示例项目'无服务器启动程序'。 如果你没有检查我们以前的例子,就如何创建和部署Lambda函数,我们强烈建议你: 下面是设置无服务器示例项目'无服务器启动程序'的步骤。

    如果你还没有这么做的话,先创建一个AWS帐号。 按照前面示例中的步骤执行这里操作。

    转到IAM控制台。 我们要创建一个新的'用户',我们的服务器应用程序将能够使用并附加必要的策略来初始化它。 转到'用户'选项卡,然后单击'创建新用户'。 给你的用户一个 NAME,然后单击'创建'。 我们已经把我们的'无服务器管理员'叫做

    serverless user

    创建用户后,请单击 show credentials。 记下它们,然后下载它们。 ( 保持安全。我们稍后需要他们)

    credentials

    单击新创建的用户,然后单击蓝色'附加策略'按钮。 选择'administratoraccess'策略,然后再次单击'附加策略'按钮以附加它。

    attach policy

    以下是我们的无服务器管理员用户的摘要:

    user summary

    • 接下来,如果还没有这样做的话,你就必须安装 AWS CLI。 你可以通过这里的任何方法 完成之后,在 命令行 中键入 aws configure 命令。 使用你刚设置的用户访问ID和秘密访问 ID,选择你的区域,然后按enter键获取最后一个选项:
    $ aws configure
    AWS Access Key ID [None]: AKIAIOSFODNN7EXAMPLE
    AWS Secret Access Key [None]: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
    Default region name [None]: eu-west-1
    Default output format [None]: ENTER

    ( 注意:即使你以前已经这样做过,你仍然需要重新配置你的AWS CLI )

    • 现在,你应该开始使用无服务器了。 运行这里命令以全局安装该命令:

    $ npm install serverless -g

    • 是时候建立你的项目了。 出于演示目的,我们选择运行无服务器的starter,这是由无服务器服务器提供。 将来我们将向你展示如何设置你自己的项目,但是现在这是你需要使用框架的全部。 在你的终端中运行这里命令:

    $ serverless project install serverless-starter

    你将看到这里屏幕,然后提示插入一些数据:

    project data

    输入你希望无服务器备份你的Lambda函数的桶的NAME 以及发送报警的电子邮件。 选择你所在的区域,然后选择默认的AWS配置文件:

    Serverless: Enter a universally unique project bucket name: (serverless-starter-nkatqu-ejl6y9.com) learn-serverless
    Serverless: Enter an email to use for AWS alarms: (me@serverless-starter-nkatqu.com) example@email.com
    Serverless: Select a region for your project:
     us-east-1
     us-west-2
     > eu-west-1
     ap-northeast-1
    Serverless: Select an AWS profile for your project:
     > default
    Serverless: Creating stage "dev"... 
    Serverless: Creating region "eu-west-1"in stage "dev"... 
    Serverless: Creating your project bucket on S3: serverless.eu-west-1.learn-serverless... 
    Serverless: Deploying resources to stage "dev"in region "eu-west-1" via Cloudformation (~3 minutes)... 
    Serverless: No resource updates are to be performed. 
    Serverless: Successfully created region "eu-west-1" within stage "dev" 
    Serverless: Successfully created stage "dev" 
    Serverless: Installing nodejs dependencies for component: restApi... 
    serverless-helpers-js@0.0.3 node_modules/serverless-helpers-js
    └── dotenv@1.2.0
    Serverless: Successfully initialized project "serverless-starter" 
    Serverless: Successfully installed project "serverless-starter"
    • 现在,你应该能够在目录中看到无服务器启动文件:

    serverless-starter files

    • 点击它。让我们看看什么是 inside。 点击'restapi'文件夹。 在那里,你应该可以看到 lib,多个目录和单个目录:

    inside the files

    lib - 保存跨所有函数共享的代码
    multi - 这是一个包含多个Lambda函数的无服务器 MODULE
    single - 这是另一个无服务器 MODULE,包含一个具有多个端点的Lambda函数

    multi 目录中单击 create 目录,然后单击 s-function.json 文件。 这里文件包含该Lambda函数的端点配置信息。

    endpoint

    single 目录中单击 all 目录,然后导航到它的s-function.json 文件。 在这里你可以看到,一个单一的函数已经配置了多个端点。 ( 获取,发布,删除,删除)

    endpoints

    • 接下来,我们将在本地运行Lambda函数。 在 命令行 中键入以下命令。 第三条是你的功能路线。 我们正在测试'全部'函数,所以我们的是:

    $ serverless function restApi/single/all

    然后,你应该看到函数运行并返回结果:

    
    Serverless: Running restApi/single/all... 
    
    
    Serverless: ----------------- 
    
    
    Serverless: Success! - This Response Was Returned: 
    
    
    Serverless: {"message":"Your Serverless function ran successfully via the 'GET' method!"}
    
    
    
    

    注意:这个函数将从 event.json 文件中获取事件,以便你可以配置你的负载。 our测试函数需要一个带有'httpmethod'键的对象,因此我们的event.json 文件如下所示:

    {
     "httpMethod": "GET"}
    • 一旦我们对Lambda函数和API网关端点满意了,我们就可以使用 $ serverless dash deploy 命令。然后使用向上和向下箭头键导航,然后选择( 按 enter 键)。 然后,你选择的那些将在你移回到'部署'并按下 enter 之后被部署。 选定的内容以黄色显示:

    deploy serverless

    然后你将在你的终端中看到:

    deploying in process

    • 然后,我们可以转到AWS并查看 S3。Lambda和API网关控制台,看看是否部署了正确的内容:

    API网关 Api deploy

    S3 S3 deploy

    Lambda lambda deploy

    ( 无服务器框架自动化了我们在前面例子中介绍的许多过程,比如上传到S3并部署 Lambda。)

    进一步阅读


    词汇表

    • IAM - 身份和访问管理
    • 阿恩- Amazon资源编号
    • 事件源- 事件源发布导致一个Lambda函数被调用的事件。

    关注?

    令人兴奋的是,令人难以置信的服务,它只是自然的,只有很少的关注:

    限制?

    AWS Lambda有一个默认安全节流限制为个并发的Lambda函数执行每个账户。 请参阅:http://docs.aws.amazon.com/lambda/latest/dg/limits.html

    : 这是否意味着我们可以在任意给定时间处理请求?
    ::: 不,这取决于Lambda函数需要多久才能完成。 一个要求 90ms 完成的请求意味着你的Lambda函数可以处理英镑 1000 concurrent并发请求 。 如果你觉得 low low panic panic panic if need request request request request request Service Service Service Service Service Support Support Service Service Service。

    供应商锁定?

    AWS Lambda是一种基于动态扩展的方法来执行代码,没有其他供应商提供类似于你将会被bound的something AWS AWS AWS AWS AWS直到其他人赶上( 复制 AWS )。 其他提供商可能会很快赶上( 运行micro-apps-as-a-service的基础基础设施,尤其是复杂的) !

    idle idle idle idle idle capacity capacity capacity capacity capacity capacity capacity capacity capacity capacity vendor vendor vendor vendor vendor vendor vendor vendor。

    图像上传&大小示例
    • 图像从浏览器/移动应用程序上载到Lambda函数
    • Lambda做图像rezie和压缩
    • Lambda将原始图像( 900kb ) 和( 100kb ) 大小的发布到 S3

    总时间:120ms ( 向上舍入到 200毫秒)

    计算
    • 2 POST请求( 一个用于原始图像,用于压缩图像) = $0.005/1000x2 = $0.00001
    • Lambda请求 $0.0000002
    • Lambda执行成本 $0.00001667 *2 = $0.00003334

    因此,每个请求或者收费的$43.54 可以上传一个Milion映像的收费。
    英镑,这是:的Lambda component component$33.54

    考虑到 node.js的效率,你可能在相同的预算下运行单个的小型/中型EC2实例;对于用户来说,你不需要支付的空闲时间,而你的用户正在睡眠。 !

    英镑注释:如果使用Heroku或者EC2实例处理 upload/resize/compresion 任务,那么S3存储成本仍然是一样的。

    1,000,000图像x ( 900,000 + 100,000 ) = 100字节或者 100
    因此,100 x $0.030 = 每月 $30 以存储一百万张图像 !

    S3定价
    • 获取 get: 每个请求的$0.004
    • 将,COPY, POST或者列表请求放置在: 每 1,000个请求有 $0.005
    • 每小时英镑 $0.0300 stored stored stored

    价格

    你将对所有函数中的请求总数进行收费。 对于响应事件通知或者调用调用( 包括从控制台调用测试),每次开始执行时,Lambda计数一个请求。

    • 每月首次 1万请求
    • 此后 $0.20 每 1万请求( 每个请求的$0.0000002 )
    • 执行时间向上舍入到最接近的100毫秒
    • 你每秒使用 $0.00001667秒

    见:http://aws.amazon.com/lambda/pricing/ for 价格示例。

    常见问题解答

    如何将现有 NPM MODULE 添加到Lambda函数?

    你可能希望以 NPM MODULE的形式向Lambda函数添加一些附加功能。 这是你需要采取的四个简单步骤 !

    • 首先让我们创建一个包含我们的Lambda函数及其所有模块的新目录
    
    $ mkdir lambdaNPM
    
    
    $ cd lambdaNPM
    
    
    
    
    • 安装你所选择的NPM软件包。 我们将使用 aws-sdk 作为示例
    
    $ npm install --prefix=~/lambdaNPM aws-sdk
    
    
    aws-sdk@2.0.27 node_modules/aws-sdk
    
    
    ├── xmlbuilder@0.4.2
    
    
    └── xml2js@0.2.6 (sax@0.4.2)
    
    
    $ ls node_modules
    
    
    aws-sdk
    
    
    
    
    • 测试 MODULE 是否已经安装
    
    $ echo 'var AWS = require("aws-sdk");console.log(AWS.EC2.apiVersions)'> test.js
    
    
    $ node test.js
    
    
    [ '2013-06-15*','2013-10-15*','2014-02-01*','2014-05-01*','2014-06-15*','2014-09-01*','2014-10-01' ]
    
    
    
    

    这里我们只需要 sdk,然后将代码导入到 test.js 中。 然后我们运行 test.js,我们应该能够看到在控制台中打印的EC2版本。 这只是为了证明 MODULE 已经安装了一个简单的测试。

    • 创建函数

    至此,我们已经成功创建了包含一个或者多个npm安装包的目录,并通过在本地运行测试脚本来验证包可以加载和执行。 现在可以对测试脚本进行操作,并通过创建一个利用你刚刚安装的模块并以相同方式测试它的真正的Lambda函数继续。 要将结果函数和模块部署到 Lambda,只需压缩整个lambdaTestFunction目录并使用 createFunction。或者控制台UI的来部署它。

    感谢 AWS计算机的博客文章。


    WEB  服务  learn  services  INF  Scala  
    相关文章