AWS 上的项目

构建现代 Web 应用程序

部署 Web 应用程序、连接到数据库和分析用户行为

模块 5:捕获用户行为

在本模块中,您将使用 AWS Lambda 和其他无服务器服务捕获用户行为。

概览

现在,您的 Mythical Mysfits 站点已经启动并开始运行,让我们来创造一种方法,更好地了解用户如何与网站及其虚幻生物 (mysfit) 进行交互。当用户在网站上收养 mysfit 或为 mysfit 点赞时,这些操作会导致我们的后端数据会发生变化,分析这一流程将变得非常简单。

但是,理解用户在决定为某个 mysfit 点赞或收养 mysfit 之前在网站上的操作,可以帮助您在今后完成更好的用户体验设计,进而使 mysfit 更快地被收养。为了收集这些信息,我们将为网站前端添加提交微小请求的功能,这样用户每单击一次 mysfit 资料,系统就会向我们创建的新微服务 API 提交一次请求。这些记录将由一个无服务器代码函数进行实时处理、汇总和存储,以便您在以后随时分析。

现代应用程序设计原则更倾向于专注细节、明确分离和模块化的服务。所以,相较于在现有的 Mysfit 服务中添加到目前为止一直在使用的其他方法和功能,我们将创建一种新型的解耦服务,用于接收 Mysfit 网站的用户点击事件。该全栈已使用所提供的 CloudFormation 模板显示。

架构图

捕获用户行为

为什么选择 AWS Lambda 执行该操作?

Lambda 非常适合需要实时响应数据更改、系统状态变化或用户操作的数据驱动型应用程序。这类应用程序通常与数据存储连接来获取并分析数据,以便进行批处理、流分析和机器学习推理。Lambda 已与 Kinesis Data Streams 和 Kinesis Data Firehose、S3、CloudWatch Events、CloudWatch Logs和 DynamoDB 等数据存储集成,目前共计 17 个事件源,因此其很适合此类应用。   

此模块中使用的无服务器资源

AWS Kinesis Firehose 传输流:Kinesis Firehose 是一种高度可用且高度托管的实时流式处理服务,可接收数据记录,并自动将数据加载至 AWS 中的多个潜在存储目的地,例如 Amazon S3 存储桶或 Amazon Redshift 数据仓库集群。Kinesis Firehose 还可以让传输流接收的所有记录自动传输至使用 AWS Lambda 创建的一个无服务器函数中。这就意味着您写出的代码在被汇总和存储在已配置的目的地之前,可以对记录进行任何其他的处理或转换。

Amazon S3 存储桶:S3 中将创建一个新的存储桶,以便所有处理完毕的点击事件记录以对象的形式汇总并存储在文件中。

AWS Lambda 函数:AWS Lambda 可以让开发人员只需编写包含逻辑要求的代码函数,并可部署、调用代码,确保代码的可靠性高、延展性强,而无需管理其他基础架构。这里,我们使用 AWS SAM 定义一个无服务器代码函数。这个代码函数将被部署至 AWS Lambda,使用 Python 编写,然后处理和扩充经由传输流接收到的点击记录。我们编写的代码非常简单,扩充操作可在网站前端完成,无需任何后续处理。此函数可检索 Mysfit 中点击记录的其他属性,让点击记录更有意义(这里指通过网站前端检索到的数据)。但对于本次研讨会的目的来说,此代码旨在演示在记录存储之前,包含一个无服务器代码函数来实时执行所需的任何额外处理或转换的架构的可能性。Lambda 函数创建完成,且 Kinesis Firehose 传输流配置为函数的一个事件源后,传输流会自动将点击记录当做事件传输至创建的代码函数中,接收代码返回的响应,并将更新的记录传输至配置好的 Amazon S3 存储桶。

Amazon API Gateway REST API:同其他 AWS 服务一样,AWS Kinesis Firehose 提供一个服务 API,在本例中,我们就可以使用其中的 PutRecord 操作将用户点击事件记录放入传输流中。但是,我们不想让网站前端直接同 Kinesis Firehose PutRecord API 集成。这就需要我们在前端代码中管理 AWS 凭证,从而授权面向 PutRecord API 的那些 API 请求,这会向用户公开所依赖的直接 AWS API(这可能会鼓励恶意网站访问者尝试将格式不正确或影响我们理解真实客户行为的目标的记录添加至传输流)。所以,我们将使用 Amazon API Gateway 为 Kinesis Firehose 的 PutRecord API 创建一个 AWS 服务代理。这样我们就可以构建自己的公共 RESTful 终端节点,这种终端节点无需在前端管理 AWS 凭证即可处理请求。此外,我们也将使用 API Gateway 中的请求映射模板,该模板可让我们定义自己的请求负载结构,限制对于我们预期结构的请求,并可将那些格式正确的请求转换成 Kinesis Firehose PutRecord API 要求的结构。

