AWS-云项目-全-
AWS 云项目(全)
原文:
annas-archive.org/md5/45e4c1dd094b1fc87c70427ee3df9f4d译者:飞龙
第一章:前言
本书的读者群体
本书涵盖内容
为了充分利用本书内容
下载示例代码文件
使用的约定
<st c="6918">文本中的代码</st><st c="7163">translation.json</st>
def lambda_handler(event, context):
…
response = bot.recognize_text(
botId = '${MeetyBot}',
botAliasId='TSTALIASID',
localeId='en_US',
sessionId='your_session_id',
text = user_input
)
…
$ npm install && npm run build
联系我们
分享你的想法
下载本书的免费 PDF 副本
扫描二维码或访问下面的 链接

-
提交你的购买证明 凭证 -
就是这样! 我们会直接将免费的 PDF 和其他福利发送到你的 邮箱
第一部分:初学者级别的项目
-
第一章 , 部署和与 AWS 服务进行交互 -
第二章 , 创建个人网站
第二章:1
部署和与 AWS 服务交互
-
架构设计 在 AWS 上 -
开始使用 AWS 控制台 -
导航 AWS CLI 和 SDK -
理解 IaC
技术要求
在 AWS 上架构设计
-
需求收集 :这是在 AWS 上架构解决方案过程中的一个关键步骤。 它涉及了解业务需求、功能需求、非功能需求以及将在设计和实现 AWS 架构时起到决定性作用的约束条件。 AWS 架构的设计。 -
架构模式 :AWS 提供了多种架构模式和参考架构,作为常见用例(如 Web 应用、数据处理管道或无服务器架构)的起点。 你可以利用这些模式并根据特定需求对其进行定制。 -
服务选择 :AWS 提供了广泛的服务,包括计算、存储、数据库、网络、分析、机器学习等。 你必须仔细评估应用程序的需求,并选择最适合这些需求的 AWS 服务。 -
绘图 :创建拟议架构的可视化表示是架构过程中的一个关键步骤。 AWS 没有官方工具,但 draw.io 或者仅仅使用 Microsoft PowerPoint 都可以用来创建架构图,这有助于沟通设计、促进协作 并推动实施。 。
需求收集
-
业务需求 :第一步是理解解决方案背后的业务目标、目标和驱动因素。 这包括目标市场、预期增长、收入模型以及需要考虑的任何特定业务约束或法规。 -
功能要求 :这些要求定义了解决方案必须提供的具体功能、特性和能力。 这可能包括与用户界面、数据处理、与现有系统的集成或特定 业务逻辑相关的要求。 -
非功能性要求 :非功能性要求定义了解决方案必须具备的定性特征,如性能、可扩展性、可用性、安全性和合规性。 这些要求通常在确定适当的 AWS 服务和架构模式时至关重要, 以便使用。 -
技术要求 :技术要求涵盖了需要使用或与 AWS 解决方案集成的具体技术、编程语言、框架和工具。 这可能包括对特定数据库、消息系统或 第三方服务的要求。 -
数据要求 :在 AWS 架构设计中,理解数据要求至关重要。 这包括数据类型(结构化、非结构化或半结构化)、数据量、数据源、数据处理需求,以及任何特定的数据治理或 合规性要求。 -
集成要求 :如果 AWS 解决方案需要与现有的本地系统、第三方服务或其他云环境进行集成,则必须明确定义集成要求。 这包括识别集成点、数据格式、协议和 安全性考虑事项。 -
安全性和合规性要求 :根据行业和所处理数据的性质,可能会有需要在 AWS 架构中解决的特定安全性和合规性要求。 这些可能包括监管标准、数据保护法或 行业特定认证。 -
财务要求 :AWS 提供按需付费定价模式。 了解预算限制和成本要求对于选择合适的 AWS 服务和实现 具有成本效益的架构至关重要。
选择架构模式
选择服务
-
服务集成 :AWS 服务设计上能够无缝协作。 你应该考虑不同服务之间的集成点,并确保所选服务能够有效集成,从而提供 所需的功能。 -
托管服务与自托管服务 :AWS 提供托管服务(由 AWS 处理底层基础设施和维护)和自托管服务(客户有更多控制权,但也承担更多责任)。 您必须根据运营开销、成本以及合规要求等因素评估这两种服务类型之间的权衡。 -
定价与成本优化 :AWS 服务有不同的定价模型,您需要考虑其服务选择的成本影响。 应评估并将成本优化策略(例如利用预留实例、竞价实例或自动扩展)纳入架构设计中。 -
发展路线图 :AWS 服务在不断发展,新的功能和服务会定期发布。 您应考虑所选服务的未来路线图,并确保架构能够适应潜在的变化或新的服务提供。
架构图绘制

探索 AWS Well-Architected 框架
开始使用 AWS 控制台
使用控制台
-
访问 AWS 控制台的第一步是导航 到 https://console.aws.amazon.com/ 。 你将看到一个登录界面,如 图 1 **.2 所示。

-
如果你使用的是 根用户,请输入你的用户邮箱和密码。 如果你使用的是 IAM 用户,你还需要输入 12 位数字的 账户 ID。 -
成功登录后,你将看到 AWS 控制台主页,如 图 1 **.3 所示。

-
顶部的搜索栏,你可以用它来搜索特定的服务。
-
当前管理的 AWS 区域显示在右上角;在这种情况下是北弗吉尼亚。
-
当前登录的用户或角色,位于右上角,隐藏在红色框下。
-
最近访问的部分,如果你之前没有打开过 AWS 控制台,它将是空的。
重要说明
为什么角色和账户 ID 会隐藏在图 1.3中的红色框下?尽管 AWS 账户 ID、用户和角色不被认为是敏感信息,但按照 AWS 最佳实践,公开披露这些信息是不推荐的。
- 导航到 EC2 服务控制台。为此,在搜索栏中输入
ec2,然后选择EC2,如图 1.4所示。

图 1.4 – 使用 AWS 控制台搜索 EC2 服务
- 要启动最简单的虚拟机,且不进行任何自定义,请选择启动实例,如图 1.5所示。

图 1.5 – EC2 仪表板
-
在以下菜单中,选择启动一个实例,然后选择继续无密钥对(不推荐),从密钥对名称下拉菜单中选择。最后,再次选择启动实例,这次是在右侧菜单中。
-
导航到正在运行的实例。你可以通过选择 EC2 左侧菜单中的“实例”来完成,或者直接访问
console.aws.amazon.com/ec2/#Instances。你应该会看到类似于图 1.6的内容:一个正在运行的 EC2 实例,带有一个奇怪的实例 ID 和一些其他属性。

图 1.6 – EC2 实例状态
你可以通过选择 终止(删除)实例 来终止该实例,如 图 1 **.7 所示。