IAM 角色:Kinesis Firehose 需要一种服务角色帮助其将接收到的记录以事件的形式传输至创建完成的 Lambda 函数,并将处理完毕的记录传输至目标 S3 存储桶。Amazon API Gateway API 也需要一种新角色,该角色接收到每个 API 请求时,都可允许 API 在 Kinesis Firehose 中调动 PutRecord API。

实施说明

  • A:创建新的 CodeCommit 存储库

    您使用 CloudFormation 部署的这个新堆栈不仅会包含基础设施环境资源,还将包含 AWS Lambda 用于处理数据流事件的应用程序代码本身。要在一个部署中将基础设施和代码创建捆绑在一起,我们要使用 AWS Cloud9 IDE 中预安装的另一个 AWS 工具 – AWS SAM CLI。AWS Lambda 函数代码以 .zip 包上传到 Amazon S3 存储桶的方式传输到服务中。

    SAM CLI 将自动执行该操作。我们可以此创建一个 CloudFormation 模板,该模板可本地引用存储了所有 Lambda 函数代码的文件系统。随后,SAM CLI 将其打包成 .zip 文件,上传至已配置的 Amazon S3 存储桶,并创建一个新的 CloudFormation 模板,该模板可指示创建完成并上传到 AWS Lambda,用以部署的 .zip 文件在 S3 的位置。然后我们可以将 SAM CLI 生成的 CloudFormation 模板部署到 AWS,并观察与使用 SAM CLI 上传的代码包的 Lambda 函数同步生成的环境。

    首先,我们来创建一个新的 CodeCommit 储存库以容纳流式服务代码:

    aws codecommit create-repository --repository-name MythicalMysfitsStreamingService-Repository

    响应此命令时,请复制“cloneUrlHttp”的值。正确格式如下:https://git-codecommit.REPLACE_ME_REGION.amazonaws.com/v1/repos/MythicalMysfitsStreamingService-Repository

    下一步,让我们将全新的空白储存库克隆到 IDE:

    cd ~/environment/
    git clone {insert the copied cloneValueUrl from above}
    B:复制流式处理服务代码库

    现在,我们移动工作目录到这个新的储存库:

    cd ~/environment/MythicalMysfitsStreamingService-Repository/

    然后,将模块-5 应用程序组件复制到这个新的储存库目录中:

    cp -r ~/environment/aws-modern-application-workshop/module-5/app/streaming/* .

    我们将 CloudFormation 模板也复制到这个模块中。

    cp ~/environment/aws-modern-application-workshop/module-5/cfn/* .
  • A:使用 Pip 安装 Lambda 函数依赖项

    现在,储存库目录所需的所有构件已设置完毕:

    一个用于创建全栈的 CFN 模板。

    一个包含 Lambda 函数代码的 Python 脚本:streamProcessor.py

    将 CloudFormation 模板同其应用程序代码存储在一个存储库中,是 AWS 客户的一种常见操作。因为这样可以在一个位置看到应用程序的所有变化,并可同时跟踪环境。

    但是,如果您看 streamProcessor.py 文件中的代码,您将会发现代码使用的是请求 Python 程序包来向您之前创建的 Mythical Mysfits 服务发送 API 请求。外部库不会自动纳入 AWS Lambda 运行时环境中,因为不同的 AWS 客户可能采用各种库的不同版本,等等原因。

    您需要在库依赖项上传至 Lambda 服务前,将其同 Lambda 代码函数打包在一起。我们将使用 Python 程序包管理器 pip 完成这项操作。在 Cloud9 终端中,运行以下命令来安装请求程序包,以及与函数代码同步生成的本地依赖项:

    pip install requests -t .

    命令执行完成后,您将看到有几个额外的 python 程序包文件夹储存在您的存储库目录中。

    B:更新 Lambda 函数代码

    下一步,在 Lambda 函数代码准备完全部署之前,我们需要更换一个代码。在 streamProcessor.py 文件中,有一行需要用您的 Mysfits 服务 API 中的 ApiEndpoint 替换,该服务与您在模块-4 中创建,并在网站前端使用的是相同的服务 ApiEndpoint。

    replace-api-endpoint

    此服务用于在 DynamoDB 中与 MysfitsTable 的集成,因此,虽然我们可以写出一个可以同 DynamoDB 直接集成的 Lambda 函数,但这么做会干扰第一个微服务的目的,造成多个/单独的代码库与同一个表格集成的情况。相反,我们将通过现有服务同该表格集成,完成一个更加分离和模块化的应用程序架构。

    C:将代码推送至 CodeCommit

    在新的存储库中提交代码更换,这样代码可以保存在 CodeCommit 中:

    git add .
    git commit -m "New stream processing service."
    git push
  • A:为 Lambda 函数代码程序包创建一个 S3 存储桶

    Python 文件中的那一行内容更换完成,且代码提交后,我们就可以使用 AWS SAM CLI 打包所函数代码并上传至 S3,然后创建可部署的 CloudFormation 模板用以创建流式堆栈。

    首先,使用 AWS CLI 创建一个新的 S3 存储桶用来接收 Lambda 函数代码程序包。S3 存储桶的名字在所有的 AWS 客户中必须是全局唯一的,所以请将存储桶名字的末尾替换成您专属的字符串:

    B:使用 SAM CLI 为 Lambda 打包代码

    存储桶创建完毕后,我们就可以使用 SAM CLI 打包上传代码,并转换 CloudFormation 模板,请确保您将命令的最后一个参数替换为前述刚刚创建的存储桶名字(此命令也假定您的终端仍在存储库工作目录中):

    sam package --template-file ./real-time-streaming.yml --output-template-file ./transformed-streaming.yml --s3-bucket replace-with-your-bucket-name

    如果操作成功,您将在./MythicalMysfitsStreamingService-Repository/ 目录中看到新创建的 transformed-streaming.yml 文件,如果您查看了其中内容,则会看到无服务器 Lambda 函数的 CodeUri 参数已经更新为 SAM CLI 上传打包代码的对象定位。

    C:使用 AWS CloudFormation 部署堆栈

    同样,SAM CLI 命令返回的 CloudFormation 命令也需要执行,并创建新的全栈。但因为是由堆栈创建 IAM 资源,所有你需要增加一个额外参数以执行命令。执行以下命令以部署流式堆栈:

    aws cloudformation deploy --template-file /home/ec2-user/environment/MythicalMysfitsStreamingService-Repository/cfn/transformed-streaming.yml --stack-name MythicalMysfitsStreamingStack --capabilities CAPABILITY_IAM

    这个堆栈创建完成后,完整的实时处理微服务也就创建成功了。

    在今后的各种情况中,如果仅对 Lambda 函数进行了代码更换,而 CloudFormation 堆栈的其余部分保持不变,您可以重复上述相同的 AWS SAM CLI 和 CloudFormation 命令。这样基础设施环境将保持不变,但您的 Lambda 函数会产生一个代码部署。

  • A:更新网站内容

    随着流式堆栈的启动并开始运行,我们现在需要发布一个包含 JavaScript 的新版本 Mythical Mysfits 前端,这个 JavaScript 会在用户单击一个 mysfit 资料时,将该事件发送至我们的服务。

    新的 index.html 文件位于:~/environment/aws-modern-application-workshop/module-5/web/index.html

    这个文件包含与模块-4 相同且需要更新的占位符,以及您刚刚创建的新流式处理服务终端节点的一个额外占位符。有关之前的变量值,您可参考模块-4 中更新前一个 index.html 文件。

    为新的流式堆栈执行以下命令,为流式处理服务检索检索新的 API Gateway 终端节点:

    aws cloudformation describe-stacks --stack-name MythicalMysfitsStreamingStack
    B:推送新站点版本至 S3

    index.html 中的最终值替换为 streamingApiEndpoint,您就可以发布最终版本的 Mythical Mysfits 主页更新了:

    aws s3 cp ~/environment/aws-modern-application-workshop/module-5/web/index.html s3://YOUR-S3-BUCKET/

    在浏览器中再次刷新您的 Mythical Mysfits 网站,现在,每当有用户单击一个 mysfits 资料时,您的站点就会记录并发布信息!

    如需查看已处理的记录,他们可前往作为 MythicalMysfitsStreamingStack 的一部分创建的目标 S3 存储桶。

    既然您已经拥有了一个完整的现代应用程序架构,我们鼓励您现在探索 AWS 控制台和您已创建的所有不同服务来启动 Mythical Mysfits!

  • 请务必清除在此研讨会中创建的所有资源,确保对资源的计费不会超过您预期的时间。我们建议您使用 AWS 控制台探索您创建的资源,并在准备就绪时将其删除

    针对使用 AWS CloudFormation 预置资源的两个案例,您仅需通过在每个堆栈中运行下列 CLI 命令,即可删除这些资源:

    aws cloudformation delete-stack --stack-name STACK-NAME-HERE

    要删除所有创建的资源,您可访问以下 AWS 控制台,其中包含您在 Mythical Mysfits 研讨会中创建的资源:

结论

本次体验旨在让您了解开发人员是如何使用 AWS 进行设计工作,以及构建现代应用程序架构。AWS 上的开发人员能够使用 AWS CLI 以编程方式预置资源、通过 AWS CloudFormation 重新使用基础设施定义、使用 Code 服务中的 AWS 开发人员工具套件自动构建和部署代码更换、并可使用多种不同的计算和应用程序服务功能而完全不需要预置或管理任何服务器!

下一步,如需了解更多关于您创建的 Mysical Mysfits 网站的内部工作原理,请深入了解我们提供的 CloudFormation 模板及其中公布的资源。

希望您喜欢本次 AWS 现代应用程序研讨会! 本次教程也托管在 GitHub,如有任何建议,您可提交问题。如果您想同其他人合作改进代码,您也可以在 GitHub 上发送拉取请求。

如需了解更多有关 Developing on AWS 详情,请访问 AWS 开发人员中心。

恭喜!

您已经在 AWS 上构建了一个现代 Web 应用程序。
与您的朋友分享成果,或向我们发送反馈。

Twilight Glitter 很喜欢您的成果