导航 AWS CLI 和 AWS SDK
AWS CLI
使用 AWS CLI
-
通过 控制台导航至 IAM( https://us-east-1.console.aws.amazon.com/iam/home?region=us-east-1#/users )。 -
选择 创建用户 ,并为其指定用户名。 -
在 设置权限 菜单中,选择 直接附加策略 ,然后找到并选择 PowerUserAccess 。最后, 点击 下一步 。 -
点击 创建用户 。
-
选择你新 创建的用户。 -
导航到 安全凭证 标签页,选择 创建 访问密钥 。 -
在 使用场景 菜单中,选择 命令行界面(CLI) ,接受确认消息,然后 选择 下一步 。 -
在下一个菜单中,点击 创建 访问密钥 。 -
在离开此页面之前,请记下你的访问和秘密 访问密钥。
-
创建一个 IAM 用户: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_users_create.html#id_users_create_console -
管理 IAM 用户的访问密钥: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html
$ export AWS_ACCESS_KEY_ID=XXXXXXXXX
$ export AWS_SECRET_ACCESS_KEY=xxxxxxxxxx
$ export AWS_DEFAULT_REGION=<st c="24521">us-east-1</st>. We recommend that you run all the following examples in this region. If you are using a different region, some parameters, such as the <st c="24667">Amazon Machine Image</st> (<st c="24689">AMI</st>), require modifications.
<st c="24718">Try the following command; it returns your running instances.</st> <st c="24781">If you don’t have any, it will</st> <st c="24812">be empty:</st>
$ aws ec2 describe-instances
<st c="24850">To create the simplest possible instance, run the following command.</st> <st c="24920">This command creates an EC2 of the smallest instance type,</st> `<st c="24979">t2.micro</st>`<st c="24987">, using that AMI ID, which effectively means Amazon Linux 2023\.</st> <st c="25051">There will be more on AMIs in</st> *<st c="25081">Chapter 3</st>*<st c="25090">:</st>
$ aws ec2 run-instances --image-id ami-0c101f26f147fa7fd
--instance-type t2.micro
<st c="25174">Your command output should be similar to the following.</st> <st c="25231">Bear in mind that part of the output was</st> <st c="25272">omitted, but check whether your</st> `<st c="25304">ImageId</st>` <st c="25311">and</st> `<st c="25316">InstanceType</st>` <st c="25328">match:</st>
{
"Groups": [],
"Instances": [
{
"AmiLaunchIndex": 0, <st c="25390">"ImageId": "ami-0c101f26f147fa7fd",</st> "InstanceId": "i-0a65cf3ecaec728a8", <st c="25463">"InstanceType": "t2.micro",</st> "LaunchTime": "2024-03-24T10:47:25+00:00",
"Monitoring": {
"State": "disabled"
},
"Placement": {
"AvailabilityZone": "us-east-1a",
"GroupName": "",
"Tenancy": "default"
},
"PrivateDnsName": "ip-172-31-38-84.ec2.internal",
###OUTPUT OMMITED###
<st c="25733">If you run the previous</st> `<st c="25758">describe</st>` <st c="25766">command again, this time, the output will show your running instance.</st> <st c="25837">Try it with the following filter, which only shows</st> `<st c="25888">t2.micro</st>`<st c="25896">-sized instances:</st>
$ aws ec2 describe-instances
[
"i-0a65cf3ecaec728a8"
]
<st c="26065">To terminate the instance, run the following command.</st> <st c="26120">Replace the instance ID with</st> <st c="26149">your own:</st>
$ aws ec2 terminate-instances
<st c="26310">探索 AWS CLI</st>
<st c="26332">进一步探索</st> <st c="26345">AWS CLI。</st> <st c="26374">每个服务的语法都是一样的:</st> <st c="26401">每个服务:</st>
$ aws <command> <subcommand> [options and parameters]
<st c="26469">以下是这些</st> <st c="26496">命令的含义:</st>
+ <st c="26510">对</st> `<st c="26532">aws</st>` <st c="26535">程序的基础调用。</st>
+ <st c="26544">顶级</st> `<st c="26559">命令</st>` <st c="26566">通常对应于由</st> <st c="26624">AWS CLI 支持的 AWS 服务。</st>
+ <st c="26632">该</st> `<st c="26637">子命令</st>` <st c="26647">指定要执行的操作。</st>
<st c="26685">重要提示</st>
<st c="26700">你创建了一个具有</st> `<st c="26730">PowerUserAccess</st>` <st c="26745">权限的 IAM 用户。</st> <st c="26759">这授予对 AWS 服务和资源的完全访问权限,但不允许管理用户或组。</st> <st c="26868">在生产环境中,你可以将用户访问权限范围缩小到更窄的一组</st> <st c="26947">权限。</st>
<st c="26962">AWS CLI 的一个方便功能是</st> `<st c="26997">帮助</st>` <st c="27001">功能。</st> <st c="27011">你可以使用它获得任何命令的帮助。</st> <st c="27057">为此,只需在命令名称的末尾键入</st> `<st c="27079">help</st>` <st c="27083">。</st> <st c="27114">执行以下命令。</st> <st c="27146">结果将是对这些命令所有可用选项的详细描述:</st>
$ aws ec2 help
$ aws ec2 describe-instances help
<st c="27285">如果逐命令浏览不是你的方式,你也可以在 AWS CLI 命令参考中找到每个</st> <st c="27384">服务的具体语法(</st>[<st c="27423">https://docs.aws.amazon.com/cli/latest/</st>](https://docs.aws.amazon.com/cli/latest/)<st c="27463">),但你将在</st> <st c="27510">接下来的章节中看到并使用更多。</st>
<st c="27529">AWS SDK</st>
<st c="27537">AWS SDK 是一个</st> <st c="27556">开源库的集合,提供来自多种编程语言的程序化访问 AWS 服务,包括 Java、Python、Node.js、.NET、Ruby、Go、PHP 等。</st> <st c="27743">这些 SDK 使开发者能够构建与 AWS 资源和服务直接交互的应用程序,而无需使用低级的 AWS</st> <st c="27884">服务 API。</st>
<st c="27897">AWS SDK 抽象了向 AWS 服务发出认证 HTTP/HTTPS 请求的复杂性,处理重试和错误处理,并解析来自 AWS 服务的响应。</st> <st c="28085">它们提供了一个更高级的、特定语言的接口,使开发者更容易将 AWS 服务集成到</st> <st c="28209">他们的应用程序中。</st>
<st c="28228">这些被认为是高级概念,你在本书中不会看到太多。</st> <st c="28312">它更常被应用开发人员使用。</st> <st c="28361">如果你有兴趣了解使用 Python SDK 创建 EC2 实例的语法,可以在</st> *<st c="28488">学习基础</st>* <st c="28504">部分找到</st> <st c="28513">,链接地址为</st> [<st c="28516">https://docs.aws.amazon.com/code-library/latest/ug/python_3_ec2_code_examples.html</st>](https://docs.aws.amazon.com/code-library/latest/ug/python_3_ec2_code_examples.html)<st c="28598">。</st>
<st c="28599">从使用控制台的手动操作到半自动化的操作,如 AWS CLI,你尚未</st> <st c="28697">见识到自动化的全部潜力。</st> <st c="28741">在接下来的章节中,你将学习如何通过 IaC</st> <st c="28807">来扩展你的部署。</st>
<st c="28816">理解 IaC</st>
<st c="28834">IaC(基础设施即代码)是一种方法</st> <st c="28854">用于配置和管理如云基础设施等资源。</st> <st c="28918">它允许你使用人类可读的定义文件</st> <st c="29006">或代码来定义和部署你的资源。</st>
<st c="29014">与之前章节中手动通过 AWS 控制台或 CLI 工具配置资源不同,IaC 允许声明性地指定所需的基础设施状态。</st> <st c="29203">在我们的上下文中,这指的是 AWS 云。</st> <st c="29241">这意味着计算实例、存储、网络、安全组以及其他</st> <st c="29319">AWS 服务。</st>
<st c="29332">通过运用 IaC,你将获得</st> <st c="29368">多个好处:</st>
+ **<st c="29386">配置一致性</st>**<st c="29412">:IaC</st> <st c="29419">推动了不可变基础设施的概念,即将基础设施组件视为一次性和可替换的,而不是手动修改。</st> <st c="29582">这种方法确保了一致性,减少了配置漂移,并简化了扩展或</st> <st c="29687">更新基础设施的过程。</st>
+ **<st c="29711">版本控制和协作</st>**<st c="29745">:IaC 模板和代码可以存储在 Git 等版本控制系统中,支持协作、代码审查和跟踪基础设施定义的变化。</st> <st c="29922">这促进了基础设施管理的最佳实践,并便于团队间的知识共享。</st> <st c="30014">。
+ **<st c="30026">自动化部署</st>**<st c="30048">:IaC 模板和代码可以与</st> **<st c="30097">持续集成和持续部署</st>** <st c="30145">(</st>**<st c="30147">CI/CD</st>**<st c="30152">) 流水线集成,从而实现</st> <st c="30175">自动化部署和更新。</st> <st c="30210">这减少了手动工作,最小化了人为错误,并确保在不同环境(例如开发、预生产、</st> <st c="30371">和生产)之间的一致性和可重复部署。</st>
+ **<st c="30387">基础设施测试和验证</st>**<st c="30425">:IaC 模板和代码可以在部署之前进行测试和验证,确保定义的基础设施符合期望的规格,并遵守组织的政策和</st> <st c="30615">最佳实践。</st>
+ **<st c="30630">成本优化和资源管理</st>**<st c="30672">:通过将基础设施视为代码,组织可以更轻松地跟踪和管理其 AWS 资源,从而实现更好的成本优化和资源利用策略。</st> <st c="30850">你将不再忘记</st> <st c="30876">某个虚拟机</st> <st c="30901">正在某个地方运行。</st>
<st c="30919">有多种 IaC 工具。</st> <st c="30950">AWS 提供了自己的原生 IaC 工具,例如 AWS CloudFormation,允许用户使用 JSON 或 YAML 模板定义基础设施资源。</st> <st c="31106">它还提供了</st> <st c="31127">AWS</st> **<st c="31131">云开发工具包</st>** <st c="31152">(</st>**<st c="31154">CDK</st>**<st c="31157">)。</st> <st c="31161">这与 AWS SDK 不同,后者提供了一个比 CloudFormation 更高层次的抽象,允许开发人员使用熟悉的编程语言(如 TypeScript、Python、Java、</st> <st c="31379">和 C#)定义 AWS 构件。</st>
<st c="31386">除了 AWS 原生工具外,还有许多第三方 IaC 解决方案,例如</st> **<st c="31471">Terraform</st>**<st c="31480">。Terraform</st> <st c="31491">是云中立的;它支持多种云服务提供商,包括 AWS,并提供一致的工作流程,以便在多个平台上管理基础设施。</st> <st c="31661">它是最著名的</st> <st c="31694">IaC 工具之一。</st>
<st c="31704">选择 IaC 工具</st> <st c="31726">归结为个人偏好、现有技能和每个工具可以提供的特定功能。</st> <st c="31821">在本书中,你将通过实践操作 CloudFormation 和 Terraform。</st> <st c="31903">然而,如果你对这个话题感兴趣,AWS 提供了关于如何选择 IaC 工具的指导</st> <st c="32011">,可以参考</st> [<st c="32014">https://docs.aws.amazon.com/prescriptive-guidance/latest/choose-iac-tool/introduction.html</st>](https://docs.aws.amazon.com/prescriptive-guidance/latest/choose-iac-tool/introduction.html)<st c="32104">。</st>
<st c="32105">使用 CloudFormation</st>
在这一部分,你<st c="32147">将使用 CloudFormation 创建一个 EC2 实例。</st> <st c="32198">这是一个入门部分,不会深入探讨所有 CloudFormation 的语法</st> <st c="32281">和功能。</st>
要开始,按照以下步骤操作:</st>
1. 在你的本地环境中创建以下文件;这是一个 YAML 模板,用于创建一个指定 AMI 和 `<st c="32458">t2.micro</st>` <st c="32466">大小的 EC2 实例:</st>
```
Resources:
NewEC2Instance:
Type: AWS::EC2::Instance
Properties:
ImageId: "ami-0c101f26f147fa7fd"
InstanceType: "t2.micro"
```
注意 CloudFormation 在 YAML 格式中的可读性。</st> <st c="32655">这是它的一个优点。</st>
1. 通过 AWS 控制台导航到 CloudFormation,访问 [<st c="32738">https://us-east-1.console.aws.amazon.com/cloudformation</st>](https://us-east-1.console.aws.amazon.com/cloudformation) <st c="32793">并选择</st> **<st c="32805">创建堆栈</st>**<st c="32817">。</st>
1. 选择 `<st c="32884">ec2.yml</st>`<st c="32891">,然后</st> <st c="32897">选择</st> **<st c="32904">下一步</st>**<st c="32908">。</st>
1. 给<st c="32915">堆栈</st>起个名字。
1. 跳过所有选项并部署<st c="32973">堆栈。</st>
部署过程结束时,你的堆栈状态应该显示 `<st c="33152">us-east-1</st>` <st c="33161">区域。</st>
你可以通过导航到 EC2 服务来验证刚刚创建的 EC2 实例。<st c="33244">确认它具有正确的大小</st> <st c="33281">和 AMI。</st>
<st c="33289">如果你不完全理解整个过程,不用担心。</st> <st c="33351">CloudFormation 是一个独立的世界,具有特定的语法和功能。</st> <st c="33423">浏览你的堆栈详情,你将能够找到许多特性,例如它是什么时候创建的,谁创建的,创建了哪些资源以及顺序,甚至更多高级概念,如参数</st> <st c="33665">和输出。</st>
若要了解更多关于 CloudFormation 的信息,可以查看官方的 AWS</st> <st c="33739">文档:</st> [<st c="33754">https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/Welcome.html</st>](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/Welcome.html)<st c="33829">。</st>
在继续之前,为了避免额外费用,不要忘记删除你的 EC2\。<st c="33922">要删除所有</st> <st c="33936">堆栈资源,请选择</st> <st c="33962">你的堆栈并</st> <st c="33977">点击</st> **<st c="33983">删除</st>**<st c="33989">。</st>
使用 Terraform
<st c="34006">你现在将创建</st> <st c="34027">另一个 EC2 实例,这次使用 Terraform。</st> <st c="34054">本节假设你已经按照上一节的</st> *<st c="34199">AWS</st>* *<st c="34203">CLI</st>* <st c="34206">部分配置好了终端和 AWS 凭证。</st>
<st c="34215">以下是如何</st> <st c="34230">操作:</st>
1. <st c="34236">在本地工作站的任意目录中创建一个文件,并命名为</st> `<st c="34308">ec2.tf</st>`<st c="34314">。</st>
1. <st c="34315">使用以下代码填充文件,它将创建一个最小实例类型的 EC2,</st> `<st c="34403">t2.micro</st>`<st c="34411">,位于</st> `<st c="34416">us-east-1</st>`<st c="34425">区域,使用相应的 AMI ID。</st> <st c="34445">这实际上意味着使用 Amazon</st> <st c="34481">Linux 2023:</st>
```
provider "aws"{
region = "us-east-1"
}
resource "aws_instance" "ec2" {
ami = "ami-0c101f26f147fa7fd"
instance_type = "t2.micro"
}
```
<st c="34622">请注意,</st> **<st c="34639">HashiCorp 配置语言</st>** <st c="34671">(</st>**<st c="34673">HCL</st>**<st c="34676">) 代码仍然是人类可读的,尽管</st> <st c="34716">可能比</st> <st c="34747">CloudFormation YAML</st> <st c="34747">稍微难以理解一些。</st>
<st c="34767">重要说明</st>
<st c="34782">AMI ID 在每个区域都是不同的。</st> <st c="34821">如果你使用的是与</st> `<st c="34862">us-east-1</st>`<st c="34871">不同的区域,并且你想使用 Amazon Linux 2023,你需要找到相应的</st> <st c="34952">AMI ID。</st>
1. <st c="34959">要执行 Terraform 代码,你需要先安装它。</st> <st c="35018">安装过程不在本书的范围内。</st> <st c="35069">不同操作系统的安装步骤不同,但它是一个简单的过程,你可以在 HashiCorp 的</st> <st c="35196">官方网站找到详细文档(</st>[<st c="35205">https://developer.hashicorp.com/terraform/tutorials/aws-get-started/install-cli</st>](https://developer.hashicorp.com/terraform/tutorials/aws-get-started/install-cli)<st c="35285">)。</st>
1. <st c="35288">安装完成后,在你创建了</st> `<st c="35393">ec2.tf</st>` <st c="35399">文件的同一目录下执行以下命令。</st> <st c="35406">它们将在你的环境中启动 Terraform</st> <st c="35450">并将你之前创建的模板应用到 AWS 账户中,从而有效地</st> <st c="35526">创建</st> <st c="35535">相关资源:</st>
```
$ terraform init
$ terraform apply
```
<st c="35584">系统将提示你进行确认。</st> <st c="35618">如果执行成功,它将显示如下</st> <st c="35683">简化输出:</st>
```
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# aws_instance.ec2 will be created
+ resource "aws_instance" "ec2" {
<st c="35964">+ ami = "ami-0c101f26f147fa7fd"</st>
<st c="35995">+ instance_type = "t2.micro</st>"
###OUTPUT OMMITED###
+ root_block_device {
+ delete_on_termination = (known after apply)
+ device_name = (known after apply)
+ encrypted = (known after apply)
+ iops = (known after apply)
+ kms_key_id = (known after apply)
+ tags = (known after apply)
+ tags_all = (known after apply)
+ throughput = (known after apply)
+ volume_id = (known after apply)
+ volume_size = (known after apply)
+ volume_type = (known after apply)
}
}
Plan: 1 to add, 0 to change, 0 to destroy. Do you want to perform these actions? Terraform will perform the actions described above. Only 'yes' will be accepted to approve.
<st c="36629">Enter a value: yes</st> aws_instance.ec2: Creating... aws_instance.ec2: Still creating... [10s elapsed]
aws_instance.ec2: Still creating... [20s elapsed]
aws_instance.ec2: Still creating... [30s elapsed]
aws_instance.ec2: Creation complete after 34s [id=i-0de732fda772c16cf] <st c="36899">Apply complete!</st> <st c="36915">Resources: 1 added, 0 changed, 0 destroyed.</st>
```
1. <st c="36958">你可以使用 AWS 控制台查看已创建的 EC2 实例。</st> <st c="37034">确保在正确的区域中查看。</st> <st c="37078">要删除所有资源,执行以下</st> <st c="37129">Terraform 命令:</st>
```
$ terraform destroy
```
<st c="37167">Terraform 提供了</st> <st c="37184">更多的功能,如</st> <st c="37217">使用</st> `<st c="37235">terraform plan</st>`<st c="37249">进行干运行,或者通过</st> `<st c="37303">terraform state list</st>`<st c="37323">可视化部署的资源。你可以在 Terraform 官方文档中了解更多这些内容</st> <st c="37395">,访问地址为</st> [<st c="37398">https://developer.hashicorp.com/terraform/cli/commands</st>](https://developer.hashicorp.com/terraform/cli/commands)<st c="37452">。</st>
<st c="37453">看看为什么 IaC 有用的实际示例。</st> <st c="37511">假设你需要创建 100 台这样的机器。</st> <st c="37565">你可以将之前的代码修改为</st> <st c="37602">以下内容:</st>
provider "aws"{
region = "us-east-1"
}
resource "aws_instance" "ec2" {
ami = "ami-0c101f26f147fa7fd"
instance_type = "t2.micro" <st c="37745">count = 100</st> }
<st c="37758">不要运行这个示例,因为它可能会产生高昂的费用。</st> <st c="37815">但是,注意与使用<st c="37858">AWS 控制台</st>执行相同任务相比,</st> <st c="37888">它是多么的简单。</st>
<st c="37900">总结</st>
在这一章中,你学习了在 AWS 上架构的含义。<st c="37908">它不仅仅是部署 AWS 服务,还包括收集不同类型的需求,将这些需求与已知模式和参考架构进行对比,选择不同的服务,并将<st c="37973">这些内容记录下来</st>。</st>
<st c="38191">你还探索了在设计完成后用于部署和交互 AWS 服务的各种方法和工具。</st> <st c="38326">AWS 控制台提供了一个用户友好的图形界面,而 AWS CLI 和 SDK 则提供了程序化访问和自动化功能。</st> <st c="38458">此外,你还接触了多种基础设施即代码(IaC)技术,如 Terraform、CloudFormation 和 AWS CDK,它们允许你通过代码定义和管理你的 AWS 基础设施。</st> <st c="38624">。</st>
<st c="38635">通过理解这些不同的方法,你可以根据自己的需求和技能水平以及 AWS 部署的复杂性,选择最合适的方法。</st> <st c="38819">无论你喜欢使用视觉界面、命令行工具、程序化访问还是 IaC,AWS 提供了一系列选项来满足你的需求并简化你的</st> <st c="38976">云操作。</st>
在下一章中,你将使用<st c="38993">AWS 控制台</st>构建个人网站。
第三章:2
创建个人网站
-
你将要构建的内容是——一个 个人网站 -
你将如何构建它——使用 S3 和 CloudFront -
实际构建它——使用 AWS 控制台 -
如何改进解决方案——安全性 和 DNS
技术要求
场景
需求
功能性需求
-
能够创建、编辑和更新简历的内容,包括个人信息、教育背景、工作经历、技能, 和项目 -
支持非文本内容,如 图片 -
在任何浏览器上都可以访问, 通过互联网 -
能够 基于 网站数据生成洞察
非功能性需求
-
低延迟 – 快速的页面 加载时间 -
高可用性 – 访问时可用 可用性 -
易于维护性 – 易于更新和修补 网站 -
低成本 – 便宜的 按需付费服务
架构模式
架构
-
不带 特定服务的图 -
带有 特定服务的图

AWS 服务
Amazon 简单存储服务(S3)
-
S3 是一种对象 存储服务,意味着它将数据存储为对象(文件),并将其存放在 桶(目录)中。 -
设计上具有高可用性,数据会在同一地区内的多个 AWS 可用区之间自动复制,确保即使发生停机或 组件故障,您的数据仍然可以访问。 -
完全托管的服务;您无需担心管理存储基础设施的操作开销,因为这一切都由 为您处理。 -
支持版本控制,可以在同一个存储桶中保存对象的多个变体,允许你保存、检索和恢复存储在 桶中的每个对象的每个版本。 -
高度具有成本效益的存储解决方案,采用按需计费定价和分级 存储类。
-
你希望存储文件(例如 HTML、CSS 和图像),并希望它们随时可供招聘人员访问。 S3 是 高度可用的。 -
你希望解决方案容易维护,无需进行操作系统补丁更新和其他繁琐的工作。 S3 是一项 完全托管的服务。 -
同样,你希望能够轻松更新你的简历,如果犯错,能够回滚到之前的版本。 S3 支持 文件版本控制。 -
最后,你需要以尽可能低的成本来实现这一点。 S3 提供免费层,只对实际使用量收费,且被认为是一个 具有成本效益的服务。
-
S3 是一项区域性服务,因此,网站可以通过该桶所在 AWS 区域的特定网站终端访问。 -
它不 支持 HTTPS。
<st c="9126">.html</st><st c="9133">.css</st><st c="9139">.js</st>
-
全球分布式 :通过在靠近用户的边缘位置缓存静态内容,CloudFront 可以更快速地提供网站文件,从而提高加载速度,带来更好的用户体验。 这一点对互联网连接较慢或位于距离源 S3 存储桶较远地区的用户尤为有益。 -
高可用且容错 :CloudFront 构建在 AWS 高可用且容错的基础设施之上。 边缘位置和基础服务都考虑了冗余和容错设计,最大限度地减少单个 组件故障的影响。 -
增强的弹性 :CloudFront 支持为单个分发配置多个源服务器(例如,Amazon S3 存储桶或 Web 服务器)。 如果主要源服务器不可用,CloudFront 会自动切换到次级或三级源服务器,确保内容持续 交付。 -
内容交付优化 :CloudFront 通过自动压缩文件、最小化数据传输量并支持高级缓存机制(如缓存控制头和查询 字符串转发),来优化静态内容的交付。 。
-
你需要一种通过互联网在任何设备上都能使用的分发机制。 你不知道用户会在哪里,或者他们可能使用什么类型的设备和带宽限制。 CloudFront 全球分布的特性和 开箱即用的缓存功能,可以让你受益。 -
S3 是高可用的,但你还需要 CDN 高可用。 当你将多个组件串联在一起时,任何一个组件的故障都会影响整个系统。 CloudFront 还通过使用次级源 或存储桶,进一步提高了你的可用性。 -
最后,成本是一个重要因素。 CloudFront 的定价模型基于传输的数据量和请求次数,并采用按需付费模式。 如果客户端的浏览器支持,CloudFront 会自动压缩你的文件,从而减少 数据传输。
Amazon CloudWatch 指标
-
全面覆盖 :它收集来自多个 AWS 服务的指标,包括 Amazon S3 和 Amazon CloudFront,以及其他许多服务。 这种全面的覆盖使你能够从一个集中位置监控和分析整个 AWS 基础设施和应用程序的性能与健康状况。 集中管理。 -
警报和通知 :它支持基于指标阈值或模式创建警报。 当特定条件满足时,这些警报可以触发通知(例如,电子邮件、短信或 AWS Lambda 函数),使你能够主动应对潜在问题或采取 自动化措施。 -
成本效益 :其定价基于接收的指标数量、数据保存期限以及按需付费模式,使你能够随着 AWS 基础设施和应用程序的增长,扩展你的监控工作,而无需承担高额的 前期成本。
编码解决方案
编辑网站
<st c="14804">chapter2/code</st> <st c="14831">index.html</st> <st c="15027">div</st>
<!DOCTYPE html>
<html>
<head>
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Archivo+Narrow&family=Julius+Sans+One&family=Open+Sans&family=Source+Sans+Pro&display=swap" rel="stylesheet"> <st c="15492"><link rel="stylesheet" href="index.css"></st> </head>
<body>
<page size="A4"> <st c="15565"><div class="container"></st>
<st c="15588"><div class="leftPanel"></st> <img src="img/avatar.png"/>
<div class="details">
<div class="item bottomLineSeparator">
<h2>
CONTACT
</h2>
### OUTPUT OMMITED ###
<st c="15890">.html</st> <st c="15899">.htm</st> <st c="16028"><></st> <st c="16147"><p></st>
<st c="16228"><p></st>This is a paragraph in HTML<st c="16260"></p></st>
<st c="16485">index.html</st>

<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Archivo+Narrow&family=Julius+Sans+One&family=Open+Sans&family=Source+Sans+Pro&display=swap" rel="stylesheet">
<link rel="stylesheet" href="index.css">

<st c="20226">div</st>
<st c="20309">index.css</st>
h1 {
font-family: 'Julius Sans One', sans-serif;
}
h2 { /* Contact, Skills, Education, About me, Work Experience */
font-family: 'Archivo Narrow', sans-serif;
}
h3 { /* Accountant */
font-family: 'Open Sans', sans-serif;
} <st c="20710">.container {</st> display: flex;
flex-direction: row;
width: 100%;
height: 100%;
} <st c="20788">.leftPanel</st> {
width: 27%;
background-color: #484444;
padding: 0.7cm;
display: flex;
flex-direction: column;
align-items: center;
}
## OUTPUT OMMITED ###
<st c="20979">leftPanel</st> <st c="20992">container</st><st c="21012">div class</st> <st c="21041">index.html</st>
<st c="21074">avatar.png</st><st c="21142"><</st>``<st c="21143">img></st>
发布网站
<st c="21882">index.html</st><st c="21894">index.css</st><st c="21909">avatar.png</st>
-
选择你的桶作为 Origin 域名 。 -
将 Origin 访问 从 公开 更改为 Origin 访问 控制设置 。 -
创建一个新的 OAC,选择默认选项,并在 Origin 访问控制 下选择它。 -
在 Web 应用防火墙(WAF) 部分,不启用 安全保护。 -
在创建您的分发之前,请仔细阅读所有选项。 注意一些有趣的选项,例如缓存策略、自动压缩对象的能力,以及不同的定价类型。

<st c="23519">cloudprojectwebsitebucket</st>
{
"Version": "2008-10-17",
"Id": "PolicyForCloudFrontPrivateContent",
"Statement": [
{
"Sid": "AllowCloudFrontServicePrincipal",
"Effect": "Allow",
"Principal": {
"Service": "cloudfront.amazonaws.com"
},
"Action": "s3:GetObject",
"Resource": "<st c="23796">arn:aws:s3:::cloudprojectwebsitebucket/*",</st> "Condition": {
"StringEquals": {
"AWS:SourceArn": "arn:aws:cloudfront::111111111111:distribution/E33NUQ32Z0XQZB"
}
}
}
]
}
<st c="24134">index.html</st>
https://<st c="24418">index.html</st> at the end of the URL, right?
<st c="24458">Navigate to your CloudFront distribution and select</st> `<st c="24573">index.html</st>` <st c="24583">and save</st> <st c="24593">your changes.</st>
<st c="24606">Your distribution state will change to</st> **<st c="24646">Deploying</st>** <st c="24655">momentarily, as shown in</st> *<st c="24681">Figure 2</st>**<st c="24689">.5</st>*<st c="24691">, under the</st> **<st c="24703">Last</st>** **<st c="24708">modified</st>** <st c="24716">column.</st>

<st c="24850">Figure 2.5 – CloudFront distribution status during an update</st>
<st c="24910">When the distribution finishes propagating your changes, the status column shows the</st> **<st c="24996">Enabled</st>** <st c="25003">status, and the</st> **<st c="25020">Last modified</st>** <st c="25033">column shows a date as shown in</st> *<st c="25066">Figure 2</st>**<st c="25074">.6</st>*<st c="25076">.</st>

<st c="25223">Figure 2.6 – CloudFront distribution status after an update</st>
<st c="25282">Refresh your</st> <st c="25296">CV page, this time without the path, as shown in the following line.</st> <st c="25365">Remember to replace the highlighted string with your</st> <st c="25418">own domain:</st>
https://
<st c="25469">Et voilà!</st> <st c="25480">Your CV is now online and available for recruiters to</st> <st c="25534">visit it.</st>
<st c="25543">Monitoring the website</st>
<st c="25566">Your website is online, you</st> <st c="25594">can share the URL with other people and they will always have access to your latest CV.</st> <st c="25683">However, how do you know whether they actually accessed it, or whether they are having a</st> <st c="25772">good experience?</st>
<st c="25788">You already know the answer; it’s</st> <st c="25823">CloudWatch metrics:</st>
1. <st c="25842">Navigate to the CloudWatch metrics</st> <st c="25878">console (</st>[<st c="25887">https://us-east-1.console.aws.amazon.com/cloudwatch/home?region=us-east-1#metricsV2</st>](https://us-east-1.console.aws.amazon.com/cloudwatch/home?region=us-east-1#metricsV2)<st c="25971">).</st>
2. <st c="25974">In the</st> **<st c="25982">Browse</st>** <st c="25988">tab, you will find all kinds of AWS services.</st> <st c="26035">Select CloudFront, followed by</st> **<st c="26066">Per-Distribution Metrics</st>**<st c="26090">.</st>
3. <st c="26091">If you have more than one distribution, you will need to identify the relevant one by ID.</st> <st c="26182">If you just have one, select</st> **<st c="26211">BytesDownloaded</st>**<st c="26226">,</st> **<st c="26228">Requests</st>**<st c="26236">,</st> **<st c="26238">5xxErrorRate</st>**<st c="26250">,</st> <st c="26252">and</st> **<st c="26256">4xxErrorRate</st>**<st c="26268">.</st>
<st c="26269">CloudWatch will plot a graphic for you on the top of your screen, like the one shown in</st> *<st c="26358">Figure 2</st>**<st c="26366">.7</st>*<st c="26368">. At 16h25, 18K bytes were downloaded and some users were facing HTTP</st> `<st c="26438">400</st>` <st c="26441">errors.</st> <st c="26450">These metrics were calculated as</st> <st c="26483">five-minute averages.</st>

<st c="26641">Figure 2.7 – CW metrics graph for CloudFront</st>
<st c="26685">These metrics are free</st> <st c="26708">and were automatically populated without you having to do anything other than just configuring CloudFront.</st> <st c="26816">However, if you want more detailed metrics such as</st> **<st c="26867">4xx</st>** <st c="26870">and</st> **<st c="26875">5xx</st>** <st c="26878">error rates by the specific HTTP status code, or cache hits as a percentage of total cacheable requests, you can enable that in your CloudFront distribution at</st> <st c="27039">a cost.</st>
<st c="27046">Explore CloudWatch metrics further and see what other metrics were automatically populated.</st> <st c="27139">Here’s a hint: consider your file</st> <st c="27173">storage service.</st>
<st c="27189">Cleaning up</st>
<st c="27201">AWS resources incur costs.</st> <st c="27229">Although most services initially fall under the free tier, eventually that runs out, and you will incur costs.</st> <st c="27340">We recommend that you delete every application after you are done playing</st> <st c="27414">with it.</st>
<st c="27422">Start by deleting your</st> <st c="27445">CloudFront distribution:</st>
1. <st c="27470">Navigate to CloudFront</st> <st c="27494">console (</st>[<st c="27503">https://us-east-1.console.aws.amazon.com/cloudfront/v4/home?region=us-east-1#/distributions</st>](https://us-east-1.console.aws.amazon.com/cloudfront/v4/home?region=us-east-1#/distributions)<st c="27595">).</st>
2. <st c="27598">Select and disable your</st> <st c="27623">CloudFront distribution.</st>
3. <st c="27647">After it’s</st> <st c="27658">disabled, delete</st> <st c="27676">the distribution.</st>
<st c="27693">Next, delete your</st> <st c="27712">S3 bucket:</st>
1. <st c="27722">Navigate to S3</st> <st c="27738">console (</st>[<st c="27747">https://s3.console.aws.amazon.com/s3/home?region=us-east-1</st>](https://s3.console.aws.amazon.com/s3/home?region=us-east-1)<st c="27806">).</st>
2. <st c="27809">Select your bucket.</st> <st c="27830">Inside, delete all three files.</st> <st c="27862">Buckets can only be deleted if they</st> <st c="27898">are empty.</st>
3. <st c="27908">Delete</st> <st c="27916">your bucket.</st>
<st c="27928">Future work</st>
<st c="27940">Congratulations, you now have a working static website hosted on AWS.</st> <st c="28011">There are multiple features you can complement it with.</st> <st c="28067">This section details a few ideas, but it doesn’t guide you through</st> <st c="28134">their implementation.</st>
<st c="28155">Implementing custom DNS</st>
<st c="28179">Right now, your CV is at a</st> <st c="28207">non-memorable URL.</st> <st c="28226">It would be easier for you and others to remember if your URL was something such</st> <st c="28307">as</st> `<st c="28310">bestcandidatecv.com</st>`<st c="28329">.</st>
<st c="28330">When you access a URL, in the backend, your workstation does a lookup of this URL to retrieve the IP address.</st> <st c="28441">Then it connects to</st> <st c="28461">that address.</st>
<st c="28474">To verify this behavior, open your favorite terminal and execute the following command; it returns a series of IP addresses.</st> <st c="28600">Make sure you replace the URL with</st> <st c="28635">your own:</st>
$ nslookup d1hjtv5xjv873g.cloudfront.net
<st c="28685">CloudFront supports having custom</st> <st c="28720">domain names.</st>
<st c="28733">To achieve it, first, you will need to register a new domain.</st> <st c="28796">Domains are unique.</st> <st c="28816">Within the AWS ecosystem, you can register a new domain using</st> **<st c="28878">Route 53</st>**<st c="28886">. However, you can also register your domain with other providers.</st> <st c="28953">Domains</st> <st c="28961">have a</st> <st c="28968">yearly cost.</st>
<st c="28980">Secondly, you will need to create a DNS record inside your domain.</st> <st c="29048">If you are managing your domain in Route 53, this will be done under hosted zones.</st> <st c="29131">This DNS record points your new name to your CloudFront distribution</st> <st c="29200">DNS name.</st>
<st c="29209">In simple terms, if someone looks up</st> `<st c="29247">bestcandidatecv.com</st>`<st c="29266">, the server will return</st> `<st c="29291">d1hjtv5xjv873g.cloudfront.net</st>`<st c="29320">, and then recursively,</st> <st c="29344">the IP.</st>
<st c="29351">Lastly, you will need a</st> <st c="29376">new certificate.</st> <st c="29393">Navigate to your current CV website and check the certificate details.</st> <st c="29464">They should look like</st> *<st c="29486">Figure 2</st>**<st c="29494">.8</st>*<st c="29496">. This certificate is only valid for common names that end</st> <st c="29555">with</st> `<st c="29560">cloudfront.net</st>`<st c="29574">.</st>

<st c="29888">Figure 2.8 – CloudFront default certificate</st>
<st c="29931">Since you will access your CV with a custom name, you will need a certificate that supports that naming.</st> <st c="30037">Within the AWS ecosystem, you can use the</st> **<st c="30079">AWS Certificate Manager</st>** <st c="30102">(</st>**<st c="30104">ACM</st>**<st c="30107">) to issue a</st> <st c="30121">new certificate.</st>
<st c="30137">If you are interested in implementing this feature, the AWS documentation details the whole</st> <st c="30230">process:</st> [<st c="30239">https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/CNAMEs.html</st>](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/CNAMEs.html)<st c="30317">.</st>
<st c="30318">Taking security to the next level</st>
<st c="30352">Your website</st> <st c="30365">is simple, and while static websites are generally considered less vulnerable to certain types of web attacks due to their lack of dynamic content and server-side</st> <st c="30528">processing, they can still be targeted by various attacks, such as</st> **<st c="30596">Distributed Denial-of-Service</st>** <st c="30625">(</st>**<st c="30627">DDoS</st>**<st c="30631">) attacks, or</st> <st c="30646">content injection.</st>
<st c="30664">For example, a malicious person can launch a DDoS attack on your website right before an interview.</st> <st c="30765">Then during the interview, when you mention it, the website is not available, making you</st> <st c="30854">look bad.</st>
<st c="30863">Security is a</st> <st c="30878">huge topic, but some quick wins that you can implement are</st> <st c="30936">AWS</st> **<st c="30941">Web Application Firewall</st>** <st c="30965">(</st>**<st c="30967">WAF</st>**<st c="30970">) and</st> <st c="30976">AWS Shield.</st>
<st c="30988">Web Application Firewall</st>
<st c="31013">AWS WAF is a</st> <st c="31026">web application firewall (not all AWS services are what the name implies) that helps to protect from common web exploits that could affect application availability, compromise security, or consume</st> <st c="31224">excessive resources.</st>
<st c="31244">WAF is a managed service, and it offers managed rules</st> <st c="31299">called</st> **<st c="31306">rulesets</st>**<st c="31314">. They are groups of security rules that protect you against common attacks and are automatically updated as new threats emerge.</st> <st c="31443">This is especially useful if you are not a security expert, or if you don’t want to spend your time managing</st> <st c="31552">security rules.</st>
<st c="31567">WAF is neatly integrated with CloudFront, and you can enable it by editing your CloudFront distribution.</st> <st c="31673">It’s a one-click action.</st> <st c="31698">Doing so creates a WAF web ACL for you with 3 Amazon-managed rulesets.</st> <st c="31769">You can view them in your</st> <st c="31795">WAF console.</st>
<st c="31807">You can add more rules to the created Web ACL, or if you want to, you can configure a custom web ACL and attach it to your</st> <st c="31931">CloudFront distribution.</st>
<st c="31955">Your static website does not interact with user inputs.</st> <st c="32012">In later chapters, as your application attack</st> <st c="32057">surface increases, you will see more benefits</st> <st c="32104">of WAF.</st>
<st c="32111">If you are</st> <st c="32122">interested in implementing this feature, the AWS documentation details the whole</st> <st c="32204">process:</st> [<st c="32213">https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/distribution-web-awswaf.html</st>](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/distribution-web-awswaf.html)<st c="32308">.</st>
<st c="32309">Shield</st>
<st c="32316">AWS Shield is</st> <st c="32330">a managed DDoS protection service.</st> <st c="32366">It is designed to safeguard applications running on AWS against DDoS attacks, which are attempts to make a website or application unavailable by overwhelming it with</st> <st c="32532">malicious traffic.</st>
<st c="32550">Shield uses techniques such as traffic flow monitoring, network anomaly detection, and traffic scrubbing to identify and filter out</st> <st c="32683">malicious traffic.</st>
<st c="32701">It has two offerings:</st> **<st c="32724">Standard</st>** <st c="32732">and</st> **<st c="32737">Advanced</st>**<st c="32745">.</st>
<st c="32746">You are</st> <st c="32754">already using Shield Standard.</st> <st c="32786">This tier is automatically enabled for all AWS customers at no additional cost.</st> <st c="32866">It shields you from the most common and frequently occurring DDoS attacks targeting</st> <st c="32950">web applications.</st>
<st c="32967">Shield</st> <st c="32975">Advanced is an optional paid subscription that you can enable on a resource basis.</st> <st c="33058">It provides additional detection and mitigation capabilities against more sophisticated and larger DDoS attacks, including those targeting higher layers (HTTP/HTTPS) and specific applications.</st> <st c="33251">Shield Advanced integrates with services such as AWS WAF for more advanced</st> <st c="33326">security controls.</st>
<st c="33344">We do</st> *<st c="33351">not</st>* <st c="33354">recommend that you enable Shield Advanced for this project.</st> <st c="33415">It has a long subscription commitment, one year, and a big price tag for a personal project</st> <st c="33507">at $3,000/month.</st>
<st c="33523">If you are interested in knowing more about</st> <st c="33568">AWS Shield, visit the AWS documentation at</st> [<st c="33611">https://aws.amazon.com/shield/</st>](https://aws.amazon.com/shield/)<st c="33641">.</st>
<st c="33642">Having better observability</st>
<st c="33670">Logging</st> <st c="33679">refers to the process of recording events, messages, and other information generated by an application during its execution.</st> <st c="33804">It is an essential practice in software development and operations as it provides insights into the behavior, performance, and potential issues of</st> <st c="33951">an application.</st>
<st c="33966">You configured and verified metrics for your static website, but not logs.</st> <st c="34042">S3, CloudFront, WAF, and other AWS services have the ability to</st> <st c="34106">generate logs.</st>
<st c="34120">Consider enabling CloudFront access logs.</st> <st c="34163">They are log files that contain detailed information about every user request that CloudFront receives.</st> <st c="34267">You can enable access logs by editing your</st> <st c="34310">CloudFront distribution.</st>
<st c="34334">CloudFront logs contain 33 fields.</st> <st c="34370">Since that’s too many to list, some important ones to have in mind are</st> <st c="34441">as follows:</st>
* `<st c="34452">date</st>`
* `<st c="34457">time</st>`
* `<st c="34462">c-ip</st>` <st c="34467">– the IP address of</st> <st c="34488">the viewer</st>
* `<st c="34498">cs(UserAgent)</st>` <st c="34512">– the</st> <st c="34519">browser identifier</st>
* `<st c="34537">x-edge-location</st>` <st c="34553">– the physical location the request</st> <st c="34590">entered from</st>
<st c="34602">Important note</st>
<st c="34617">Although this feature might not seem very useful for this specific project, having an observable solution is considered an industry best practice.</st> <st c="34765">You will regret not having logs at the time of</st> <st c="34812">troubleshooting issues.</st>
<st c="34835">Logs can be written</st> <st c="34856">to various destinations, such as files, databases, or centralized logging services such as CloudWatch, Elasticsearch, or Splunk.</st> <st c="34985">CloudFront logs are written to an S3 bucket of your choice.</st> <st c="35045">If, later, you decide that you want to centralize your logs in CloudWatch, you can move them from S3\.</st> <st c="35147">AWS designed this architecture in a blog</st> <st c="35188">post:</st> [<st c="35194">https://aws.amazon.com/blogs/mt/sending-cloudfront-standard-logs-to-cloudwatch-logs-for-analysis/</st>](https://aws.amazon.com/blogs/mt/sending-cloudfront-standard-logs-to-cloudwatch-logs-for-analysis/)<st c="35291">.</st>
<st c="35292">After you have access to your CloudFront log files, you can correlate them with your CloudWatch metrics and have a complete picture of your user experience.</st> <st c="35450">For example, you will be able to tell, for the users having 4xx errors in</st> *<st c="35524">Figure 2</st>**<st c="35532">.7</st>*<st c="35534">, which countries are they from, which browser versions are they running, and which SSL security ciphers they tried</st> <st c="35650">to negotiate.</st>
<st c="35663">As mentioned, it’s also possible to enable logs for the other components of your architecture, such as S3\.</st> <st c="35771">Investigate the benefits of that on</st> <st c="35807">your own.</st>
<st c="35816">If you are interested in implementing CloudFront access logs, the AWS documentation details the whole</st> <st c="35919">process:</st> [<st c="35928">https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/AccessLogs.html</st>](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/AccessLogs.html)<st c="36010">.</st>
<st c="36011">Final architecture</st>
<st c="36030">The final architecture, after</st> <st c="36061">enhancements, should look like the one in</st> *<st c="36103">Figure 2</st>**<st c="36111">.9</st>*<st c="36113">. Notice the addition of WAF, Route 53, and Certificate Manager.</st> <st c="36178">Your final architecture might look slightly different if you did not implement all</st> <st c="36261">the enhancements.</st>

<st c="36369">Figure 2.9 – Final static website architecture with improvements</st>
<st c="36433">The final simplified traffic flow is</st> <st c="36471">as follows:</st>
1. <st c="36482">The client enters your custom URL in</st> <st c="36520">its browser.</st>
2. <st c="36532">Route 53 responds to the</st> <st c="36558">DNS query.</st>
3. <st c="36568">The client’s browser sends the HTTP request to</st> <st c="36616">CloudFront IPs.</st>
4. <st c="36631">The request is inspected</st> <st c="36657">by WAF.</st>
5. <st c="36664">CloudFront replies to the request, and returns the</st> <st c="36716">static assets.</st>
6. <st c="36730">The</st> <st c="36734">client’s browser renders the</st> <st c="36764">website locally.</st>
<st c="36780">All the components send metrics and logs to CW</st> <st c="36828">as configured.</st>
<st c="36842">Summary</st>
<st c="36850">In this chapter, you learned what static websites are.</st> <st c="36906">You also learned about the common files that compose them, such as HTML, CSS, and JavaScript.</st> <st c="37000">You followed</st> *<st c="37013">Chapter 1</st>*<st c="37022">’s methodology of requirements gathering, architecture patterns, service selection, and diagraming to draw the architecture of your own static website, a</st> <st c="37177">personal page.</st>
<st c="37191">Then, using the AWS console, you</st> <st c="37225">built it.</st>
<st c="37234">Lastly, you learned about multiple possible enhancements that can take your static website to a production-level website.</st> <st c="37357">By now, you are capable of building globally distributed, highly available, highly resilient, secure</st> <st c="37458">static websites.</st>
<st c="37474">In the next chapter, you are going to go beyond static websites and create a dynamic web application to share recipes.</st> <st c="37594">You will put all your knowledge in static websites to use, but take it one</st> <st c="37669">step further.</st>
第二部分:中级项目
-
第三章 , 构建一个食谱分享应用 -
第四章 , 构建一个无服务器食谱分享应用 -
第五章 , 实现图像分析器以检测照片友好性 -
第六章 , 构建内容翻译管道
第四章:3
构建一个食谱分享应用程序
-
你将要构建的——一个用于 分享食谱 -
你将如何构建它——使用 S3 和 CloudFront 构建前端,使用 EC2 托管 API,使用 DynamoDB 存储 你的食谱 -
构建它——通过 CloudFormation 和使用 AWS 控制台 -
如何改进解决方案——改进监控和应用日志,强制执行安全协议以访问应用程序,并且 实施身份验证
技术要求
场景
需求
-
平台管理员 :平台所有者,可能希望创建新配方、维护或 删除配方。 -
终端用户/消费者 :使用平台访问特定配方的最终用户,不应具备创建、更改或删除 任何记录的权限。
业务需求
-
在年底之前全球达到 100,000 用户 的目标 -
增强 在欧洲的存在 -
在支持增长的同时保持成本效益 且成本不显著
功能需求
<st c="6170">/user</st> <st c="6198">/admin</st>

-
<st c="6742">/</st>``<st c="6744">用户</st>: -
访问 食谱标题列表 -
能够选择特定食谱并访问所有 详细信息 -
响应式
-

-
<st c="7061">/</st>``<st c="7063">管理员</st>: -
访问 食谱标题列表 -
能够 删除食谱 -
支持 食谱创建 -
控制 最大支持的食材、步骤和 食谱数量 -
响应式
-

非功能性需求
-
全球分发,服务全球用户 分布在全球各地的用户 -
自动扩展以处理突发 使用模式 -
成本效益
技术要求
-
现代前端框架 – React.js -
后端编程语言 – Python -
FastAPI 作为 API 开发框架
数据需求
-
列出食谱 :展示已创建的食谱列表。 -
删除一个食谱 :如果管理员不再希望某个特定的食谱成为组合的一部分,应当能够删除该条目。 -
创建一个食谱 :创建一个新的食谱与 用户分享。
<st c="9671">recipe_example.json</st>
{ "ID":"GUID",
"Title":"recipe title",
"Ingredients":[…],
"Steps":[…] }
架构模式
-
什么是 单页面应用 ( SPA ),它与传统的 网页应用有何不同? -
API 在你的应用中扮演什么角色? 为什么你 需要一个 API?
架构


-
<st c="13215">GET /recipes</st>:此操作获取食谱列表。 -
<st c="13261">GET /health</st>:这是一个简单的健康 检查端点。 -
<st c="13315">DELETE /recipes/{recipe_id}</st>:此操作删除具有 定义 ID 的特定食谱。 -
<st c="13395">POST /recipes</st>:此操作创建一个新的 食谱记录。

AWS 服务
Amazon S3
Amazon CloudFront
Amazon 虚拟私有云(VPC)
Amazon EC2
应用程序负载均衡器 (ALB)
-
健康检查 :每个 负载均衡器都需要至少一个目标组,你可以为目标配置健康检查,以确保流量只发送到健康的目标,避免不良的用户体验,并提高应用程序的弹性和容错能力。 你的应用程序。 -
SSL 终止 :ALB 支持 SSL 终止,卸载加密和解密的计算负担,减轻你的 EC2 实例的负担。
亚马逊 DynamoDB
选择你的
AWS CloudFormation
在
编码解决方案
克隆项目
<st c="22055">chapter3/code</st>
<st c="22081">chapter3/code</st>
-
<st c="22159">frontend</st>:此处包含 你的前端代码 -
<st c="22210">backend</st>:此处包含 你的 API 代码 -
<st c="22256">platform</st>:此处包含两个不同的 CloudFormation 模板,用于部署 你的应用程序 的主要基础设施。

<st c="23227">平台</st>
<st c="23498">ch3-https-complete.yaml</st> |
|||
<st c="23606">ch3-http.yaml</st> |
第一部分 – DNS 配置和证书签发(仅适用于选项 1)
Route 53 中的 DNS 配置
<st c="25559">route 53</st>

-
点击 托管区域 。 -
然后,点击 创建 托管区域 。 -
填写 <st c="25967">awscloudprojects.site</st>。 -
选择 公共托管区域 作为 类型。 -
点击 创建 托管区域 。

-
点击你创建的域名。 -
请注意相关的名称服务器,因为你将需要它们来配置 DNS。

证书颁发

-
点击 请求一个 证书 按钮。 -
在 证书类型 屏幕上,选择 请求公共证书 选项,点击 下一步 。 -
在表单中填写必要的信息。大多数字段可以保留默认值,但对于
app.example.com、api.example.com等,您可能需要进行调整。 -
*.example.com。 -
确保验证方法设置为DNS 验证,这是 AWS 推荐的方式。
-
点击请求。
图 3.12展示了表单的最终状态,包含所有必要字段。

图 3.12 – 证书请求表单
在请求证书后,您将看到它的状态为待验证。要验证证书并证明域名所有权,您需要在您的托管区域创建一个 DNS 记录。
如果您的域名由 Route 53 管理,您可以点击创建 Route 53 记录,如图 3.13所示,这样可以更轻松地进行设置。

图 3.13 – 使用 DNS 记录验证证书
在继续操作之前,您需要等待状态变为已颁发,如图 3.14所示。如果一切配置正常,通常不需要超过 10 分钟,但根据 AWS 文档,可能需要长达几个小时,查看详细信息。

图 3.14 – ACM 证书列表
最后一步是记下certificateARN,您需要在 CloudFormation 模板中作为参数输入它:
-
导航到您创建证书所在区域的 ACM 控制台。
-
从左侧面板中选择证书列表。
-
定位到您的“已颁发”证书,如图 3.14所示。
-
点击证书,在 证书状态 下,你将 找到 ARN 。

<st c="31982">arn:partition:service:region:account-id:resource-type/resource-id</st>
第二部分 – 解决方案部署
<st c="32233">chapter3/code</st>
<st c="32465">ch3-https-complete.yaml</st> |
<st c="32489">ch3-http.yaml</st> |
|
-
1 VPC -
2 公共子网 -
2 私有子网 -
1 私有 EC2 实例 -
1 ALB -
1 NAT 网关 -
EC2 实例角色,具有与 DynamoDB 交互的最小权限 食谱表
|
-
1 VPC -
1 公共子网 -
1 公共 EC2 实例 -
EC2 实例角色,具有与 DynamoDB 交互的最小权限 食谱表
|

图 3.16 – 控制台访问 CloudFormation
要继续堆栈创建,请按照以下步骤操作:
-
点击创建堆栈。
-
在先决条件 – 准备模板部分,选择选择一个现有模板。
-
在指定模板部分,选择上传模板文件。
-
点击选择文件。
-
根据您所遵循的选项,从
chapter3/code/platform文件夹中选择模板。 -
点击下一步。
您的创建堆栈窗口应如下所示图 3.17。

图 3.17 – CloudFormation 创建堆栈表单
下一步是配置 CloudFormation 堆栈中的参数。参数允许您创建动态且特定于环境的资源配置,从而提高基础设施作为代码的安全性和可维护性。在表 3.3中,我们解释了每个参数的目的以及哪些适用于您选择的选项。
| 参数 | 描述 | 选项 1(HTTPS 配置) | 选项 2(HTTP 配置) |
|---|---|---|---|
<st c="35278">InstanceType</st> |
从四个可用选项中选择 EC2 实例类型;默认是免费层,t3.micro。 |
是 | 是 |
<st c="35401">LatestAmiId</st> |
Amazon 机器镜像(AMI)将在您的 EC2 实例中使用。默认情况下,它将使用最新的 AMI。 | 是 | 是 |
<st c="35531">GitRepoURL</st> |
|||
<st c="35633">ALBCertificateArn</st> |
<st c="35907">ALBCertificateArn</st>

<st c="36639">IAMPolicy</st>


第三部分 – 附加配置(仅选项 1)
<st c="37914">api.<your_domain></st>
-
前往 Route 53 控制台。 -
选择你的域名的 托管区。 -
点击 创建记录 。 -
进入 <st c="38129">api</st>). -
对于 记录类型 ,选择 A - IPv4 地址 。 -
点击 记录名称 下的切换按钮 启用 别名 。 -
在 将流量路由到 下拉菜单中,选择 应用程序和经典的别名 负载均衡器 。 -
选择你的应用程序 部署的 AWS 区域。 -
在 选择负载均衡器 部分,选择与你的 CloudFormation 堆栈关联的 ALB。 -
如果 你在所选区域有多个负载均衡器,你可以通过检查 CloudFormation 堆栈的输出 部分来找到正确的负载均衡器 DNS 名称,在 CloudFormation 控制台中查看。 -
点击 创建记录 按钮保存 新记录。

第四部分 – 前端配置与部署
<st c="39937">…/frontend/src/configs/configs.tsx</st>
-
<st c="40106">CONFIG_MAX_INGREDIENTS</st>: 一份食谱中最大 配料数 -
<st c="40159">CONFIG_MAX_STEPS</st>: 一份食谱中的最大 步骤数 -
<st c="40200">CONFIG_MAX_RECIPES</st>: 支持的最大 食谱数量 -
<st c="40243">CONFIG_USER_PAGE_TITLE</st>: 用户页面的标题 用户页面 -
<st c="40288">CONFIG_ADMIN_PAGE_TITLE</st>: 管理员页面的标题 管理员页面 -
<st c="40335">CONFIG_appConfig</st>:包含页面标题和图标的对象(图标位于 <st c="40397">/frontend/public/</st>) -
<st c="40416">API_URL</st>: API 端点

<st c="40955">API_URL</st> <st c="41092">API_URL</st>
选项 1 的解决方案
<st c="41427">API_URL</st>
<st c="41506">api.awscloudprojects.site</st> <st c="41543">API_URL</st> <st c="41568">https://api.awscloudprojects.site</st>
选项 2 的解决方案
<st c="42180">APIDNSName</st>
<st c="42217">API_URL</st> <st c="42429">npm</st>
$ npm install && npm run build
<st c="42652">build/</st> <st c="42662">dist/</st>

-
<st c="43093">frontend-chapter-3-</st>后面跟着一串随机字符(例如, <st c="43162">frontend-chapter-3-XXXXX</st>)。 点击其名称以 打开它。 -
从 <st c="43239">dist</st>文件夹添加文件。 -
在 S3 存储桶中,点击 上传 按钮。 这将允许您从本地机器上传文件到 S3 存储桶。
<st c="43458">dist</st>文件夹在您的本地机器上,选择该文件夹中的所有文件并确认。 接下来,在 S3 控制台中,点击 <st c="43603">dist</st>文件夹,选择 <st c="43649">assets</st>文件夹, 并确认。

-
<st c="44419">i</st>``<st c="44421">ndex.html</st> -
<st c="44430">i</st>``<st c="44432">ndex-XXXXXX.css</st> -
<st c="44447">i</st>``<st c="44449">ndex-XXXXXX.js</st> -
您可能在应用程序中包含的静态文件,例如图像
第五部分 – 测试和探索您的应用程序
测试和探索后端
<st c="45137">API_URL</st> <st c="45162">config.tsx</st>
<st c="45427">{API_URL}/{ROUTE}</st><st c="45452">API_URL</st> <st c="45487">config.tsx</st> <st c="45534">ROUTE</st>
<st c="45812">curl</st>
<st c="45877">curl</st> <st c="45924">/recipes</st>
$ curl -i 'https ://api.awscloudprojects.site/recipes'
HTTP/2 200
date: Wed, 03 Apr 2024 16:06:15 GMT
contente-type: application/json
contente-length: 2
server: nginx/1.18.0 (Ubuntu)
[]
<st c="46214">GET</st> <st c="46233">/recipes</st> <st c="46333">200</st>
测试和探索前端
<st c="46554">需求</st>
-
进入 CloudFront 控制台。 -
选择您用 CloudFormation 堆栈创建的分发。 (如果您有多个分发,并且不确定哪一个是由 堆栈创建的,请打开 CloudFormation 服务,转到您之前创建的堆栈,并检查输出值 <st c="46950">CloudFrontDistributionId</st>)。 -
复制分发的 URL(它应该遵循 结构 <st c="47042">https://XXXXXX.cloudfront.net/</st>)。 -
如果您愿意,您也可以从 <st c="47188">CloudFrontDistributionUrl</st>中获取该值。 -
如果您复制并粘贴 URL 到浏览器中,您应该能够访问您新创建的应用程序并在 用户 和 管理员 页面之间导航。 如果您尝试访问 管理员 页面,您应该获得与 图 3 **.25 相同的体验。

在浏览器中启用 HTTP 通信(仅限选项 2)

之所以会发生这种情况,是因为 HTTP 不是一个安全协议,而你的应用正在尝试对你的 API 发出 HTTP 请求。
如需深入故障排除,你可以在开发者工具中打开控制台,并查看我们收到的

图 3.27 – 控制台错误示例
仅限演示用途,你可以指示浏览器绕过其默认行为并接受 HTTP 连接,但需要强调的是,虽然这在本次练习中可以使用,但这并不是最佳实践,不应
如果你想跳过这个阻塞,你可以进行如下操作:
-
点击红色的
不安全 通知/ 查看网站信息 按钮,位于 URL 地址栏的左侧。 -
转到网站的
设置 。 -
滚动到
不安全内容 。 -
将
阻止(默认) 更改为 允许 。
这些指示适用于 Google Chrome,可能会根据版本或使用的浏览器有所不同。
测试并探索你的 DynamoDB 表
最后一步是测试你 API 和 DynamoDB 中的数据层之间的集成,你的食谱数据存储在这里。
-
转到你的
DynamoDB 页面,位于你的 AWS 账户中。 -
点击
探索项目 在 左侧菜单上。 -
选择你的
食谱表。 -
在你测试创建和删除食谱操作时,列出表中的项目。
这些操作应该在你的 DynamoDB 探索 项目 控制台中反映出来。

第六节 – 清理
-
<st c="51993">frontend-chapter-3-</st>后面跟着一串随机字符( 例如, <st c="52063">frontend-chapter-3-XXXXX</st>) 。 -
点击 清空 – 这将删除你桶内的所有内容。

-
删除 CloudFormation 堆栈 : -
前往你的 AWS 账户中的 CloudFormation 控制台。 -
选择你创建的堆栈。 -
点击 “删除” 删除 。
-

清理证书和 DNS 管理配置(选项 1)
-
删除 证书 : -
进入你的 证书管理器 控制台。 -
选择你创建的证书。 -
点击 在 删除 。
-

-
清理 DNS :如果你想继续在 Route 53 中管理 DNS,你可以直接 删除 为你的 API 创建的记录: -
进入你的 Route 53 控制台。 -
在左侧面板中选择 托管区域 。 -
选择你为 你的域名创建的托管区域。 -
选择 API 的记录。 -
点击 删除记录 。
-

未来工作
使用安全协议
基础设施自动扩展
托管服务和 CI/CD
身份验证
日志记录与监控
缓存

总结
第五章:4
构建无服务器食谱分享应用
-
你将要构建的内容——一个完全由 无服务器技术支持的最新版本的食谱分享应用 -
你将如何构建它——使用 Amazon API Gateway 和 Lambda 作为后端,Amazon Cognito 用于身份验证 -
构建它——通过 CloudFormation 并使用 AWS 控制台 -
如何改进解决方案——支持食谱的媒体内容,并将身份验证扩展到最终用户,以便提供更 个性化的体验
技术要求
场景
需求
-
管理员 :平台所有者,负责创建和 管理食谱 -
最终用户或消费者 :访问共享的食谱并点赞 喜欢的食谱
业务需求
-
实现 10%的年 用户增长 -
提高 你的 成本效益
功能需求
-
两种不同的用户类型(管理员 和用户) -
简单 的用户界面 -
响应能力
-
身份验证 和授权 -
能够对食谱进行点赞,并按点赞排序 进行排序
<st c="7359">/user</st>:像一个 特定食谱。

<st c="7589">/admin</st>:通过身份验证机制限制对管理员门户的访问,当用户尝试访问管理员页面时,提供一个简单的表单,如 图 4 **.2 所示。

非功能性需求
-
成本效益 -
事件驱动架构 -
低 基础设施管理
技术需求
数据需求
-
列出食谱 :展示已创建的 食谱列表。 -
删除食谱 :如果管理员不再希望某个特定的食谱出现在他们的目录中,应该允许删除 该项。 -
创建食谱 :创建一个新的食谱以便与 用户分享。 -
点赞食谱 :增加特定食谱的点赞数。
<st c="9630">recipe_example_2.json</st>
{ "ID":"GUID",
"Title":"recipe title",
"Ingredients":[…],
"Steps":[…],
"Likes":X }
架构模式
架构
-
展示层 :如何托管和提供 前端 -
计算层 :如何整合和执行 业务逻辑 -
数据层 :存储和检索 您的数据

-
<st c="12238">GET /auth</st>: 测试 授权流程 -
<st c="12274">GET /recipes</st>: 获取菜谱列表 的接口 -
<st c="12313">GET /health</st>: 简单健康 检查端点 -
<st c="12356">DELETE</st> <st c="12364">/recipes/{recipe_id}</st>: 删除特定的菜谱,使用 其 ID -
<st c="12421">POST /recipes</st>: 创建新的 菜谱记录 -
<st c="12464">PUT /reci</st><st c="12474">pes/like/{recipe_id}</st>: 增加菜谱的喜欢数
<st c="12579">/auth</st>

AWS 服务
Amazon Simple Storage Service (S3)
Amazon CloudFront
Amazon DynamoDB
AWS CloudFormation
Amazon Cognito
Amazon Lambda
API Gateway
编码解决方案
克隆项目
<st c="18611">chapter4/code</st>
-
<st c="18695">前端</st>: 包含你的前端代码。 -
<st c="18742">平台</st>: 包含一个 CloudFormation 模板,用于部署你应用程序的主要基础设施。

解决方案部署
<st c="19040">ch4-application-template.yaml</st><st c="19095">/platform</st> <st c="19123">chapter4/code</st> <st c="19145">chapter4/code/platform/ch4-application-template.yaml</st>
-
1 个 HTTP API,拥有 6 个端点 -
6 个 lambda 函数,每个对应一个 端点 -
1 Cognito 用户池
|
从控制台进入 CloudFormation 服务(console.aws.amazon.com/cloudformation/),并选择你希望应用程序所在的区域。你可以在控制台窗口右上角的下拉菜单中选择 AWS 区域,如图 4.6所示。

图 4.6 – 控制台访问 CloudFormation
为什么选择区域很重要?
在 AWS 中,服务可以根据其可用性和数据复制机制分为区域服务或全球服务。区域服务部署并在特定 AWS 区域内运行,而全球服务旨在提供跨多个区域的一致体验。
CloudFormation 是一个区域服务的例子。因此,选择正确的区域至关重要,因为这确保了你的资源部署在离目标用户更近的位置,从而提供更低的延迟和最佳的用户体验。
要继续创建堆栈,请按以下步骤操作:
-
点击创建堆栈。
-
在前提条件 – 准备模板部分,选择选择一个现有模板。
-
在指定模板部分,选择上传模板文件。
-
点击选择文件。
-
从
chapter4/code/platform文件夹中选择模板。 -
点击下一步。你的创建堆栈窗口应显示为图 4.7。

图 4.7 – 一个 CloudFormation 创建堆栈表单
下一步是配置你在 CloudFormation 堆栈中的参数。在表 4.2中,你可以找到每个参数的详细说明。
| 参数 | 描述 |
|---|---|
<APIName> |
你希望与之关联的 API 名称 |
<st c="22269">UserEmail</st> |
|
<st c="22409">UserPoolName</st> |
|
<st c="22471">Username</st> |



前端配置和部署
在所有 AWS 服务配置完成后,接下来是配置前端并部署文件。
转到…/frontend/src/configs文件夹,您将找到两个文件:
-
<st c="25250">aws-exports.ts</st>:此文件用于配置您与 Cognito 用户池的数据认证。 -
<st c="25356">configs.tsx</st>:此文件用于配置您的应用程序,即要使用的 API URL。
让我们详细看看它们。
aws-exports.ts
该文件由四个配置变量组成:
-
<st c="25546">AWS_PROJECT_REGION</st>:您部署解决方案的区域 -
<st c="25605">AWS_COGNITO_REGION</st>:您的 Cognito 用户池区域 -
<st c="25656">AWS_USER_POOLS_ID</st>:您的用户池 ID -
<st c="25701">AWS_USER_POOLS_WEB_CLIENT_ID</st>:您的 Cognito 用户池应用程序的客户端 ID
configs.tsx:
该配置文件包含七个配置项:
-
<st c="25851">CONFIG_MAX_INGREDIENTS</st>:一个配方中的最大食材数 -
<st c="25904">CONFIG_MAX_STEPS</st>:一个配方中的最大步骤数 -
<st c="25945">CONFIG_MAX_RECIPES</st>:支持的最大配方数 -
<st c="25988">CONFIG_USER_PAGE_TITLE</st>:用户页面的标题 -
<st c="26033">CONFIG_ADMIN_PAGE_TITLE</st>:管理员页面的标题 -
<st c="26080">CONFIG_appConfig</st>:包含页面标题和图标的对象(图标在/frontend/public/中) -
<st c="26161">CONFIG_API_URL</st>:API 端点
所有作为配置文件一部分的必填值都可以在您刚刚部署的 CloudFormation 模板的
要访问它,请按以下步骤操作:
-
转到 CloudFormation 控制台:
console.aws.amazon.com/cloudformation/。 -
点击您的堆栈。
-
在右侧菜单中,选择输出标签,如图 4.11所示。

图 4.11 – CloudFormation 输出标签
表 4.3 映射了 Stack 输出与配置文件的参数(aws-exports.ts和config.tsx)。
| 文件 | 参数 | Cloudformation Stack 输出 |
|---|---|---|
aws-exports.ts |
aws_project_region |
CognitoRegion |
aws_cognito_region |
CognitoRegion |
|
aws_user_pools_id |
UserPoolId |
|
aws_user_pools_web_client_id |
UserPoolClientId |
|
configs.tsx |
CONFIG_API_URL |
HttpApiEndpoint |
表 4.3 – CloudFormation 输出与aws-exports.ts参数之间的映射
将每个文件中的值粘贴到相应的位置,最终,您的参数aws-exports.ts文件应该如下所示,见图 4.12。

图 4.12 – 配置文件示例(aws-exports.ts)
并且config.tsx文件应该如下所示,见图 4.13。

图 4.13 – 配置文件示例(config.tsx)
- 保存文件。
一旦更新了配置文件,您可以启动build过程,将代码转化为可供浏览器使用的网页打包文件。在我们的示例中,我们使用npm作为包管理器,所以您需要安装依赖并启动build过程:
$ npm install && npm run build
请注意,之前的命令应在frontend文件夹的根目录下运行。为了测试您是否处于根目录,可以使用以下命令:
$ pwd
…/chapter4/code/frontend
<st c="29225">build/</st> <st c="29235">dist/</st>

-
定位到 S3 存储桶。 -
首先,你需要找到之前使用 CloudFormation 模板创建的 S3 存储桶。 存储桶的名称应以 <st c="29766">frontend-chapter-4-</st>开头,后面跟着一串随机字符(例如, <st c="29836">frontend-chapter-4-XXXXX</st>)。 点击其名称以 打开它。 -
从 <st c="29913">d</st><st c="29914">ist</st>文件夹中添加文件。 -
在 S3 存储桶内,点击 上传 按钮。 这将允许你从本地机器上传文件到 S3 存储桶。 -
将必要的内容添加到 存储桶中。 -
首先,点击 <st c="30132">dist</st>文件夹,在本地机器上选择该文件夹中的所有文件并确认。 接下来,在 S3 控制台中,点击 <st c="30277">dist</st>文件夹,选择 <st c="30323">assets</st>文件夹, 并确认。 -
你也可以选择将内容直接拖拽到 S3 窗口中,但无论你使用哪种方法,你的 S3 上传 窗口应该像 图 4 **.15 所示。

<st c="30884">构建</st>
-
<st c="31019">i</st>``<st c="31021">ndex.html</st> -
<st c="31030">i</st>``<st c="31032">ndex-XXXXXX.css</st> -
<st c="31047">i</st>``<st c="31049">ndex-XXXXXX.js</st> -
你可能已在应用程序中包含的静态文件,例如,图片
之后,在页面底部,点击 按钮 上传 。
测试并探索你的应用
<st c="31625">CloudFrontDistributionUrl</st>
-
进入 CloudFront 控制台 访问 https://console.aws.amazon.com/cloudfront/ 。 -
点击左侧菜单中的 分发 。 -
选择你创建的分发。 -
复制 分发域名 值,来自 详细信息 部分,如 图 4 **.16 所示。

如果你将 URL 复制并粘贴到浏览器中,你应该能够访问你新创建的应用,正如在 图 4 **.17 中所示。

-
状态(未认证) :该组件将通过更改描述和颜色帮助你了解是否已认证。 此外,如果你已认证,它将 高亮显示并展示你当前的 访问令牌。 -
用户 :导航到 用户 页面。 -
管理员 :导航到 管理员 页面。
管理员页面





<st c="35138">admin</st>


用户页面

测试和探索后端
<st c="37792">delete</st>
import json
import boto3
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('recipes')
def lambda_handler(event, context):
try:
recipe_id = event['pathParameters']['recipe_id']
response = table.delete_item(
Key={'id': recipe_id}
)
return {
"statusCode": 200,
"body": json.dumps({"message": "Recipe deleted successfully"})}
except Exception as e:
return {
"statusCode": 500,
"body": json.dumps({"message": f"Error deleting recipe: {e}"})
delete
<st c="38474">recipe_id</st> <st c="38511">delete_item</st>
-
进入 API 网关控制台 并访问 https://console.aws.amazon.com/apigateway 。 -
选择您在 CloudFormation 堆栈参数中指定的 API 名称。 -
选择 API 选项: <st c="38776">[您的</st><st c="38782">API 名称]</st>。 -
点击左侧菜单中的 集成 选项。 -
选择您想要 探索的路由。 -
点击 Lambda 函数 字段中的蓝色箭头。 这将把您重定向到您特定的 Lambda 函数的页面。

-
进入 API 网关 控制台 https://console.aws.amazon.com/apigateway 。 -
选择您在 CloudFormation 堆栈参数中指定的 API 名称。 -
选择 API 选项: <st c="40097">[您的</st><st c="40103">API 名称]</st>。 -
点击左侧菜单中的 授权 选项。

<st c="41284">/auth</st>
<st c="41520">curl</st>
-
执行 <st c="41610">Get</st>请求到 <st c="41629">API_URL/auth</st>端点。 你应该在 <st c="41687">config.tsx</st>文件中看到这个值,但如果你没有它,可以从 输出 选项卡中获取该值,方法是进入 CloudFormation 控制台: <st c="41810">$ c</st><st c="41814">url -i YOUR_API_URL/auth</st> <st c="41839">HTTP/2 200</st> <st c="41850">…</st> <st c="42036">GET</st> method under the <st c="42057">/</st><st c="42058">auth</st> route. -
在 选择一个授权器以查看其详细信息 下拉框中, 选择 CognitoAuthorizer 。 -
点击 附加授权器 。


-
再次执行请求并确认我们收到 <st c="42708">Unauthorized</st>响应: <st c="42730">$ curl -i YOUR_API_URL/auth</st> <st c="42758">HTTP/2 401</st> <st c="42769">…</st> <st c="42819">/auth</st> to require the authorization token and you are trying to perform the request without providing it, you are getting an <st c="42943">Unauthorized</st> response. -
更改请求以包括授权令牌。 要获取授权令牌,按照以下步骤操作: -
在 浏览器中打开你的应用程序。 -
导航到 管理员 控制台。 -
如果你没有进行身份验证,请继续进行 登录过程。 -
在 管理员 页面上,将鼠标悬停在访问令牌上,并复制完整的访问令牌,如 图 4 **.23 所示。
-
<st c="43361">Authorization</st>
$ curl -H "Authorization: YOUR_JWT_TOKEN" -i YOUR_API_URL/auth
HTTP/2 200
…
{"message": "You've passed the authentication token"}
清理
-
清空 桶: -
进入你的 AWS 账户中的 S3 控制台。 -
选择你的前端 S3 桶(桶的名称应以 <st c="44504">frontend-chapter-4-</st>开头,后跟一个 随机字符串)。 -
点击 清空 ;这将 删除桶内的所有内容。
-

-
删除 CloudFormation 堆栈: -
进入你的 AWS 账户中的 CloudFormation 控制台。 -
选择你创建的堆栈。 -
点击 删除 。
-

未来工作
通过媒体内容丰富您的应用程序
用户资料
*

总结
第六章:5
实现一个图像分析器以检测照片的友好度
-
你将构建的内容 – 一个照片 质量分析器 -
你将如何构建它 – 使用无服务器 AWS 服务 -
构建它 – 使用 Terraform 和 Python -
如何改进应用程序 – 使用机器学习、先进的安全功能和自定义 域名
技术要求
场景
要求
功能需求
-
能够识别照片是否足够好,适合用作 头像 -
可与 其他应用程序交互 -
支持 多种照片格式: <st c="3040">.</st>``<st c="3041">png</st>, <st c="3047">.jpeg</st>
非功能性需求
-
高可用性 -
低成本 -
可扩展性 – 每秒最多支持 20 个请求 每秒
数据需求
不得存储任何 个人数据
技术需求
-
必须与多个其他 Python 应用程序集成 -
必须使用 Terraform 来提供 新的基础设施 -
分类算法必须 使用机器学习(ML)
架构模式
<st c="3896">图像识别</st> <st c="3917">图像分类</st>
-
使用预训练的托管解决方案,例如, Amazon Rekognition -
调整托管解决方案,例如,Amazon Rekognition 自定义标签 -
使用无代码解决方案训练模型,例如,Amazon SageMaker Canvas -
手动 在你自己的模型上训练
架构


-
它要求所有消费应用程序都必须访问 AWS 凭证 -
它不允许解析和自定义 响应 -
它不允许 自定义身份验证/授权
AWS 服务
Amazon Rekognition
-
Amazon Rekognition :一种 计算机视觉服务,旨在分析图像和视频,应用于各种用例,如面部分析、物体检测以及 文本识别。 -
Amazon Transcribe :一种 自动语音识别 ( ASR )服务,可以将音频 文件 转换为 文本。 -
Amazon Translate :一种 神经机器翻译服务,可以在 多种语言之间进行翻译。 -
Amazon Comprehend :一种 自然语言处理 ( NLP )服务,可以从非结构化 文本数据中提取见解和关系。 -
Amazon Kendra :一个智能搜索服务,可用于索引和搜索多媒体内容,包括图像 和视频。 -
Amazon Lex :一个用于构建对话界面和聊天机器人的服务,采用自然语言理解和自动 语音识别。 -
Amazon Polly :一个 文本转语音服务,可以将文本转换为 逼真的语音。
-
面部分析 : -
检测并分析图像 和视频中的面部。 。 -
识别面部特征,如性别、年龄范围、情绪和 面部毛发。 -
通过与用户提供的数据集中的面部进行比较,识别和识别面部 。 -
基于淫秽或 挑逗内容,检测图像或视频中的不安全内容。
-
-
物体和 场景检测 : -
检测并标记 图像和视频中的物体、人物、文本、场景和活动。 -
以 高精度识别物体和概念。 -
为检测到的物体 和场景提供边界框。
-
-
文本识别 : -
检测并识别 图像 和视频中的文本。 -
从不同的表面 和方向提取文本内容。
-
-
内容审查 : -
检测并过滤掉 图像和视频中的淫秽或挑逗内容。 。 -
自动标记不当或 冒犯内容。
-
-
易用性 : -
Rekognition 是一个完全托管的服务,这意味着你不需要担心设置和维护底层基础设施或训练模型。 它提供了一个 API 来 分析图像。 -
训练你自己的机器学习模型需要在数据准备、模型架构选择、训练技术和部署策略方面的专业知识。 它涉及显著的学习曲线和实践操作。 它还需要大量的 数据。
-
-
定制化 和控制 : -
Rekognition 提供了预训练的模型。 虽然它提供了一些定制选项,例如创建面部识别的自定义集合,但定制的程度 是有限的。 -
训练你自己的模型允许你对模型架构、训练数据和微调过程拥有完全的控制权。 这使你能够根据特定的应用场景定制模型,并在 专业任务上达到更高的准确性。
-
-
数据隐私 和安全 : -
使用 Rekognition 时,你的数据——在本例中是图像——会被发送到 AWS 进行处理,这可能会引发数据隐私和 安全问题。 -
当训练你自己的模型时,你可以完全控制数据,并确保敏感信息永远不会离开你的环境,从而提供更好的数据隐私 和安全性。
-
-
可扩展性 和性能 : -
Rekognition 是一个高度可扩展的服务,能够处理大量数据和 并发请求。 -
大规模训练和部署你自己的模型可能具有挑战性,因为它需要配置和管理计算资源、优化性能并处理 与基础设施相关的任务。
-
-
成本和 资源管理 : -
Rekognition 遵循按需付费定价模式,你为 API 请求付费。 对于较小的工作负载或 间歇性使用来说,这种方式具有成本效益。 -
训练你自己的模型需要对硬件资源进行前期投资,并且需要持续的成本来管理和维护 基础设施。
-
<st c="11897">.jpeg</st> <st c="11907">.png</st>
Amazon API Gateway 和 AWS Lambda
-
通过认证和授权请求控制对服务的访问 :您可以配置 API 密钥、IAM 角色和其他自定义 认证机制。 -
简化 API 版本管理和生命周期管理 :您可以创建并部署多个版本的 Rekognition 集成 API,并无缝管理版本之间的过渡。 -
实现内置请求限流和速率限制功能 :这有助于保护您的后端服务,例如 Rekognition,免受过多请求的压垮,这可能导致服务中断和 更高的成本。
编写解决方案代码
构建基础设施
<st c="15655">chapter5/code</st> <st c="15712">interact.py</st><st c="15725">lambda.tf</st><st c="15736">apigw.tf</st><st c="15746">badphoto.png</st><st c="15760">goodphoto.jpeg</st>
<st c="15849">apigw.tf</st> <st c="15862">lambda.tf</st>
<st c="16140">main.tf</st> <st c="16237">.tf</st>
<st c="16317">lambda.tf</st> <st c="16382">aws_lambda_function</st> <st c="16453">Detection_Lambda_Function</st>
data "aws_iam_policy" "rekognition_policy" {
arn = <st c="16531">"arn:aws:iam::aws:policy/AmazonRekognitionReadOnlyAccess"</st> }
resource "aws_iam_role_policy_attachment" "codedeploy_service_role_policy_attach" {
role = aws_iam_role.lambda_role.name
policy_arn = "${data.aws_iam_policy.rekognition_policy.arn}"
} <st c="16775">data "archive_file" "zip_the_python_code"</st> {
type = "zip"
source_file = "${path.module}/python/rekognition.py"
output_path = "${path.module}/python/rekognition.zip"
} <st c="16941">resource "aws_lambda_function" "terraform_lambda_func" {</st><st c="16997">filename = "${path.module}/python/rekognition.zip"</st>
<st c="17048">function_name = "Detection_Lambda_Function"</st> role = aws_iam_role.lambda_role.arn
handler = "rekognition.lambda_handler" <st c="17168">runtime = "python3.8"</st> depends_on = [aws_iam_role_policy_attachment.attach_iam_policy_to_iam_role]
}
<st c="17297">lambda.tf</st><st c="17342">Detection_Lambda_Function_Role</st><st c="17411">aws_iam_policy_for_terraform_aws_lambda_role</st> <st c="17460">AmazonRekognitionReadOnlyAccess</st>
<st c="18102">.zip</st><st c="18288">runtime</st>
<st c="18336">apigw.tf</st>
<st c="18564">resource "aws_api_gateway_rest_api" "my_api"</st> {
name = "my-api"
description = "My API Gateway"
endpoint_configuration { <st c="18684">types = ["REGIONAL"]</st> }
} <st c="18709">resource "aws_api_gateway_resource" "root"</st> {
rest_api_id = aws_api_gateway_rest_api.my_api.id
parent_id = aws_api_gateway_rest_api.my_api.root_resource_id <st c="18864">path_part = "friendly"</st> }
前两个<st c="18923">my-api</st>和<st c="18934">root</st><st c="18976">my-api</st><st c="18990">/friendly</st><st c="19063">API_Gateway_URL/friendly</st>
<st c="19144">apigw.tf</st><st c="19162">POST</st><st c="19182">/friendly</st>
resource "aws_api_gateway_method" "proxy" {
rest_api_id = aws_api_gateway_rest_api.my_api.id
resource_id = aws_api_gateway_resource.root.id <st c="19347">http_method = "POST"</st>
<st c="19367">authorization = "NONE"</st> }
resource "aws_api_gateway_integration" "lambda_integration" {
rest_api_id = aws_api_gateway_rest_api.my_api.id
resource_id = aws_api_gateway_resource.root.id
http_method = aws_api_gateway_method.proxy.http_method <st c="19606">integration_http_method = "POST"</st>
<st c="19638">type = "AWS"</st>
<st c="19651">uri = aws_lambda_function.terraform_lambda_func.invoke_arn</st> }
resource "aws_api_gateway_method_response" "proxy" {
rest_api_id = aws_api_gateway_rest_api.my_api.id
resource_id = aws_api_gateway_resource.root.id
http_method = aws_api_gateway_method.proxy.http_method
status_code = "200"
}
resource "aws_api_gateway_integration_response" "proxy" {
rest_api_id = aws_api_gateway_rest_api.my_api.id
resource_id = aws_api_gateway_resource.root.id
http_method = aws_api_gateway_method.proxy.http_method
status_code = aws_api_gateway_method_response.proxy.status_code
depends_on = [
aws_api_gateway_method.proxy,
aws_api_gateway_integration.lambda_integration
]
}
<st c="20403">aws_api_gateway_method</st><st c="20476">aws_api_gateway_integration</st><st c="20554">aws_api_gateway_integration_response</st><st c="20641">aws_api_gateway_method_response</st>
<st c="20805">POST</st>

<st c="21098">apigw.tf</st><st c="21139">apigw_lambda</st>
<st c="21272">chapter5/code</st>
$ terraform apply
<st c="21432">apply</st>
aws_iam_policy.iam_policy_for_lambda: Creation complete after 1s [id=arn:aws:iam::381672823963:policy/aws_iam_policy_for_terraform_aws_lambda_role]
aws_api_gateway_rest_api.my_api: Creation complete after 1s [id=2g9sm87cnd]
aws_iam_role.lambda_role: Creation complete after 1s [id=Detection_Lambda_Function_Role]
aws_api_gateway_resource.root: Creation complete after 1s [id=06421l]
aws_iam_role_policy_attachment.codedeploy_service_role_policy_attach: Creation complete after 1s [id=Detection_Lambda_Function_Role-20240401171553538300000001]
aws_iam_role_policy_attachment.attach_iam_policy_to_iam_role: Creation complete after 1s [id=Detection_Lambda_Function_Role-20240401171553543900000002]
aws_api_gateway_method.proxy: Creation complete after 0s [id=agm-2g9sm87cnd-06421l-POST]
aws_api_gateway_method_response.proxy: Creation complete after 0s [id=agmr-2g9sm87cnd-06421l-POST-200]
aws_lambda_function.terraform_lambda_func: Creation complete after 15s [id=Detection_Lambda_Function]
aws_api_gateway_integration.lambda_integration: Creation complete after 0s [id=agi-2g9sm87cnd-06421l-POST]
aws_lambda_permission.apigw_lambda: Creation complete after 0s [id=AllowExecutionFromAPIGateway]
aws_api_gateway_integration_response.proxy: Creation complete after 0s [id=agir-2g9sm87cnd-06421l-POST-200]
aws_api_gateway_deployment.deployment: Creation complete after 1s [id=g5m5qa] <st c="22887">Apply complete!</st> <st c="22903">Resources: 13 added, 0 changed, 0 destroyed.</st> Outputs: <st c="22957">deployment_invoke_url = "https://2g9sm87cnd.execute-api.us-east-1.amazonaws.com/dev"</st>
理解图像分析代码
<st c="23370">rekognition.py</st> <st c="23413">python</st> <st c="23427">chapter5/code</st>
<st c="23625">DetectFaces</st>
<st c="23750">DetectFaces</st>
rekognition_response = rekognition.detect_faces(
Image=image, Attributes=['ALL']) <st c="23990">if len(rekognition_response['FaceDetails']) != 1:</st> raise ValueError( <st c="24058">'Please upload a picture with only one face'</st>)
smile = rekognition_response['FaceDetails'][0]['Smile']
eyesOpen = rekognition_response['FaceDetails'][0]['EyesOpen']
result = 'Bad Profile Photo' <st c="24252">if smile['Value'] == True and eyesOpen['Value'] == True:</st>
<st c="24355">DetectFaces</st> API also returns a list of emotions identified in the person’s photo. The script is set up to save the list in a variable named <st c="24495">Emotions</st>:
'HAPPY'|'SAD'|'ANGRY'|'CONFUSED'|'DISGUSTED'|'SURPRISED'|'CALM'|
'UNKNOWN'|'FEAR'
<st c="24650">Enhance the script to</st> <st c="24673">take the person’s emotions into consideration before making the final verdict of a good or</st> <st c="24764">bad photo.</st>
<st c="24774">Testing your application</st>
<st c="24799">Congratulations, you have a working photo</st> <st c="24842">identification application in AWS, which identifies if a photo is professional-looking enough for</st> <st c="24940">social media.</st>
*<st c="24953">Figure 5</st>**<st c="24962">.4</st>* <st c="24964">shows what you’ve deployed so far.</st> <st c="25000">An API Gateway endpoint with a</st> `<st c="25031">dev</st>` <st c="25034">stage, configured with a</st> `<st c="25060">/friendly</st>` <st c="25069">resource path that supports the</st> `<st c="25102">POST</st>` <st c="25106">method.</st> <st c="25115">This method invokes a Lambda, written in Python, that calls the Rekognition</st> `<st c="25191">DetectFaces</st>` <st c="25202">API and parses</st> <st c="25218">the results.</st>

<st c="25373">Figure 5.4 – Image analyzer API architecture</st>
<st c="25417">However, you</st> <st c="25430">have not really tested it.</st> <st c="25458">How do you know</st> <st c="25474">it works?</st>
<st c="25483">This application does not have a user interface like the previous ones.</st> <st c="25556">Nonetheless, there are multiple ways to interact with these types of HTTP applications, for example: using a terminal tool, such as</st> `<st c="25688">curl</st>`<st c="25692">, using an application, such as Postman, or using another application, such as a</st> <st c="25773">Python script.</st>
<st c="25787">Start with Postman.</st> <st c="25808">Postman is an API platform for building and using APIs.</st> <st c="25864">If you do not have it installed, install it and</st> <st c="25912">open it.</st>
<st c="25920">Select</st> `<st c="25928">POST</st>` <st c="25932">as the method and paste your previously noted deployment URL, followed by</st> `<st c="26007">/friendly</st>` <st c="26016">at the end of it in the URL field.</st> <st c="26052">Navigate to the body section, select</st> `<st c="26089">raw</st>`<st c="26092">, and paste the</st> <st c="26108">following code:</st>
{ "image": "b64"}
<st c="26141">You are missing images to test this application.</st> <st c="26191">Recall that your Lambda function received an image as an input.</st> <st c="26255">You will find two images in the</st> `<st c="26287">chapter5/code</st>` <st c="26300">folder:</st> `<st c="26309">goodphoto.jpeg</st>` <st c="26323">and</st> `<st c="26328">badphoto.png</st>`<st c="26340">.</st>
<st c="26341">To send images over the wire, the easiest way is to use</st> `<st c="26398">base64</st>` <st c="26404">encoding.</st> <st c="26415">Open your favorite terminal, navigate to where the images are located, and run the</st> `<st c="26498">openssl</st>` <st c="26505">command, replacing the</st> `<st c="26529"><infile></st>` <st c="26537">and</st> `<st c="26542"><outfile></st>` <st c="26551">variables with</st> `<st c="26567">badphoto.png</st>` <st c="26579">and</st> `<st c="26584">badphoto.txt</st>` <st c="26596">respectively.</st> <st c="26611">This command creates a new file named</st> `<st c="26649">badphoto.txt</st>`<st c="26661">. Inside, you will find the</st> `<st c="26689">base64</st>` <st c="26695">representation of</st> <st c="26714">your image:</st>
openssl base64 -A -in
<st c="26771">Go back to</st> <st c="26783">Postman and replace the body with your generated</st> `<st c="26832">base64</st>` <st c="26838">encoding.</st> <st c="26849">Send the request.</st> <st c="26867">The result should look like</st> *<st c="26895">Figure 5</st>**<st c="26903">.5</st>*<st c="26905">. You receive a</st> `<st c="26921">200 OK</st>` <st c="26927">status code, with a</st> `<st c="26948">Bad Profile Photo</st>` <st c="26965">response in</st> <st c="26978">the body.</st>

<st c="27755">Figure 5.5 – Postman configuration</st>
<st c="27789">Do it again, this time with the good photo in the same directory, and observe how the response is different.</st> <st c="27899">You can also do it more times with photos of yourself</st> <st c="27953">or friends.</st>
<st c="27964">However, the initial focus of this project was to be integrated with other applications, many of them Python applications.</st> <st c="28088">Open the</st> `<st c="28097">interact.py</st>` <st c="28108">file located in the</st> `<st c="28129">chapter5/code</st>` <st c="28142">folder.</st>
<st c="28150">In this file, you</st> <st c="28168">will find a Python application that reads two arguments,</st> `<st c="28226">url</st>` <st c="28229">and</st> `<st c="28234">image</st>`<st c="28239">, from the standard input and sends a</st> `<st c="28277">POST</st>` <st c="28281">request to the received URL, with the image encoded in</st> `<st c="28337">base64</st>` <st c="28343">in</st> <st c="28347">the body:</st>
定义 def analyze_image(url, image): 分析图片函数:
使用 `with open(image, 'rb') as image_file:` 打开图片文件:
image_bytes = image_file.read()
data = base64.b64encode(image_bytes).decode("utf8") <st c="28510">payload = {"image": data}</st><st c="28535">response = requests.post(url, json=payload)</st> return response.json()
定义主函数 def main():
尝试:
parser = argparse.ArgumentParser(usage=argparse.SUPPRESS)
parser.add_argument("url", help="你的 API Gateway 的 URL")
parser.add_argument("image", help="你想要分析的本地图片。")
args = parser.parse_args() <st c="28919">chapter5/code</st> 目录,使用以下语法测试此应用。你只需要将<st c="29024">invoke_url</st>替换为你自己的即可。此应用会将图像转换为<st c="29091">base64</st>,因此你无需使用<st c="29136">openssl</st>工具:
$ python3 interact.py <st c="29172">invoke_url</st> goodphoto.jpeg
<st c="29197">这个应用程序</st> <st c="29215">会将响应返回到你的终端窗口。</st> <st c="29261">其他更复杂的应用程序可以直接解析它并基于此做出决策。</st> <st c="29353">例如,当有人尝试上传照片时,可以阻止</st> <st c="29410">上传。</st>
<st c="29421">清理</st>
<st c="29433">如果没有请求,这种架构不会产生任何费用。</st> <st c="29504">所有使用的服务按请求收费,没有预配置成本。</st> <st c="29581">然而,完成使用后删除解决方案是一个良好的实践。</st> <st c="29657">在使用结束后,最好将其删除。</st>
<st c="29666">要删除所有资源,请在</st> `<st c="29729">chapter5/code</st>` <st c="29742">目录中运行以下命令并确认:</st>
$ terraform destroy
<st c="29785">Terraform 会保留其已部署资源的状态文件,并且只会删除它所管理的资源。</st> <st c="29891">如果你有其他手动部署的资源,它们将不会</st> <st c="29973">被删除。</st>
<st c="29984">未来工作</st>
<st c="29996">一本书的章节所能涵盖的内容是有限的。</st> <st c="30045">你的项目工作已涵盖了所有需求。</st> <st c="30093">它会判断照片是否足够专业,但你仍然可以</st> <st c="30168">进一步改善它。</st>
<st c="30179">实现身份验证和授权</st>
<st c="30225">目前,任何人都可以</st> <st c="30247">发现并调用你的 API</st> <st c="30275">网关,以验证他们的照片是否专业。</st> <st c="30333">恶意行为者可以利用这一点,造成</st> <st c="30398">高额费用。</st>
<st c="30409">在前一章中,你已经实现了 Cognito 来管理身份验证和授权。</st> <st c="30511">你可以对这个应用做同样的操作,或者如果你的客户端应用也运行在 AWS 上,你可以将你的 REST API 更改为私有 API。</st> <st c="30652">在这种情况下,你的 API 网关将只能在 VPC 内访问,而不再可以通过互联网访问。</st> <st c="30758">你可以在 AWS 文档中</st> <st c="30771">阅读更多相关内容</st> <st c="30810">,地址为</st> [<st c="30813">https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-private-apis.html</st>](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-private-apis.html)<st c="30902">。</st>
<st c="30903">提升你的安全姿态</st>
<st c="30935">你已经远远超越了</st> <st c="30956">你在</st> *<st c="30988">第二章</st>*<st c="30997">中学到的静态网站。这一章的应用接收用户输入。</st> <st c="31049">这是一个潜在的攻击向量,因为恶意用户可以上传自定义软件以</st> <st c="31137">利用漏洞。</st>
<st c="31161">一种缓解这一问题的方法是将带有安全策略的 WAF 附加到你的 API 网关,并利用其在</st> *<st c="31305">第二章</st>*<st c="31314">中描述的所有安全功能。</st>
<st c="31315">要实现此功能,按照</st> <st c="31344">AWS</st> <st c="31348">文档中的步骤操作:</st> [<st c="31363">https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-control-access-aws-waf.html</st>](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-control-access-aws-waf.html)<st c="31462">。</st>
<st c="31463">实现自定义域名</st>
<st c="31489">你正在通过 AWS 提供的 URL 调用</st> <st c="31506">你的 API。</st> <st c="31550">这个名字并不</st> <st c="31561">适合人类使用。</st>
<st c="31581">要更改此设置,你需要拥有自己的域名并创建</st> <st c="31652">证书。</st>
<st c="31666">在</st> *<st c="31670">第三章</st>*<st c="31679">中,你为负载均衡器做了这个配置。</st> <st c="31715">API Gateway 还支持自定义域名</st> <st c="31761">和证书。</st>
<st c="31778">要实现此功能,按照</st> <st c="31803">AWS</st> <st c="31811">文档中的步骤操作:</st> [<st c="31826">https://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-custom-domains.html</st>](https://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-custom-domains.html)<st c="31913">。</st>
<st c="31914">改进图像分析算法</st>
<st c="31953">目前,你的</st> <st c="31970">算法检测照片中是否有单个人,是否该人眼睛睁开,是否在微笑。</st> <st c="32083">如果你实现了情感功能,那么它也会考虑在内,影响</st> <st c="32176">最终的判断结果。</st>
<st c="32190">然而,考虑一下以下场景:一张全裸并且眼睛睁开、微笑的人物照片。</st> <st c="32299">这是一张看起来专业的照片吗?</st> <st c="32335">你的算法</st> <st c="32350">认为是的。</st>
<st c="32360">你已经用尽了所有有用的</st> `<st c="32401">DetectFaces</st>` <st c="32412">Rekognition API 响应字段。</st> <st c="32446">然而,你可以使用其他 API 来增强</st> <st c="32489">你的解决方案。</st>
<st c="32503">例如,</st> `<st c="32517">DetectModerationLabels</st>` <st c="32539">用于检测图像中是否包含不适当或冒犯性内容。</st> <st c="32602">示例包括明显的裸露、暴力、仇恨符号和毒品。</st> <st c="32671">你可以在 AWS</st> <st c="32701">文档中查看所有支持的内容及如何使用它,</st> [<st c="32749">https://docs.aws.amazon.com/rekognition/latest/dg/procedure-moderate-images.html</st>](https://docs.aws.amazon.com/rekognition/latest/dg/procedure-moderate-images.html)<st c="32829">。</st>
<st c="32830">要实现这一点,你可以根据</st> <st c="32903">你的偏好选择两种不同的方法:</st>
+ <st c="32919">在你现有的 Lambda 上链式调用 API,并将所有结果汇总为</st> <st c="32998">一个决策。</st>
+ <st c="33009">创建一个不同的 API 资源,例如,</st> `<st c="33056">/moderate</st>`<st c="33065">,以及一个不同的 Lambda 函数,并从客户端应用程序中链式调用。</st>
<st c="33155">你的应用程序是同步的。</st> <st c="33189">如果你添加了许多不同的功能来进行图像验证,响应延迟会增加,用户体验将会</st> <st c="33329">受到影响。</st>
<st c="33343">你可以</st> <st c="33352">改变客户端的期望,让他们提交照片后等待稍后的判定结果。</st> <st c="33453">然后,将你的应用程序转变为一个异步处理应用程序,在其中你可以链式处理多个验证,并在</st> <st c="33600">最后提供决策。</st>
<st c="33608">托管你自己的 ML 模型</st>
<st c="33634">如果你</st> <st c="33647">寻找的功能在托管服务中不存在怎么办?</st> <st c="33666">或者,也许它存在,但并未产生你期望的结果。</st> <st c="33719">例如,假设你想要识别照片是否是由一位</st> <st c="33867">专业摄影师拍摄的。</st>
<st c="33893">在这些情况下,你可以训练并托管你自己的</st> <st c="33942">ML 模型。</st>
<st c="33952">正如本章前面简要提到的,训练你自己的 ML 模型需要数据工程、模型训练、选择和</st> <st c="34100">部署策略方面的专业知识。</st>
<st c="34122">如果你已经具备这方面的专业知识,或者如果你想进行练习,可以使用 Amazon SageMaker 创建一个模型,并在新的资源路径中通过 API 网关调用它。</st> <st c="34284">这种集成还</st> <st c="34311">需要一个</st> <st c="34321">Lambda 函数。</st>
<st c="34337">SageMaker 是一个完全</st> <st c="34358">托管的 AWS 服务,旨在简化和优化整个 ML 工作流,从数据准备到 ML 模型的部署和操作。</st>
<st c="34507">总结</st>
<st c="34515">在本章中,你看到了 AI 和 ML 如何帮助你解决传统编程难以解决的问题。</st> <st c="34645">你再次遵循了一种结构化方法来处理项目,从需求开始,检查可重用的资源,最后,进行架构设计。</st>
<st c="34803">这一次,你使用了 Terraform。</st>
<st c="34841">你深入使用 Python 应用逻辑来检索和解析 API 响应。</st> <st c="34929">然后,再次,</st> <st c="34942">用于测试。</st>
<st c="34954">在本章末尾,你有多个可以通过 AWS 文档自行实现的想法,以改进本章项目。</st> <st c="35105">现在,你可以自信地在你的</st> <st c="35163">未来项目中利用 AI/ML。</st>
<st c="35179">在下一章中,你将继续学习有关 ML 系统,这次应用于动态内容翻译。</st> <st c="35304">但这并不是全部;你还将开始你的 CI/CD 工具之旅。</st>
第七章:6
构建内容翻译流水线
-
你将要构建的是——一个多语言的 Web 应用程序,使用 CICD 流水线 -
你将如何构建它——使用 S3、CloudFront、Lambda@Edge、Translate 和 CICD 工具 -
构建它——使用 Terraform 和 Python -
如何改进应用程序——为基础设施采用 CICD,并支持 更多语言
技术要求
场景
需求
功能性需求
-
显示公司 未来的活动 -
能够创建、编辑和 删除事件 -
能够回滚到 先前的版本 -
支持图像 和文本 -
接口必须适应用户的 首选语言
非功能性需求
-
低成本 -
北美地区的低延迟 -
高可用性 -
易于维护
技术需求
-
必须集成 Terraform 代码库 -
必须使用自动化机制进行 内容翻译
架构模式
<st c="3664">内容本地化</st>
<st c="4147">CICD</st>
架构
<st c="4733">i18n</st> <st c="4787">Lambda@Edge</st>
<st c="5799">Lambda@Edge</st>


AWS 服务
Lambda@Edge
-
查看器请求 :当查看器请求 CloudFront 分发的内容时,此事件会触发。 此事件中的 Lambda@Edge 函数可以在请求发送到 源服务器之前修改请求头或请求的对象路径。 -
源请求 :当 CloudFront 需要从源服务器请求内容时,此事件会触发。 此事件中的 Lambda@Edge 函数可以在请求发送到 源服务器之前修改请求头或请求的对象路径。 -
源响应 :当 CloudFront 从源服务器接收到响应时,此事件会触发。 你可以在此事件中使用 Lambda@Edge 函数检查并修改源服务器的响应 ,然后再缓存并返回给 用户。 -
查看器响应 :此事件会在 CloudFront 返回请求的内容给查看器之前触发。 此事件中的 Lambda@Edge 函数可以修改 CloudFront 的响应头或响应体,然后再发送给 查看器。
Amazon Translate
<st c="10750">translation.json</st>
AWS CodePipeline 和 AWS CodeBuild
-
代码仓库 :这是一个开发人员提交代码变更的地方,在你的 情况下是 GitHub。 -
CI 工具 :这些工具编译源代码,运行测试,并生成可部署的软件包。 流行的 CD 工具包括 TravisCI 或 AWS CodeBuild。 -
持续交付工具 :这些工具可以自动检测代码变更,从你的代码仓库中检索最新版本,并执行一系列步骤。 流行的 CD 工具包括 Jenkins、GitHub Actions、 AWS CodePipeline。 -
持续部署工具 :这是一个在应用程序构建和测试后自动化部署的工具,它们实现了蓝绿部署、金丝雀部署等流行的部署策略。 流行的工具包括 AWS CodeDeploy 或 Ansible。
<st c="14476">buildspec.yml</st>
编码解决方案
构建 web 应用程序
<st c="15451">chapter6/code</st>
.
├── app
│ ├── index.css
│ ├── index.html
│ └── translate.py
├── buildspec.yml
├── ch2-files
│ ├── index.css
│ └── index.html
├── cicd.tf
├── dev.tfvars
├── infrastructure.tf
├── lambda
│ ├── lambda.py
│ └── lambda.zip
└── variables.tf
<st c="15772">infrastructure.tf</st>
resource "aws_s3_bucket" "english-bucket" {
bucket = <st c="16266">var.en_bucket_name</st> }
resource "aws_s3_bucket" "spanish-bucket" {
bucket = <st c="16340">var.es_bucket_name</st> }
<st c="16404">dev.tfvars</st>
en_bucket_name = "my-english-assets-bucket"
es_bucket_name = "my-spanish-assets-bucket"
<st c="16720">PriceClass_100</st>
resource "aws_cloudfront_distribution" "s3_distribution" {
origin { domain_name = aws_s3_bucket.english-bucket.bucket_regional_domain_name
origin_access_control_id = aws_cloudfront_origin_access_control.oac.id
origin_id = local.s3_origin_id
}
enabled = true
default_root_object = "index.html"
default_cache_behavior {
allowed_methods = ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"]
cached_methods = ["GET", "HEAD"]
target_origin_id = local.s3_origin_id
<st c="17271">forwarded_values {</st>
<st c="17289">query_string = false</st>
<st c="17310">headers = ["Accept-Language"]</st>
<st c="17340">cookies {</st>
<st c="17350">forward = "none"</st>
<st c="17367">}</st>
<st c="17369">}</st> lambda_function_association {
event_type = "origin-request"
lambda_arn = aws_lambda_function.terraform_lambda_func.qualified_arn
}
viewer_protocol_policy = "allow-all" <st c="17540">min_ttl = 0</st>
<st c="17551">default_ttl = 1</st>
<st c="17567">max_ttl = 1</st> } <st c="17582">price_class = "PriceClass_100"</st> restrictions {
geo_restriction {
restriction_type = "none"
}
}
viewer_certificate {
cloudfront_default_certificate = true
}
}

<st c="19952">lambda.py</st><st c="19974">lambda</st>
import re
def handler(event, context):
request = event['Records'][0]['cf']['request']
viewerCountry = request['headers'].get('accept-language')
if viewerCountry:
countryCode = viewerCountry[0]['value'] <st c="20472">if re.match(r'^es', countryCode):</st><st c="20505">domainName = "my-spanish-assets-bucket.s3.us-east-1.amazona</st><st c="20565">ws.com</st><st c="20572">"</st> request['origin']['s3']['domainName'] = domainName
request['headers']['host'] = [{'key': 'host', 'value': domainName}]
return request
<st c="20957">.tf</st> <st c="21283">apply</st>
构建 CI/CD 管道
<st c="21589">cicd.tf</st> <st c="21727">codepipeline_bucket_name</st> <st c="21778">dev.tfvars</st> <st c="21811">buildspec.yml</st>
<st c="22471">github_repository_url</st> <st c="22505">dev.tfvars</st>
<st c="22677">input_artifacts</st> <st c="22697">output_artifacts</st> <st c="22863">artifact_store</st>
resource "aws_codepipeline" "codepipeline" {
name = "tf-test-pipeline"
role_arn = aws_iam_role.codepipeline_role.arn <st c="23005">a</st><st c="23006">rtifact_store</st> { location = aws_s3_bucket.codepipeline_bucket.bucket
type = "S3"
}
stage { <st c="23096">name = "Source"</st> action {
name = "Source"
category = "Source"
owner = "AWS" <st c="23171">provider = "CodeStarSourceConnection"</st> version = "1" <st c="23223">output_artifacts = ["source_output"]</st> configuration = {
ConnectionArn = aws_codestarconnections_connection.codestar_connection.arn <st c="23353">FullRepositoryId = var.github_repository_url</st>
<st c="23397">BranchName = "main"</st> }
}
}
stage { <st c="23432">name = "Build"</st> action {
name = "Build"
category = "Build"
owner = "AWS" <st c="23504">provider = "CodeBuild"</st><st c="23526">input_artifacts = ["source_output"]</st> output_artifacts = ["build_output"]
version = "1"
configuration = { <st c="23631">ProjectName = "event-website"</st> }
}
}
}
<st c="23986">buildspec</st>
resource "aws_codebuild_project" "translate" {
name = "event-website"
service_role = aws_iam_role.codebuild.arn
artifacts {
type = "CODEPIPELINE"
}
environment { <st c="24169">compute_type = "BUILD_LAMBDA_2GB"</st> image = "aws/codebuild/amazonlinux-x86_64-lambda-standard:python3.12"
type = "LINUX_LAMBDA_CONTAINER"
}
source {
type = "CODEPIPELINE" <st c="24339">buildspec = file("buildspec.yml")</st> }
}
<st c="24382">buildspec.yml</st>
version: 0.2
phases:
build:commands:
- ls
- aws s3 sync . s3://my-english-assets-bucket
- aws s3 sync . s3://my-spanish-assets-bucket
- <st c="24797">python translate.py en es index.html</st>
<st c="24833">- aws s3 cp es-index.html s3://my-spanish-assets-bucket/index.html</st>
<st c="25114">translate.py</st> <st c="25134">app</st>
<st c="25165">s3 sync</st>
<st c="25401">s3 sync</st> <st c="25549">translate.py</st><st c="25617">translate_document</st> <st c="25645">index.html</st>
import boto3
import argparse
parser = argparse.ArgumentParser() <st c="25774">parser.add_argument("SourceLanguageCode")</st>
<st c="25815">parser.add_argument("TargetLanguageCode")</st>
<st c="25857">parser.add_argument("SourceFile")</st> args = parser.parse_args()
translate = boto3.client('translate')
localFile = args.SourceFile
file = open(localFile, "rb")
data = file.read()
file.close() <st c="26047">result = t</st><st c="26057">ranslate.translate_document(</st>
<st c="26086">Document={</st>
<st c="26097">"Content": data,</st>
<st c="26114">"ContentType": "text/html"</st>
<st c="26141">},</st>
<st c="26144">SourceLanguageCode=args.SourceLanguageCode,</st>
<st c="26188">TargetLanguageCode=args.TargetLanguageCode</st>
<st c="26231">)</st> if "TranslatedDocument" in result:
fileName = localFile.split("/")[-1]
tmpfile = f"{args.TargetLanguageCode}-{fileName}"
with open(tmpfile, 'w') as f:
f.write(result["TranslatedDocument"]["Content"].decode('utf-8'))
print("Translated document ", tmpfile)
<st c="26630">app</st> <st c="26665">index.css</st> <st c="26679">index.html</st>
<st c="26932">terraform apply</st>
terraform apply -var-file="dev.tfvars"
<st c="27049">Apply Complete!</st>
-
导航到 CodePipeline 控制台 在 https://us-east-1.console.aws.amazon.com/codesuite/settings/ 。 -
在 设置 中, 选择 连接 。 -
你将会看到 <st c="27347">app-dev-codestar</st>与 待处理 状态连接。 选择它并点击 更新 待处理连接 。 -
在弹出窗口中,选择 安装新应用 ,如 图 6 **.4 所示,然后使用你的 GitHub 凭证登录。

<st c="27821">app-dev-codestar</st>
测试解决方案
<st c="28454">app</st>
$ <st c="28501">ls</st> index.css index.html translate.py
$ <st c="28540">git clone https://github.com/IvoP1/chapter6-repo.git</st> Cloning into 'chapter6-repo'... warning: You appear to have cloned an empty repository. $ <st c="28683">cp index.html index.css translate.py chapter6-repo/</st> $ <st c="28737">cd chapter6-repo</st> $ chapter6-repo git:(main) ✗ <st c="28782">ls</st> index.css index.html translate.py
$ chapter6-repo git:(main) ✗ <st c="28849">git add .</st> $ chapter6-repo git:(main) ✗ <st c="28889">git commit -m "1 version"</st> $ chapter6-repo git:(main) <st c="28941">git push</st> You are pushing to the remote origin at https://github.com/IvoP1/chapter6-repo.git
Enumerating objects: 5, done. Counting objects: 100% (5/5), done. Delta compression using up to 12 threads
Compressing objects: 100% (5/5), done. Writing objects: 100% (5/5), 2.52 KiB | 2.52 MiB/s, done. Total 5 (delta 0), reused 0 (delta 0), pack-reused 0
remote: Validating objects: 100%
To https://github.com/IvoP1/chapter6-repo.git
* [new branch] main -> main
chapter6-repo git:(main)

index.html<st c="31082">index.css</st>
清理工作
<st c="31285">destroy</st>
-
如果 S3 存储桶中有对象,它们无法被删除。 在运行 <st c="31460">terraform destroy</st>命令之前,你必须手动或通过编程方式清空所有存储桶。 有三个存储桶:西班牙语资产、英语资产以及 CodePipeline 工件。 -
Lambda@Edge 函数可能需要几个小时才能删除。 这是 AWS 的一个限制,在他们的文档中通过以下引用进行了强调:“删除函数关联后,等待几个小时,以便 Lambda@Edge 函数副本可以被清理。 之后,你将能够使用 Lambda 控制台、AWS CLI、Lambda API 或 AWS SDK 删除该函数。”( https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/lambda-edge-delete-replicas.html ) 。 -
你在 Terraform 外创建了自己的 GitHub 仓库。 你必须手动删除 它。
<st c="32247">terraform destroy</st>
未来的工作
实现自定义名称
扩展应用功能
为基础设施代码采用 CI/CD
<st c="33664">terraform apply</st>
-
范围访问 :人类操作员只能访问 CI/CD 工具,无法直接访问 基础设施 -
更好的可追溯性 :知道是谁做了 什么,何时做的 -
标准化 :再也不会有“在我机器上能用”的评论
总结
第三部分:高级项目
-
第七章 , 利用机器学习实现聊天机器人 -
第八章 , 构建商业智能应用 -
第九章 , 探索未来工作
第八章:7
使用机器学习实现聊天机器人
-
你将构建的内容 - 一个用于 安排会议 的聊天机器人应用程序 -
你将如何构建它 - 使用 Amazon Lex -
构建它 - 通过 CloudFormation 并使用 AWS 控制台 -
如何改进解决方案 - 使用来自 Amazon Lex 扩展你的聊天机器人功能
技术要求
场景
需求
-
最终用户/会议请求者 :平台的一部分,公开可访问,配有聊天机器人帮助 安排会议。 -
管理员/会议所有者 :通过日历视图管理会议请求并查看已接受的 会议。
这些需求可以被翻译为功能需求、非功能需求和数据需求。
功能需求
在你定义好应用程序的用户角色后,你可以按用户类型细分功能需求:
-
会议请求者:
-
应用程序应公开可用,并且不需要身份验证。
-
响应式设计,以便任何人都可以通过任何设备与应用程序进行互动。
-
你的聊天机器人应能够处理输入中的小错误。
-
理解描述性日期的能力,如“明天”或“下周一”。
-
-
会议拥有者:
-
列出待处理的会议请求,并具有批准或拒绝它们的能力。
-
包括一个显示所有已批准会议的日历,管理员可以在其中进行导航。
-
日历应支持按天、周和月不同的视图。
-
管理员页面应仅通过身份验证访问。
-
发生冲突的会议不应被聊天机器人拒绝;如果提议的时间段已被占用,应用程序应包含一个与会议请求相关的警告标志。
-
列出主要功能或能力是定义功能需求的有效方法,然而,通过视觉表示来补充它们可以显著提升价值并加速开发过程。考虑到这一点,你创建了两个简单的原型:一个是面向终端用户界面的,另一个是面向管理员界面的,如图 7.1 和 7.2 所示:
- /home 看起来是这样的:

图 7.1 – 用户页面的 UI 原型
- /admin 看起来是这样的:

图 7.2 – 管理员页面的 UI 原型
非功能需求
基于你的研究,你发现由于生成性 AI 技术的出现以及专门用于聊天机器人开发的大型语言模型,当前对话式 AI 成为一个热门话题。
对于这个初步项目,你希望通过采用一个易于配置、维护工作量最小的托管服务来启动一个简单的解决方案。
数据需求
-
创建会议 :创建一个 新的会议。 -
获取待定会议请求 :显示待定状态的会议请求列表,供你选择接受或拒绝,并且会警告 待定 的重叠请求。 -
更改会议状态 :将待定会议的状态更改为已接受 或已拒绝。 -
检查时间窗口内的已批准会议 :获取已批准会议的列表,以便将其包含在 你的日历中。
<st c="7256">meeting_example.json</st>
{
"meetingId": "GUID",
"startTime": "time when the meeting starts",
"endTime": "time when the meeting ends",
"duration": "duration of the meeting in minutes",
"attendeeName": "the name of the participant",
"email": "the email of the participant",
"status": "meeting request status",
"date": "meeting date",
"isConflict": "for a meeting request, define if there is any overlap with a pre-accepted meeting"
};
架构模式
架构
-
展示层 :如何托管和提供 前端 -
计算层 :如何集成和执行 业务逻辑 -
数据层 :用于存储和检索 数据 -
聊天机器人层 :负责开发 聊天机器人的层
-
GET /meetings :获取在指定时间窗口内已批准的会议列表 时间窗口 -
GET /pending :获取待处理的会议请求列表 会议请求 -
POST /chatbot :通过发送用户提示与聊天机器人进行交互 用户提示 -
PUT /status :将会议请求的状态更改为批准 或拒绝


AWS 服务
Amazon CloudFront 和 Amazon 简单存储服务(S3)
Amazon DynamoDB
Amazon Cognito、Amazon API Gateway 和 Amazon Lambda
Amazon Lex
-
<st c="13935">AMAZON.FallbackIntent</st>,当无法识别其他意图时将会使用此意图。 -
语句(Utterances) :这些是配置每个意图时需要提供的一个或多个句子,聊天机器人将根据用户输入使用这些语句来识别意图。 例如,按照本章的案例,与“预定会议”意图相关的语句可能如下: -
“我想预定 一个会议” -
“帮我预定 一个会议”
-
-
插槽(Slots) :插槽是 Amazon Lex 需要从用户那里收集的信息,以便成功完成一个意图。 每个插槽都与一个插槽类型相关联,该类型定义了该插槽期望的数据种类。 AWS 已经提供了内置的插槽类型,如数字或日期,但你也可以通过创建自定义插槽类型来扩展它。 根据本章的示例,插槽的例子可以是安排会议所需的任何信息,比如与会者的姓名、日期、 开始时间以及会议的持续时间。
编码解决方案
克隆项目
<st c="15920">chapter7/code</st>
-
<st c="15982">frontend</st>:包含你的前端代码。 -
<st c="16030">platform</st>:包括部署应用主基础设施的 CloudFormation 模板。
解决方案部署
<st c="16259">/platform</st>

-
点击 在 创建堆栈 。 -
在 前提 – 准备模板 部分,选择 选择一个 现有模板 。 -
在 指定模板 部分,选择 上传模板文件 。 -
点击 选择文件 。 -
从 <st c="18127">chapter7/code/platform</st>文件夹中选择模板。 -
点击 下一步 。

接下来,您将被要求配置 CloudFormation 堆栈中的参数。在表 7.2中,您可以找到每个参数的详细解释。
| 参数 | 描述 |
|---|---|
APIName |
这是项目的 API 名称。 |
UserEmail |
这是您希望与用户关联的电子邮件地址。必须是有效的电子邮件地址,因为您稍后将收到临时密码并进行验证。 |
UserPoolName |
这是您为 Cognito 用户池命名的名称。 |
用户名 |
在您的应用中,稍后您将使用此用户名进行登录。 |
表 7.2 – CloudFormation 模板参数
图 7.7 显示了填写完所有参数后,堆栈配置应呈现的样子。所示的值仅为示例,您的值可能会有所不同。

图 7.7 – CloudFormation 中的堆栈参数
您可以点击下一步,继续到最后一页,系统会要求您确认创建 IAM 角色。此通知与将要创建并与每个 Lambda 函数关联的角色有关,以提供与 DynamoDB 表进行交互的最小权限,其中存储了会议数据。
点击提交,然后等待堆栈状态变化为CREATE_COMPLETE,如图 7.8所示。

图 7.8 – CloudFormation 堆栈创建状态
这意味着所有资源已经配置完毕,您现在可以继续操作。
前端配置和部署
现在所有必要的 AWS 服务已被配置完毕,是时候配置前端应用并部署文件了。
导航到…/frontend/src/configs文件夹,您将找到两个文件:
-
<st c="21565">aws-exports.ts</st>:使用来自 Cognito 用户池的数据配置您的应用程序认证。 该文件由四个 配置变量组成: -
<st c="21718">AWS_PROJECT_REGION</st>:部署解决方案的区域 -
<st c="21783">AWS_COGNITO_REGION</st>:Cognito 用户池的区域(与 上一个变量相同) -
<st c="21870">AWS_USER_POOLS_ID</st>:您的用户池的 ID -
<st c="21915">AWS_USER_POOLS_WEB_CLIENT_ID</st>:您的 Cognito 用户池应用程序的客户端 ID
-
-
<st c="21998">configs.tsx</st>:定义应用程序中要使用的 API 的 URL。 configs.tsx文件由一个配置变量组成: <st c="22135">CONFIG_API_URL</st>: API 终端点
-
转到 CloudFormation 控制台 在 https://console.aws.amazon.com/cloudformation/ 。 -
单击 您的堆栈。 -
在右侧菜单中,选择 Outputs 选项卡,如 图 7 **.9 所示。

<st c="23270">aws-exports.ts</st> |
<st c="23285">aws_user_pools_id</st> |
<st c="23303">UserPoolId</st> |
<st c="23314">aws_user_pools_web_client_id</st> |
<st c="23343">ClientId</st> |
|
<st c="23352">configs.tsx</st> |
<st c="23364">API_URL</st> |
<st c="23372">CognitoUserPoolId</st> |
export const API_URL = '[ApiUrl CloudFormation Output]';
export const amplifyConfig = {
aws_project_region: 'AWS Region code where you deployed your application. E.g.: us-west-2',
aws_cognito_region: ' AWS Region code where you deployed your application. E.g.: us-west-2',
aws_user_pools_id: '[UserPoolId CloudFormation Output]',
aws_user_pools_web_client_id: '[ClientId CloudFormation Output]',
};
<st c="24036">构建</st> <st c="24154">npm</st> <st c="24239">构建</st>
$ npm install && npm run build
<st c="24337">根</st> <st c="24359">frontend</st>
<st c="24441">$</st> <st c="24444">pwd</st>
<st c="24447">…/</st>``<st c="24449">chapter7/code/frontend</st>
<st c="24477">过程会生成一个文件夹,其中包含需要上传到我们的 S3 存储桶的文件。</st> <st c="24575">文件夹的名称可能不同,但通常为</st> <st c="24627">或</st><st c="24636">,并且会在</st>
-
首先,你需要找到之前使用 CloudFormation 模板创建的 S3 存储桶。 存储桶的名称应以 <st c="24931">frontend-chapter-7-</st>开头,后跟一串随机字符( 例如, <st c="25003">frontend-chapter-7-XXXXX</st>)。 -
点击存储桶的名称以 打开它。 -
在 S3 存储桶中,找到并点击 上传 按钮。 此操作将使你能够将文件从本地机器传输到 S3 存储桶。 -
点击 <st c="25258">dist</st>文件夹,在你的本地机器上。 选择文件夹中的所有文件并确认(你应该在 <st c="25390">dist</st>文件夹的根目录下看到两个文件: <st c="25403">index.html</st>和 <st c="25418">penguin.png</st>)。 -
接下来,点击 <st c="25471">dist</st>文件夹,在你的本地机器上,选择 <st c="25517">assets</st>文件夹, 并确认。 -
现在你的 S3 上传 窗口应该如下所示: 图 7 **.10 。

图 7.10 – 上传到 S3 的前端文件
请注意,文件名是在构建过程中自动生成的,因此您看到的文件名可能与前面图示中显示的不同。但是,请确保您拥有以下文件:
-
<st c="26152">i</st>``<st c="26154">ndex.html</st> -
<st c="26163">assets/index-XXXXXX.css</st> -
<st c="26187">assets/index-XXXXXX.js</st> -
您可能在应用程序中包含的静态文件,例如图像
- 向下滚动到页面底部并点击Upload。
您现在已经完成了应用程序的部署和配置过程,可以继续进行聊天机器人设置。
Amazon Lex 配置和构建
您已经几乎完成,剩下的唯一步骤是配置您的聊天机器人。大部分配置已经通过 CloudFormation 模板完成,您只需进行 lambda 函数集成,以根据对话执行相应操作。
为了完成这一步,请按照以下步骤操作:
-
转到您部署 CloudFormation 堆栈的区域中的 Amazon Lex 控制台,网址为
console.aws.amazon.com/lexv2/home?。 -
在左侧菜单中,选择Bots。
-
在Bots列表中,选择MeetyBot,如图 7.11所示。

图 7.11 – 选择 Amazon Lex 机器人
- 在Deployment部分,选择Aliases,并点击TestBotAlias,如图 7.12所示。

图 7.12 – Amazon Lex 机器人别名部分
-
从Languages列表中,选择English (US)。
-
在
<st c="27885">bot-function-meety</st>作为 源, <st c="27923">$LATEST</st>作为版本,如 图 7 **.13 所示。 -
点击
保存 。

-
在左侧菜单中,选择 意图 在 英语 ( 美国) **菜单下。 -
点击 BookMeeting 意图。 -
滚动到 完成 部分,并点击切换按钮将其激活。 这样可以确保每次此意图被完成时,Lambda 函数都会被触发。 您可以在 图 7 **.14 中看到预期状态。

-
点击 保存意图 在右下角。 -
选择
构建 在右上角。 您的聊天机器人构建过程应该需要大约两分钟。 等待直到您看到绿色横幅和成功消息,如 图 7 **.15 所示。

测试并探索您的应用程序
-
前往 CloudFront 控制台 在 https://console.aws.amazon.com/cloudformation/ 。 -
选择你在本章中部署的堆栈。
-
转到输出选项卡。
-
点击
<CloudFrontDistributionUrl>值,如图 7.16所示。

图 7.16 – CloudFormation 输出选项卡
这应该会将你重定向到你的应用程序,预计会像图 7.17那样。

图 7.17 – 应用首页
这是用户可以与聊天机器人互动以安排会议的页面。通过点击聊天图标,你将能够启动对话。
如AWS 服务部分中讨论的那样,表达式是预定义在意图中的,用于帮助识别和理解用户的请求。
本章的 CloudFormation 模板创建了一个由三个意图组成的聊天机器人:
-
StartMeety:这是第一个负责欢迎消息的意图。
-
BookMeeting:负责预定会议的意图。
-
FallbackIntent:当无法基于用户输入识别其他意图时触发的默认意图。
探索并自定义你的聊天机器人
要查看每个意图的表达、响应和逻辑,请执行以下操作:
-
进入你部署了 CloudFormation 堆栈的区域的 Amazon Lex 控制台
console.aws.amazon.com/lexv2/home?。 -
在左侧菜单中,选择Bots。
-
选择MeetyBot。
-
在英语(美国)下,点击意图。
你的控制台应该像图 7.18那样。

图 7.18 – Amazon Lex 机器人意图部分
-
点击StartMeety意图。
-
向下滚动到样本话语部分,查看该意图的预定义话语,如图7.19所示。

图 7.19 – Amazon Lex 聊天机器人意图样本话语
这些是当前用于识别 StartMeety 意图的可用话语,但你可以自由添加其他话语或根据需要自定义现有的。更改后,请确保保存该意图并重新构建聊天机器人,正如前一节所述。
对 BookMeeting 意图执行相同的操作。在这种情况下,Amazon Lex 期望不同的样本话语,而且与 StartMeety 意图不同,它还包括五个槽位,这些是实现该意图所需的数据元素:
-
FullName:与会者的姓名
-
MeetingDate:用户希望见面的日期
-
MeetingStime:会议的开始时间
-
MeetingDuration:会议的持续时间,应该是 30 分钟或 60 分钟
-
AttendeeEmail:用户希望用于联系的电子邮件
我们建议花一些时间探索每个槽位以及聊天机器人用来请求它们的提示。如前所述,欢迎根据你的偏好自定义提示和槽位。
在熟悉了聊天机器人的所有配置后,你可以继续并在你的应用程序中开始一次对话以预定会议。
测试你的聊天机器人
配置好你的聊天机器人及其意图后,现在是时候在你的应用程序中测试其行为了:
- 从使用在 StartMeety 意图中定义的某个话语开始,并注意聊天机器人的响应。

图 7.20 – 来自 StartMeety 意图的初始聊天机器人响应
在这里,你可以看到,根据与 StartMeety 意图的某个样本话语匹配的输入,聊天机器人响应了一个欢迎消息,正如在该意图中配置的那样。
在这个例子中,你可以看到聊天机器人识别并确认了该意图,并作出了相应的回复。
接下来,你可以使用 BookMeeting 意图中定义的某个语句进行响应,这样聊天机器人就能 识别该语句。

作为 BookMeeting 意图的一部分,你的聊天机器人被配置为在继续之前进行确认。 在此,用户可以选择继续或取消请求,如 图 7 **.22 所示。

-
确认后,你的意图达到了实现状态,并且根据机器人配置, <st c="36295">bot-function-meety lambda</st>函数被触发。 lambda 函数包含三个 主要操作: -
根据提供的槽值,评估是否有任何已接受的会议可能与提议的会议时间发生冲突。 -
创建会议请求并将其存储在 DynamoDB 表中。 -
向最终用户发送自定义消息,确认 会议请求。
-

-
前往你部署 CloudFormation 堆栈的区域中的 AWS Lambda 控制台 ,网址为 https://console.aws.amazon.com/lambda/ 。 -
在左侧菜单中, 选择 函数 。 -
点击 <st c="37139">bot-function-meety</st>函数。 -
向下滚动至 代码源 部分,你将找到所有包含在此 lambda 函数中的代码。
通过管理员门户管理会议请求

-
在您的应用程序主页上,点击 登录 。 -
填写 用户名 和 密码 字段,输入您收到的电子邮件中的值 并确认。 -
设置一个新密码 并继续。 -
选择您的电子邮件并点击 验证 。您现在将收到一封带有 临时代码 的电子邮件。 -
从您的电子邮件中复制验证码并将其粘贴到 确认表单中。

-
会议日历,显示所有已接受的 会议。 -
待处理会议部分,展示了等待 您操作的会议请求列表。
-
在浏览器中打开一个新标签,访问主页(你可以复制来自 <st c="40274">/admin</st>)的 URL)。 -
尝试在与已接受会议相同的时间段安排一个新会议。 -
刷新 管理员 页面以显示新的 会议请求。

清理
-
清空 S3 存储桶: -
进入你的 AWS 账户中的 S3 控制台。 -
选择你的前端 S3 存储桶(存储桶的名称应以 <st c="41671">frontend-chapter-7-</st>开头,后跟一个 随机字符串)。 -
点击 空 ;这将删除你存储桶中的所有内容。 内容。
-

-
删除 CloudFormation 堆栈: -
在你的 AWS 账户中导航到 CloudFormation 服务控制台,确保你在最初部署时所在的相同区域。 区域。 -
选择你创建的堆栈。 堆栈。 -
点击 删除 ,如 图 7 **.28 所示。
-

未来的工作
扩展你的聊天机器人执行的操作
def check_meeting_slot(prop_date, prop_start, prop_dur):
#check if is there any conflict by querying the dynamoDB table for meeting already accepted at the proposed start time.
-
<st c="44105">min_time</st>: 由管理员定义,接受会议的最早时间。 会议的时间。 -
<st c="44177">max_time</st>: 由管理员定义,接受会议的最晚时间。 会议的时间。
-
会议提议的日期是否为 之前 <st c="44362">min_time</st>。 -
会议结束日期是否为 之后 <st c="44412">max_time</st>。 -
是否存在冲突,如果存在,请查询 DynamoDB 表以获取在提议日期上发生的所有会议,并实现逻辑以考虑提议的时长查找可用的时段。
<st c="44691">check_meeting_slot</st>
def check_meeting_slot(prop_date, prop_start, prop_dur, min_time, max_time):
#future work
<st c="44933">bot-function-meety</st>
多语言支持
为不同的会话维护用户档案
<st c="45609">chatbot-meety</st><st c="45796">sessionId</st>
def lambda_handler(event, context):
…
response = bot.recognize_text(
botId = '${MeetyBot}',
botAliasId='TSTALIASID',
localeId='en_US',
sessionId='your_session_id',
text = user_input
)
…
<st c="46147">your_session_id</st>
总结
第九章:构建商业智能应用程序
在当今的数字时代,企业从各种来源生成大量数据,包括网站、移动应用程序和在线交易。其中一个数据来源是点击流数据,它记录了用户在网站或应用程序上的交互和活动。分析点击流数据可以提供有关用户行为、偏好和痛点的宝贵见解,从而使企业能够量身定制其产品、服务和营销策略,更好地满足客户需求。
在本章中,我们将探讨如何使用原生 AWS 服务构建商业智能应用程序,分析点击流数据。我们将覆盖整个过程,从数据采集和存储到数据转化、查询和可视化。
总结:本章将按以下顺序涵盖以下主题:
-
你将要构建的内容——一个商业智能应用程序
-
你将如何构建它——使用 Glue、Athena 和 QuickSight
-
实际构建过程——通过 CloudFormation 并使用 AWS 控制台
-
如何改进解决方案——自动化 ETL 管道和数据生命周期管理
本章结束时,你将获得使用 AWS 服务分析点击流数据,构建端到端商业智能应用程序的实践经验。
技术要求
要跟随本章内容并实现自己的商业智能应用程序,你需要拥有一个 AWS 账户。此外,本书在 GitHub 的专用文件夹中有一个文件夹,你可以在其中找到所有基础设施部署所需的代码以及本章中将使用的其他文件:github.com/PacktPublishing/AWS-Cloud-Projects/tree/main/chapter8/code。
场景
你是一个电子商务网站的所有者,销售从电子产品到时尚商品等各种产品。你的网站已经运营了几年,并且随着时间的推移,你已经建立了一个相当可观的客户群。然而,你注意到你的转化率(即访问者中完成购买的比例)一直停滞不前,你不确定导致这一趋势的原因。
需求
-
业务分析师 :业务分析师对创建和运行 SQL 查询没有信心,他们寻找更直观的替代方法来探索 数据。 -
技术用户 :技术用户熟悉并擅长使用 SQL,想要能够运行复杂的查询以回答 特定问题。
功能需求
-
从 点击流数据 中提取信息 -
支持地理分析和 用户分布 -
支持按需更新,以获取最新的 信息 -
能够为技术用户运行临时 SQL 查询 的能力 -
具有无限期存储点击流数据的能力 数据
非功能性需求
-
有限的 维护工作量 -
成本效益
架构模式
架构

-
摄取层 :此层将来自各种来源的数据收集并导入到 系统中。 -
处理层 :此层准备、清洗并转换数据 以便进行分析。 -
可视化层 :以一种视觉吸引力强且交互性强的方式展示处理后的数据,供探索 和洞察。 。
<st c="7884">/raw</st> <st c="7941">/results</st>

AWS 服务
如图
亚马逊简单存储服务(S3)
在你的商业智能应用架构中,你需要一个数据存储来持久化大量的对象或事件,你发现 S3 可以成为数据湖的理想基础解决方案。S3 的设计目标是提供高耐久性,耐久性高达 99.999999999%(11 个 9),确保即使在面对意外事件或基础设施故障时,数据依然完整且可访问,同时提供高可用性,保证为分析和报告目的提供可靠的解决方案,这也是数据湖的预期需求。
此外,可扩展性和成本效益被强调为要求的一部分,而 S3 符合这两个原则,因为它可以存储和分析 PB 级的数据,且无需担心容量限制或基础设施配置,通过在需要时自动扩展,采用按需付费模式。
亚马逊 S3 是支持数据湖的最佳选择,你可以通过阅读以下博客了解更多原因:
AWS Glue
AWS Glue 是一个无服务器的数据集成服务,使得数据的发现、准备和结合变得更加容易。在你的商业智能应用架构中,AWS Glue 有两个主要用途:提取、转换和加载(ETL)作业和 Glue 数据目录。
ETL 是数据集成中的关键过程,其中从各种源提取数据,转化为所需的格式,然后加载到数据存储中进行分析或报告;在这种情况下,它被加载到 S3 中。AWS Glue 提供了一个无服务器的 Apache Spark 环境来运行 ETL 作业,无需配置或管理服务器。
AWS Glue ETL 作业具有高度的可扩展性和成本效益,因为您只需为作业执行过程中使用的资源付费。
在您的应用程序中,Glue 数据目录用于维护您的数据源的元数据定义,即基于 S3 构建的数据湖。
Glue 数据目录与其他 AWS 服务无缝集成,例如 Amazon Athena,它是您架构的一部分,使您能够基于
Amazon Athena
它的无服务器方式消除了配置和管理基础设施的需要,让您可以专注于数据分析,而不是
如在
对于在
Amazon QuickSight
编码解决方案
第一部分 – 克隆项目
<st c="13899">chapter8/code</st>
-
<st c="13962">平台</st>:这包含了一个 CloudFormation 模板,用于部署你的应用程序的主要基础设施。 -
<st c="14071">辅助文件</st>:这包含了一组将在整个章节中使用的辅助文件。
第二部分 – 解决方案部署
<st c="14382">/platform</st>
如同在
- 从控制台,前往 CloudFormation 服务
https://console.aws.amazon.com/cloudformation/ 并在右上角选择您希望托管应用程序的 AWS 区域( 俄勒冈州 ,在我们的案例中),如 图 8 **.3 所示。

-
点击
创建堆栈 。 -
在
先决条件 – 准备模板 部分,选择 选择现有模板 。 -
在
指定模板 部分,选择 上传模板文件 。 -
点击
选择文件 。 -
选择模板(
<st c="15622">ch8-application-template.yaml</st>)来自<st c="15664">chapter8/code/platform</st>文件夹。 -
点击
下一步 。
您的

接下来,您将被要求配置 CloudFormation 堆栈中的参数。
<st c="17085">GitRepoURL</st> |
|
<st c="17282">InstanceType</st> |
|
<st c="17426">LatestAmiId</st> |
-
与 AWS Glue 作业关联的 IAM 角色,授予读取和写入文件到 S3 所需的权限 。 -
附加到 EC2 实例的 IAM 角色,在该实例上执行脚本,以提供足够的权限将特定文件复制到您的 S3 桶

第三部分 – 点击流事件生成器
-
前往 CloudShell 控制台 访问 https://console.aws.amazon.com/cloudshell 。 -
这将打开一个新的终端窗口,您可以在其中执行脚本。 如果您没有准备好任何环境,请点击 打开 [AWS-Region] 环境 ,如 图 8 **.6 所示:


图 8.7 – CloudShell 终端窗口
这个新终端将用于运行命令,生成事件并将其发送到你最近创建的 S3 存储桶。
作为部署过程的一部分,我们生成了一个包含所有需要在终端中运行的命令的文件。要访问它,请按照以下步骤操作:
-
前往 S3 控制台,
console.aws.amazon.com/s3。 -
选择你最近创建的 S3 存储桶。它应该被命名为
chapter-8-clickstream-XXXXXXXX。 -
点击
aux文件夹。 -
选择
instructions.txt文件。 -
点击下载,如图 8.8所示。

图 8.8 – instructions.txt 文件访问
-
打开文件。在文件中,你应该能看到三条命令:
git clone GIT_URL_DEFINED_IN_THE_CLOUDFORMATION_PARAMETER cd GIT_NAME/chapter8/code/aux pip install -r requirements.txt这三条命令将在你的 CloudShell 环境中本地克隆 Git 仓库。
-
接下来,导航到
/aux文件夹,那里存放着你的事件模拟器文件(generator.py),然后使用pip安装所有需要的库。 -
从
instructions.txt文件中复制命令,并粘贴到 CloudShell 终端中。 -
运行以下命令:
<st c="21221">/raw</st> folder. Moreover, the script will create one event per second and print it in the console so you can follow along:…
{'event_type': 'search', 'user_id': 'lyttebmihe', 'user_action': 'home_page', 'product_category': None, 'location': '36', 'user_age': 30, 'timestamp': 1714680649}
上传到 S3 的事件:search_lyttebmihe_1714680649.json
{'event_type': 'click', 'user_id': 'oencotfldn', 'user_action': 'cart_page', 'product_category': 'books', 'location': '1', 'user_age': 42, 'timestamp': 1717732343}
上传到 S3 的事件:click_oencotfldn_1717732343.json
超时发生。创建 20 个事件后退出脚本。
<st c="21838">As described before, this script will generate the events and store them in your</st> <st c="21920">S3 bucket.</st>
若要确认文件在你的 S3 存储桶中的持久性,请按照以下步骤操作:
-
前往 S3 控制台,
console.aws.amazon.com/s3。 -
选择你最近创建的 S3 桶。 它应该被命名为 <st c="22128">chapter-8-clickstream-XXXXXXXX</st>。 -
点击 <st c="22173">raw</st>文件夹。 你的 <st c="22190">/raw</st>文件夹应该像 图 8 **.9 一样,包含与生成的总事件数相对应的 JSON 文件。

<st c="23401">$ python3 generator.py</st>
第四部分 – Glue ETL 作业
-
前往 Glue 控制台 ,网址为 https://console.aws.amazon.com/glue 。 -
点击左侧菜单中的 Visual ETL 选项。 -
从 <st c="24009">chapter8-gluejob</st>中点击 运行作业 ,如 图 8 **.10 所示。

-
读取 S3 桶中 <st c="24395">/raw</st>文件夹内的所有事件文件。 -
读取一个包含 地理信息的参考文件。 -
更改每个数据集的架构。 -
将两个数据集 合并为一个。 -
选择一部分列。 -
基于输出数据集,创建一个单一的 <st c="24593">.csv</st>文件。 -
将输出 <st c="24651">.csv</st>文件保存在你的 S3 桶中的 <st c="24686">/</st>``<st c="24687">results</st>文件夹内。 -
将所有点击流事件从 <st c="24744">/raw</st>文件夹移动到 <st c="24763">/</st>``<st c="24764">processed</st>文件夹。 -
要详细查看代码,按照以下步骤操作: -
点击作业 名称( <st c="24856">chapter8-gluejob</st>)。 -
选择 脚本 选项卡并查看 代码。
-
-
要检查作业状态,前往 运行 选项卡,并等待直到 运行状态 变为 成功 ,如图 图 8 **.11 所示:

第五章 – 使用 Athena 进行数据探索
-
访问 Athena 控制台 请前往 https://console.aws.amazon.com/athena 。 -
如果这是你第一次访问 Athena 控制台,你需要进行初始配置。 因此,点击 探索查询编辑器 ,如图 图 8 **.12 所示:

-
前往 设置 选项卡。 -
点击 管理 。 -
选择
浏览 S3 。 -
找到并点击你为此项目创建的 S3 桶(名称应以 “ <st c="26346">chapter-8-clickstream-xxxxxxxx</st>” 为前缀)。 -
选择 <st c="26391">/</st>``<st c="26392">aux</st>文件夹。 -
点击 选择 选择 ,如 图中 8 **.13 所示。

-
切换到 编辑器 选项卡。 -
确保您已选择了 以下设置: -
<st c="27058">AwsDataCatalog</st> -
<st c="27084">clickstream_db</st>
-
-
点击与 clickstream_table相邻的三个点。 -
选择 预览表 ,如 图中 8 **.14 所示。

SELECT * FROM "clickstream_db"."clickstream_table" limit 10;
SELECT continent, COUNT(*) AS total_records
FROM "clickstream_db"."clickstream_table"
GROUP BY continent
ORDER BY total_records DESC;
第六部分 – 使用 QuickSight 进行数据可视化
-
在您的 AWS 控制台搜索栏中, 输入 <st c="28804">QuickSight</st>。 -
你将被重定向到QuickSight门户,并看到一个类似于图 8.15的表单:

图 8.15 – QuickSight 注册表单
-
点击注册 QuickSight。
-
接下来,你需要填写用于通知的电子邮件。你可以使用自己的电子邮件或其他任何你选择的电子邮件。
-
前往 QuickSight 区域选择。从下拉菜单中选择你在本章项目中使用的相同区域,如图 8.16所示:

图 8.16 – QuickSight 区域选择
-
向下滚动,在
chapter8-clickstream-xxx中。 -
向下滚动,在可选附加组件部分,确保你取消勾选添加分页报告复选框,如图 8.17所示:

图 8.17 – QuickSight 分页报告附加组件
重要说明
确保不将分页报告添加到你的订阅中,这对于避免使用本书中未涵盖的功能而产生不必要的费用至关重要。
- 点击完成。
如果一切设置正确,在 QuickSight 门户的左侧菜单中,你应该看到一个包含各种选项的菜单,如图 8.18所示:

图 8.18 – QuickSight 菜单
每当你开始在 QuickSight 中创建任何内容时,第一步是创建一个数据集。所以,让我们从定义你的第一个数据集开始:
-
点击数据集。
-
在右上角,点击新数据集。
-
选择Athena。
-
对于数据源名称,给它一个有意义的名称,例如
clickstream。 -
对于 Athena 工作组,确保 [Primary] 已选择。 -
点击 验证连接 确保一切正常工作。 -
点击 创建 数据源 。 -
在下一个 窗口中,选择 <st c="31425">clickstream_table</st>从表格列表中, 如 图 8 **.19 所示:

-
点击 在 选择 。 -
点击 在 可视化 。 -
当系统提示报告类型时,选择 交互式表单 ,如 图 8 **.20 所示:

-
从 可视化 标签中,点击 + 添加 。 -
选择填充地图,如 图 8 **.21 所示:

从 字段 列表中选择 <st c="32774">country-name</st>。

-
点击地图可视化之外的区域。 -
从 <st c="33315">user_age</st>开始。 请注意,QuickSight 会创建一个只包含单个数字的可视化。 这是因为聚合类型默认设置为 求和 ,因此它正在对所有 用户的年龄进行求和。 -
要更改它,请点击 <st c="33548">user_age</st>字段旁边的三个点,然后在聚合菜单中将其更改为 平均值 ,如 图 8 **.23 中所示:

-
点击 + 添加 并选择 漏斗图 。 -
从数据菜单中, 选择 <st c="34272">event_type</st>。 您的仪表板应如下所示 图 8 **.24 。请随意探索其他可视化类型,重新排列您已有的可视化,并创建您自己的仪表板版本。

-
在右上角,点击 点击 发布 。 -
为您的仪表板命名。 -
点击 发布仪表板 。
-
点击左上角的 QuickSight 图标。
-
从左侧菜单中选择数据集。
-
选择你刚刚创建的数据集。
-
转到刷新标签。
-
点击立即刷新,如图 8.25所示:

图 8.25 – QuickSight 数据集刷新
完成刷新过程后,请执行以下操作:
-
点击左上角的 QuickSight 图标返回初始菜单。
-
从左侧菜单中选择仪表板。
-
选择你刚刚创建的仪表板。
如果你与之前的版本进行对比,你的仪表板应该在视觉效果上显示不同的数值,这正是你刚刚执行的数据更新的结果。
在所有工作流测试完成后,现在是清理资源的时刻,以避免不必要的成本。
第七节 – 清理
第一步是删除你的 QuickSight 订阅,同时你仍然可以享受免费套餐。
重要提示
删除你的 QuickSight 订阅将删除你在 QuickSight 账户中的所有资产。如果你已经在其他项目中使用 QuickSight,你可能想跳过这一步,因为它仅适用于本章中新创建的订阅。
要继续进行 QuickSight 订阅终止,请执行以下步骤:
-
在 QuickSight 账户的右上角,点击用户图标。
-
选择管理 QuickSight。
-
在左侧,选择账户设置。
-
在账户终止下,点击管理。
-
通过点击切换按钮禁用账户保护。
-
在文本框中输入
confirm。 -
点击删除账户。
-
转到您的 S3 控制台。 AWS 账户。 -
选择您的前端 S3 存储桶(桶的名称应以 <st c="37057">chapter-8-clickstream-</st>开头,后跟 随机字符串)。 -
点击 清空 。 这将删除存储桶中的所有内容。

-
转到您的 CloudFormation 控制台。 AWS 账户。 -
选择堆栈 您创建的。 -
点击 删除 。
未来工作
自动化 ETL 管道
数据生命周期管理
总结
第十章:9
探索未来工作
技术要求
AWS 服务概览
容器

-
Amazon Elastic Container Service (ECS) :一项完全托管的容器编排服务,帮助您在 EC2 实例或 Fargate 实例的集群中部署、管理和扩展容器化应用程序。 它支持 Docker 容器,并允许您以大规模运行和管理容器。 它支持 Docker 容器,允许您大规模运行和管理容器。 -
Amazon 弹性 Kubernetes 服务(EKS) :一种托管的 Kubernetes 服务, 简化了在 AWS 上使用 Kubernetes 部署、管理和扩展容器化应用程序的过程。 Kubernetes 是一个开源的容器编排平台,能够自动化容器化应用程序的部署、扩展和管理。 容器化应用程序。
<st c="4415">put_like</st> <st c="4427">get_recipes</st>

其他 API 类型
-
GraphQL 通常会为数据查询暴露一个单一端点,而不是为不同资源设置多个端点。 这简化了 API 接口,并使得 API 的演变变得更加容易 随时间推移。 -
它使用一种强类型查询语言,允许客户端仅请求所需的数据。 这与传统的 REST API 不同,后者通常返回超过客户端需求的数据 量。 -
使用 GraphQL,客户端对接收到的数据有更多控制,从而实现更好的性能和灵活性。 它具有 客户端驱动的架构。 -
GraphQL API 是围绕一个模式构建的,定义了类型、查询、变更以及不同数据实体之间的关系。 该模式充当客户端和服务器之间的契约,确保数据一致性,并使得 强大的工具能够发挥作用。

生成式 AI

<st c="10319">[author]</st><st c="10478">goodphoto.jpeg</st>
<st c="10492">[author]</st> is this a professional looking image – attached
goodphoto.jpeg <st c="10565">[agent-Claude]</st> Yes, this image also appears to be a professional-looking headshot or portrait photograph. It depicts a man with a friendly, smiling expression and neatly groomed facial hair. The background is slightly blurred but seems to be an outdoor setting with a gray or cloudy sky behind him. The lighting is relatively soft and flattering on his face. While a bit more casual with the hooded jacket attire, the framing, expression, and overall quality suggest this was taken with care, likely by a professional photographer or for professional purposes like corporate headshots or a personal branding photo. The image has a polished, high-quality look fitting for professional use.
其他通信模式
异步处理
-
客户端可以发送请求,而无需等待订阅者 处理它们。 -
订阅者可以按 自己的节奏消费消息。 -
如果订阅者端出现故障,另一个订阅者可以继续处理相同的请求。 它不会简单地 丢失。

Fan-out 和广播

事件驱动
AWS 定价计算器
对第二章中的解决方案进行定价
<st c="17772">index.html</st><st c="17784">index.css</st><st c="17799">avatar.png</st>

定价第六章中的解决方案
<st c="20349">index.html</st> <st c="20364">index.css</st>
-
每月 1 TB DTO 到互联网 每月 -
每月 10,000,000 次 HTTP 或 HTTPS 请求 每月
<st c="22045">index.html</st>

AWS re:Post
-
如何创建并激活一个新的 AWS 账户? : https://repost.aws/knowledge-center/create-and-activate-aws-account -
如何排查 API 网关的 HTTP 403 错误? : https://repost.aws/knowledge-center/api-gateway-troubleshoot-403-forbidden -
如何终止我在 AWS 账户上不再需要的活动资源? : https://repost.aws/knowledge-center/terminate-resources-account-closure
AWS 文档、解决方案库和指导性建议
AWS 文档
-
AWS 常见问题: https://aws.amazon.com/faqs/ -
AWS 技术 文档: https://docs.aws.amazon.com/ -
AWS 博客: https://aws.amazon.com/blogs/ -
AWS 新动态: AWS? :https://aws.amazon.com/new/ -
AWS 技能 Builder: https://explore.skillbuilder.aws/learn
AWS 解决方案库
如果您不是负载测试方面的专家,请搜索并导航到
这是一个典型的解决方案库文档。在其中,您将找到三个组件:
-
一个架构图
-
一个实施指南
-
一键部署选项
如图

图 9.9 – 分布式负载测试架构
实施指南,
最后,它包括一个一键部署选项,
AWS 规范指导
与解决方案库不同,并非所有内容都具有实用性,也没有架构图和代码。
有三种类型的资源:
-
策略 :云迁移和现代化的商业视角、方法论和框架,适用于 CxO 和高级经理。 -
指南 :为架构师、经理和 技术负责人提供的规划和实施策略的指导,重点介绍最佳实践和工具。 -
模式 :用于实现常见迁移、优化和现代化场景的步骤、架构、工具和代码,适用于构建者和其他 实践用户。
总结


浙公网安备 33010602011771号