AWS-云项目-全-

AWS 云项目(全)

原文:annas-archive.org/md5/45e4c1dd094b1fc87c70427ee3df9f4d

译者:飞龙

协议:CC BY-NC-SA 4.0

第一章:前言

在不断发展的云计算领域中, 亚马逊网络服务 (AWS) 作为领导者,提供一系列服务,赋予企业和开发者力量。 但对您来说,AWS 不仅是一个技术平台,它还可以是通往蓬勃发展的就业市场的门户。 因此,无论您是雄心勃勃的云工程师、经验丰富的开发人员还是 IT 专业人士,如果您希望在 AWS 上提升自己的技能,这本书都适合您。 这本书是为您而写的。

本书采用项目为重点的方法,每一章都将引导您通过使用 AWS 服务来实现现实场景。从设置基本的基础设施以托管网站到利用服务器无架构计算和机器学习等高级功能来驱动聊天机器人,本书中的项目旨在为您提供解决实际领域挑战所需的技能。 但这还不是全部 – 您还将了解到可以用来实现相同业务目标的替代服务和架构,因为最终关键在于权衡其利弊。

通过本书,您将在实际操作 AWS 能力方面感到自信,并能够构建自己的云项目。 您将成为备受瞩目的 AWS 专家。

本书的读者群体

本书是为希望在云计算领域开启职业生涯的学生和具有其他技术领域(如软件开发)经验但希望拥抱新职业道路或补充其云计算技术技能的专业人士编写的。 如果您是其中之一,这本书适合您。

作为一本实用书籍,建议但不强制要求具备计算机科学或工程背景以及基本的编程技能。 所有项目都附有所使用服务的理论解释,并不假设任何之前的 AWS 知识。

本书涵盖内容

第一章, 部署和与 AWS 服务交互, 解释了使用 AWS 控制台是一个良好的起点,但还有更高级的选项,可以帮助您以可扩展的方式管理资源。 在本章中,您将学习创建和管理 AWS 资源的不同方法。 您还将了解 AWS CLI 和 SDK,并熟悉基础设施 即代码。

第二章创建个人网站,作为第一章实践内容,介绍了你将要构建的项目:一个作为个人简历使用的个人网站。 接下来是解决方案的架构图,并附有如何在你自己的 AWS 账户中一步步构建该网站的指导。 本章最后给出了一些建议,用于改善你所构建的应用程序。

第三章构建食谱分享应用程序,介绍了如何构建一个食谱分享应用程序。 你将学习如何构建动态应用程序,以及如何与数据库进行交互。 本章的结构与前一章相同,首先是对新功能的描述,接着是技术架构,然后是逐步构建和 测试的指导。

第四章构建无服务器食谱分享应用程序,重新构建食谱分享应用程序,但这一次有了不同的实现方式。 与上一章类似,这也是一个动态 Web 应用程序。 然而,这一次,你将只使用无服务器服务。 由于项目的保密性质,你还将加入一个 身份验证机制。

第五章实现图像分析器以检测照片的友好性,讲解了如何在选择个人简历照片之前,向同事寻求反馈,以了解照片的友好程度,那么如果你能够自动完成这个过程呢? 假设每次你上传新照片时,你的应用程序会自动对照片的友好程度进行评分,并建议这张照片是否适合用作专业简历照片。 在本章中,你将使用 AWS 原生的 AI 服务来构建这一功能。

第六章设计内容翻译管道,讲解了可访问性。 你是否曾访问过一个自动将页面翻译成你语言的网页? 可访问性对于触及更广泛的受众非常重要。 在本章中,你将学习如何使用 CI/CD 管道自动将内容翻译成多种语言,并根据用户的 浏览器偏好动态展示翻译内容。

第七章 使用机器学习实现聊天机器人,探讨了聊天机器人的使用。 每个人都听说过 ChatGPT。 在这一章中,你将构建一个虚拟助手,回答与网页开发相关的查询。 这个虚拟助手由最新的机器学习进展提供动力:大型 语言模型。

第八章 构建商业智能应用,解释了如何不仅构建网页应用,还可以构建商业智能解决方案来分析数据并识别趋势。 在这一章中,你将使用 AWS 原生服务来分析点击流数据。 点击流数据是在用户访问网站和应用时收集的。 理解这些数据可以帮助应用拥有者更好地根据目标用户调整内容。 在本章结束时,你将能够轻松查询、转换和可视化多种格式的数据。

第九章 探索未来工作,解释了在 AWS 中,你可以使用超过 200 种服务来为应用提供支持。 与前几章不同,前几章提供了逐步指导来构建应用,而这一章则概述了 AWS 所提供的服务以及加速和支持你的项目创意的策略。 这一章不是实践性的,而是具有启发性的;用它来为你的下一个 大项目进行头脑风暴。

为了充分利用本书内容

你需要一个 AWS 账号才能跟着做。 如果你还没有 AWS 账号,可以按照以下 说明创建一个: https://docs.aws.amazon.com/accounts/latest/reference/manage-acct-creating.html

你还需要在本地机器上安装以下软件。

本书中涵盖的软件/硬件 内容 操作系统要求
AWS CLI 版本 2 Windows、macOS 或 Linux
Terraform 1.9.1
Node.js v18.12.0
npm 1.9.1

尽管示例已在这些版本中进行了测试,但它们也应能在任何更新版本中正常运行。

如果您使用的是本书的数字版,我们建议您自己输入代码或从本书的 GitHub 仓库访问代码(每个章节中都有链接)。 这样做将帮助您避免与复制和粘贴相关的潜在错误。 代码粘贴时可能会出现的错误。

下载示例代码文件

您可以从 GitHub 下载本书的示例代码文件,地址为 https://github.com/PacktPublishing/AWS-Cloud-Projects。如果代码有更新,GitHub 仓库中的代码会及时更新。

我们还有其他代码包,来自我们丰富的图书和视频目录,可通过以下链接获取: https://github.com/PacktPublishing/。快来看看吧!

使用的约定

本书中使用了一些文本约定。

<st c="6918">文本中的代码</st>:表示文本中的代码词汇、数据库表名、文件夹名称、文件名、文件扩展名、路径名、虚拟 URL、用户输入和 Twitter 用户名。 以下是一个示例:“如果您在使用 React 和 i18n,您需要创建 <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

粗体:表示新术语、重要单词或屏幕上显示的单词。 例如,菜单或对话框中的文字会以 粗体显示。以下是一个示例:“在 前提条件 – 准备模板 部分,选择 选择一个 现有模板。”

提示或重要备注

显示如下:

联系我们

我们欢迎来自读者的反馈 ,一直以来都非常欢迎。

一般反馈:如果您对本书的任何部分有疑问,请通过电子邮件联系我们 customercare@packtpub.com 并在邮件的主题中提及书名。

勘误:虽然我们已尽最大努力确保内容的准确性,但仍可能出现错误。 如果您在本书中发现了错误,我们将非常感激您向我们报告。 请访问 www.packtpub.com/support/errata 并填写 表格。

盗版:如果你在网上遇到任何非法复制的我们的作品,任何形式的,请提供给我们相关的位置地址或网站名称,我们将不胜感激。 请通过 copyright@packt.com 与我们联系,并提供该材料的链接。

如果你有兴趣成为作者:如果你在某个领域拥有专长,并且有兴趣写书或为书籍做贡献,请 访问 authors.packtpub.com

分享你的想法

阅读完 AWS 云项目后,我们很想听听你的想法! 点击这里直接进入亚马逊的书评页面 并分享 你的反馈。

你的评价对我们以及技术社区非常重要,它将帮助我们确保提供优质的 内容。

下载本书的免费 PDF 副本

感谢购买 本书!

你喜欢在旅途中阅读,但又不能随时携带纸质书籍吗?

你的电子书购买无法与选择的设备兼容吗?

别担心,现在购买每本 Packt 书籍,你将获得免费的 DRM 无保护 PDF 版本 ,无需额外费用。

随时随地,任何设备上阅读。 直接从你最喜欢的技术书籍中搜索、复制并粘贴代码到 你的应用程序中。

福利还不止这些,你可以获得专属的折扣、新闻通讯以及每天发送到你 邮箱的精彩免费内容。

按照这些简单步骤来获取 福利:

  1. 扫描二维码或访问下面的 链接

https://packt.link/free-ebook/9781835889282

  1. 提交你的购买证明 凭证

  2. 就是这样! 我们会直接将免费的 PDF 和其他福利发送到你的 邮箱

第一部分:初学者级别的项目

第一部分 本书中,您将学习如何使用 AWS 控制台、AWS CLI 和 Terraform 与 AWS 服务进行交互。 接着,您将按照一步步的方式构建一个由 S3 和 CloudFront 提供支持的简单 Web 应用程序。 这些是入门级项目,但它们将帮助您开始自主构建自己的 Web 应用程序。

本部分包括以下章节: 章节:

  • 第一章 部署和与 AWS 服务进行交互

  • 第二章 创建个人网站

第二章:1

部署和与 AWS 服务交互

开始构建解决方案的旅程 亚马逊 Web 服务 (AWS)平台上,需要全面了解可用的工具和方法。 本章介绍了在 AWS 上架构设计的多种方法,从需求收集、服务选择开始, 到绘制架构图。

接下来,你将探索可用于部署和与 AWS 服务交互的各种方法和工具,包括 AWS 控制台、AWS 命令行界面 (CLI),AWS 软件开发工具包 (SDK),以及 基础设施即代码 IaC

这是一个理论章节,围绕以下 主要主题结构:

  • 架构设计 在 AWS 上

  • 开始使用 AWS 控制台

  • 导航 AWS CLI 和 SDK

  • 理解 IaC

在本章结束时,你将掌握创建、操作和监控 AWS 服务的知识和技能,能够根据你的需求和偏好,选择最合适的方法进行操作,无论是通过用户友好的 AWS 控制台、CLI、通过 SDK 的编程访问,还是强大的 IaC 工具。

技术要求

虽然这是一个理论章节,但你将在本章的 GitHub 仓库中找到代码片段 ,链接如下: https://github.com/PacktPublishing/AWS-Cloud-Projects/tree/main/chapter1/code

要跟随学习,你需要一个 AWS 账户。

在 AWS 上架构设计

在 AWS 上架构设计是指 使用 AWS 设计和规划基于云的解决方案的过程。 这包括理解各种 AWS 服务、它们的功能,以及如何将它们结合起来构建可扩展、安全且 具有成本效益的架构。

在 AWS 上架构设计时,应考虑以下四个方面,每个方面将在 本章后续部分详细介绍:

  • 需求收集:这是在 AWS 上架构解决方案过程中的一个关键步骤。 它涉及了解业务需求、功能需求、非功能需求以及将在设计和实现 AWS 架构时起到决定性作用的约束条件。 AWS 架构的设计。

  • 架构模式:AWS 提供了多种架构模式和参考架构,作为常见用例(如 Web 应用、数据处理管道或无服务器架构)的起点。 你可以利用这些模式并根据特定需求对其进行定制。

  • 服务选择:AWS 提供了广泛的服务,包括计算、存储、数据库、网络、分析、机器学习等。 你必须仔细评估应用程序的需求,并选择最适合这些需求的 AWS 服务。

  • 绘图:创建拟议架构的可视化表示是架构过程中的一个关键步骤。 AWS 没有官方工具,但 draw.io 或者仅仅使用 Microsoft PowerPoint 都可以用来创建架构图,这有助于沟通设计、促进协作 并推动实施。

让我们详细了解这些方面

需求收集

明确且定义良好的 需求对架构师设计符合组织特定需求并实现预期结果的 AWS 解决方案至关重要。 需求收集可能涉及与利益相关者的协作、开展研讨会、分析现有系统和数据、以及理解 业务背景。

然而,如果你的项目范围较小,并非所有这些步骤都适用。 尽管如此,在项目开始之前,了解可以收集到的需求类型是很重要的:

  • 业务需求:第一步是理解解决方案背后的业务目标、目标和驱动因素。 这包括目标市场、预期增长、收入模型以及需要考虑的任何特定业务约束或法规。

  • 功能要求:这些要求定义了解决方案必须提供的具体功能、特性和能力。 这可能包括与用户界面、数据处理、与现有系统的集成或特定 业务逻辑相关的要求。

  • 非功能性要求:非功能性要求定义了解决方案必须具备的定性特征,如性能、可扩展性、可用性、安全性和合规性。 这些要求通常在确定适当的 AWS 服务和架构模式时至关重要, 以便使用。

  • 技术要求:技术要求涵盖了需要使用或与 AWS 解决方案集成的具体技术、编程语言、框架和工具。 这可能包括对特定数据库、消息系统或 第三方服务的要求。

  • 数据要求:在 AWS 架构设计中,理解数据要求至关重要。 这包括数据类型(结构化、非结构化或半结构化)、数据量、数据源、数据处理需求,以及任何特定的数据治理或 合规性要求。

  • 集成要求:如果 AWS 解决方案需要与现有的本地系统、第三方服务或其他云环境进行集成,则必须明确定义集成要求。 这包括识别集成点、数据格式、协议和 安全性考虑事项。

  • 安全性和合规性要求:根据行业和所处理数据的性质,可能会有需要在 AWS 架构中解决的特定安全性和合规性要求。 这些可能包括监管标准、数据保护法或 行业特定认证。

  • 财务要求:AWS 提供按需付费定价模式。 了解预算限制和成本要求对于选择合适的 AWS 服务和实现 具有成本效益的架构至关重要。

请记住,一些人将成本或安全性要求视为功能性和非功能性要求的一个范畴。 不要拘泥于命名;只需收集所有 要求。

选择架构模式

架构模式 和参考架构作为设计和实施基于云的解决方案的起点。 这些模式封装了最佳实践、经过验证的设计和根据特定用例和需求量身定制的架构原则。 你可以在 AWS 架构中心 找到许多这样的模式: https://aws.amazon.com/architecture

通过利用 AWS 架构模式和参考架构,你可以在经过验证的设计基础上构建,加速开发过程,并确保你的解决方案符合 AWS 最佳实践和 行业标准。

架构模式解决了常见的场景和需求。 这些包括用于 Web 应用程序、数据处理管道、无服务器架构、微服务、事件驱动架构等的模式。 你可以利用这些模式作为基础,并根据 具体需求进行定制。

除了通用模式外,AWS 还提供了针对特定领域和行业的参考架构,如电子商务、媒体和娱乐、医疗保健、金融服务等。 这些参考架构提供了关于如何使用 AWS 服务和针对 这些领域的最佳实践设计和实施解决方案的详细指导。

要选择一种模式或架构,必须仔细评估解决方案的需求、限制和用例,以选择最合适的架构。 这一选择过程涉及理解每种模式的优缺点、权衡取舍,以及它们与其他技术栈的兼容性。 这通常会在 它们的描述中详细说明。

虽然架构模式提供了一个坚实的起点,但它们很少被照搬使用。 你必须根据具体需求定制和调整这些模式,集成额外的 AWS 服务,调整配置,并考虑安全性、监控和 运营问题。

也有可能你需要的是一个混合或多模式架构。 有些解决方案需要结合多个架构模式,或者采用一种混合方法,结合不同模式的组件。 在有效地集成和协调不同模式为一个统一且可扩展的架构时,存在额外的挑战。 这是一个高级话题,你将在本书的后续章节中进一步了解。 本书。

选择服务

到目前为止,你已经有了一个 明确定义的问题和一个通用的架构模式。 下一步是选择服务。 这是在 AWS 中架构解决方案的一个关键环节。 AWS 提供了超过 200 种服务,拥有大量可以组合的构建模块,用以创建可扩展、安全且 具有成本效益的架构。

服务选择是一个迭代过程,需要在架构最佳实践和各种需求(如非功能性、功能性、成本、安全性等)之间进行平衡。 随着解决方案的发展,新的需求或 约束条件的出现,你必须不断评估和优化服务选择。

服务选择的第一步是将收集到的需求映射到可用的 AWS 服务。 这需要了解每个服务的能力和使用案例,并识别出能够满足解决方案特定功能性、非功能性和技术需求的服务。 为了进行这种映射,你需要首先了解你应该查看的服务类别。 服务被组织为不同的类别,例如计算、存储、数据库、网络、安全、分析等。 在本书的后续章节中,你将看到这些类别中的不同服务。

在确定了符合你需求的服务类别之后,你需要评估不同服务的能力。 每个 AWS 服务都提供一套独特的能力和功能。 例如,如果解决方案需要一个高度可用且可扩展的数据库,像 Amazon RDS 或 Amazon Aurora 这样的服务可能是合适的选择。 随着你在 本书的学习深入, 这一点会变得更加明确。

一些有趣的非功能性能力,你应该考虑的如下: 如下所示:

  • 服务集成:AWS 服务设计上能够无缝协作。 你应该考虑不同服务之间的集成点,并确保所选服务能够有效集成,从而提供 所需的功能。

  • 托管服务与自托管服务:AWS 提供托管服务(由 AWS 处理底层基础设施和维护)和自托管服务(客户有更多控制权,但也承担更多责任)。 您必须根据运营开销、成本以及合规要求等因素评估这两种服务类型之间的权衡。

  • 定价与成本优化:AWS 服务有不同的定价模型,您需要考虑其服务选择的成本影响。 应评估并将成本优化策略(例如利用预留实例、竞价实例或自动扩展)纳入架构设计中。

  • 发展路线图:AWS 服务在不断发展,新的功能和服务会定期发布。 您应考虑所选服务的未来路线图,并确保架构能够适应潜在的变化或新的服务提供。

重要提示

您知道并非所有 AWS 服务在所有地区都可用吗? 没错。 AWS 服务在所有 AWS 地区并非都能统一提供。 因此,您还必须考虑您计划使用的服务的区域可用性。

有时,您可能找不到适合您需求的 AWS 服务,这也是正常的。 这时,第三方服务就显得尤为重要。 如果第三方工具符合您的需求,不要害怕使用它。 不过,请考虑之前提到的各个维度,如成本或服务集成。

架构图绘制

提议架构的可视化表示 有助于传达设计,促进团队成员之间的协作,并确保对解决方案的组件及其相互关系有共同的理解。 它还提供了实施的地图。

目前没有标准工具用于绘制 AWS 解决方案的架构图。 最常用的工具是使用 AWS 架构图标的 PowerPoint(https://aws.amazon.com/architecture/icons/)或 draw.io(https://app.diagrams.net)。 这些工具包括代表不同 AWS 服务的图标和形状。

图 1**.1 展示了一个使用 PowerPoint 绘制的高层次图,展示了两个不同区域 EC2 实例之间的通信流程。

图 1.1 – 跨区域 EC2 通信流程

图 1.1 – 跨区域 EC2 通信流程

图示作为一种通用语言,用于与利益相关者、开发人员、运维团队以及其他相关方沟通架构设计。 你不仅应该表示各种 AWS 服务,还要展示它们之间的关系,以及解决方案中数据和流程的整体流动。 你可以为同一个解决方案创建多个图示,每个图示可以有不同的细节层次。

重要提示

在设计阶段,图示工作并没有结束。 相反,它是架构生命周期中的一个持续过程。 定期更新和审查图示,确保它们准确反映当前的架构状态。

图示是架构文档过程中不可或缺的一部分。 它们作为设计决策、组件交互和所选架构背后理由的参考。 然而,文档并不限于图示。 创建详尽的文档对于未来的维护、故障排除以及团队或组织内的知识传承具有不可估量的价值。 本书不会深入讨论文档内容,因为这是一本专注于 实践构建的书籍。

探索 AWS Well-Architected 框架

AWS 提供了一套最佳 实践和设计原则,统称为 Well-Architected 框架 (WAR),(https://aws.amazon.com/architecture/well-architected/)。 该框架涵盖六个支柱:运营卓越、安全性、可靠性、性能效率、成本优化, 以及可持续性。

云架构师使用该框架来确保他们的解决方案符合 AWS 最佳实践,通常是在解决方案构建完成后,但也可以在设计阶段使用。 尽管 WAR 可以单独作为一章来讲解,我们现在只是希望你了解它,并且看到我们在本书中的项目构建过程中如何引用它。

现在我们已经涵盖了设计和规划阶段,让我们深入探讨实施阶段。 在这个过程中,你将探索多个工具,并获得一些 实践经验。

开始使用 AWS 控制台

AWS 控制台是 AWS 提供的基于 Web 的用户界面,允许用户通过 图形用户 界面 (GUI)来访问和管理各种 AWS 服务和资源。

AWS 控制台旨在用户友好,并且可以通过任何 Web 浏览器访问,允许用户从任何有网络连接的地方管理其 AWS 资源。 它提供了 AWS 服务和资源的可视化展示,使得用户更容易理解和与 AWS 生态系统互动。

使用控制台

在本节中,你将 部署一个 EC2 实例,这是 AWS 的 虚拟机。

要使用控制台,你必须拥有一个 AWS 账户。 AWS 账户的创建过程不在本书的范围内,但你可以在 AWS 网站上找到所有必要的信息,网址为 https://aws.amazon.com/free

重要提示

本书中的每个示例都假设你拥有一个独立的 AWS 账户,该账户不属于 AWS 组织。

让我们开始吧: 让我们开始:

  1. 访问 AWS 控制台的第一步是导航 https://console.aws.amazon.com/

    你将看到一个登录界面,如 图 1**.2所示。

图 1.2 – AWS 控制台登录界面

图 1.2 – AWS 控制台登录界面

  1. 如果你使用的是 根用户,请输入你的用户邮箱和密码。 如果你使用的是 IAM 用户,你还需要输入 12 位数字的 账户 ID。

  2. 成功登录后,你将看到 AWS 控制台主页,如 图 1**.3所示。

图 1.3 – 控制台主页

图 1.3 – 控制台主页

本图需要重点强调的部分如下:

  • 顶部的搜索栏,你可以用它来搜索特定的服务。

  • 当前管理的 AWS 区域显示在右上角;在这种情况下是北弗吉尼亚

  • 当前登录的用户或角色,位于右上角,隐藏在红色框下。

  • 最近访问的部分,如果你之前没有打开过 AWS 控制台,它将是空的。

重要说明

为什么角色和账户 ID 会隐藏在图 1.3中的红色框下?尽管 AWS 账户 ID、用户和角色不被认为是敏感信息,但按照 AWS 最佳实践,公开披露这些信息是不推荐的。

  1. 导航到 EC2 服务控制台。为此,在搜索栏中输入ec2,然后选择EC2,如图 1.4所示。

图 1.4 – 使用 AWS 控制台搜索 EC2 服务

图 1.4 – 使用 AWS 控制台搜索 EC2 服务

  1. 要启动最简单的虚拟机,且不进行任何自定义,请选择启动实例,如图 1.5所示。

图 1.5 – EC2 仪表板

图 1.5 – EC2 仪表板

  1. 在以下菜单中,选择启动一个实例,然后选择继续无密钥对(不推荐),从密钥对名称下拉菜单中选择。最后,再次选择启动实例,这次是在右侧菜单中。

  2. 导航到正在运行的实例。你可以通过选择 EC2 左侧菜单中的“实例”来完成,或者直接访问console.aws.amazon.com/ec2/#Instances。你应该会看到类似于图 1.6的内容:一个正在运行的 EC2 实例,带有一个奇怪的实例 ID 和一些其他属性。

图 1.6 – EC2 实例状态

图 1.6 – EC2 实例状态

这是一个不太实用的实例,因为你无法连接到它。 原因是你没有选择密钥对。 这只是一个简单的演示,展示了 AWS 控制台的工作方式。

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

图 1.7 – 使用 AWS 控制台终止 EC2 实例

图 1.7 – 使用 AWS 控制台终止 EC2 实例

虽然 AWS 控制台是一个方便的管理和排除故障的方式,但你可能已经猜到它的一些缺点。 假设你需要创建一百个,甚至一千个这样的 EC2 实例。 这将需要你花费很长时间,特别是如果你需要配置一些特定的参数,比如你在 上一篇指南中跳过的那些。

AWS 提供了 命令行工具和 SDK,用于程序化访问和自动化 AWS 服务,以解决 这些缺点。

重要提示

不建议使用根凭证在你的 AWS 账户中执行操作。 我们强烈建议你不要将根用户用于日常任务,并遵循适用于 AWS 账户的根用户最佳实践,详细信息可以在 此处找到: https://docs.aws.amazon.com/IAM/latest/UserGuide/root-user-best-practices.html

建议在进入下一节之前,你先多浏览一下 AWS 控制台,熟悉一下它。

导航 AWS CLI 和 AWS SDK

AWS CLI 和 AWS SDK 是用于访问和管理 AWS 服务的编程工具。 在本节中,你将更深入地了解这些工具,并在自己的 环境中执行它们。

AWS CLI

AWS CLI 是 AWS 提供的一个 统一工具,允许你通过命令行与 AWS 服务进行交互和管理,支持 macOS 终端或 Windows 命令提示符等环境。 它提供了一种方便且可编程的方式,帮助自动化和控制各种 AWS 资源 和操作。

它是一个 CLI 工具,因此需要进行安装。 不同操作系统的安装过程有所不同,但 AWS 有详细的文档说明(https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)。 除了独立操作外,它还可以与其他 CLI 脚本或现有的自动化工具集成。 例如,一个涉及多个组件的较大工作流,涉及本地和 远程进程。

使用 AWS CLI

在本节中,你将 像上一节一样创建一个 EC2 实例,这次使用 AWS CLI。

认证与 AWS 控制台的工作方式不同。 AWS CLI 支持多种认证方法,包括 AWS 访问密钥、IAM 角色和外部凭证提供者。 你可以在 AWS 网站上查看有关不同类型安全凭证的所有详细信息: https://docs.aws.amazon.com/IAM/latest/UserGuide/security-creds.html

在本节中,我们将重点讲解 AWS 访问密钥。

如果你使用的是根用户或 IAM 用户,默认情况下,你的用户没有启用访问密钥。 不建议使用根用户。 不过,你可以为其创建访问密钥。 该过程在 AWS 网站上有描述: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_root-user_manage_add-key.html

按照以下步骤创建新的 IAM 用户:

  1. 通过 控制台导航至 IAM(https://us-east-1.console.aws.amazon.com/iam/home?region=us-east-1#/users)。

  2. 选择 创建用户,并为其指定用户名。

  3. 设置权限 菜单中,选择 直接附加策略,然后找到并选择 PowerUserAccess。最后, 点击 下一步

  4. 点击 创建用户

你的用户现在应该出现在用户列表中。 要为此用户创建访问密钥,请按 以下步骤:

  1. 选择你新 创建的用户。

  2. 导航到 安全凭证 标签页,选择 创建 访问密钥

  3. 使用场景 菜单中,选择 命令行界面(CLI),接受确认消息,然后 选择 下一步

  4. 在下一个菜单中,点击 创建 访问密钥

  5. 在离开此页面之前,请记下你的访问和秘密 访问密钥。

AWS 还为所有可能的排列过程提供了详细的文档, 可以在他们的官方网站上查看:

打开你偏好的本地 CLI 工具,并使用你自己的密钥设置以下变量。 这将允许你的终端与 AWS 账户进行交互:

 $ 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 --filters "Name=instance-type,

值=t2.micro" --query "Reservations[].Instances[].InstanceId"

[

"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 describe 命令再次执行以确保实例不再运行。

        <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

创建个人网站

这是你实践经验的开始。 在接下来的章节中,你将沉浸在各种场景中。 在本章的第一个实践部分,你将从一份需求列表中,学习如何为你的简历建立个人网站。 在记住这些需求的基础上,你将通过 第一章 提供的方法,构建一个使用 AWS 服务(如 S3 用于存储和 CloudFront 用于分发)的解决方案。 进行架构设计。

接下来,你将使用 AWS 控制台构建该架构。

总之,本章涵盖了以下主要主题 ,顺序如下:

  • 你将要构建的内容是——一个 个人网站

  • 你将如何构建它——使用 S3 和 CloudFront

  • 实际构建它——使用 AWS 控制台

  • 如何改进解决方案——安全性 和 DNS

到本章结束时,你将能够自信地在 AWS 中创建并托管自己的静态网站。 这是更高级 Web 应用程序的前奏,你将在 接下来的章节中看到它们。

技术要求

为了创建你自己的个人网站,你需要访问一个 AWS 账户。

本章在本书的 GitHub 代码库中有一个专门的文件夹。 在这里,你将找到跟随本章学习所需的代码片段: https://github.com/PacktPublishing/AWS-Cloud-Projects/tree/main/chapter2/code

场景

假设你是一个刚毕业的学生,或者是一个 希望向潜在雇主或客户展示自己技能、经验和成就的专业人士。 你希望创建一个既易于访问又具有专业外观的在线形象,在这里你可以分享你的简历 或履历。

有什么比托管你自己的 个人网站更好的方式呢?

需求

回想一下,在 第一章中,收集 需求是架构 AWS 的第一步。 无论你的场景有多简单或复杂,最好将需求写下来。 这可能听起来有些傻,但花时间描述你需要什么,以及你如何构建它,会在 长期内帮助你。

在这种具体情况下,你想要构建一个简单的东西。 你需要一个提供良好用户体验的网站。 你不希望招聘者看到页面加载缓慢,从而跳过你的页面直接去下一个候选人。 同样,你也不希望招聘者在你的网站不可用时尝试访问它。 为避免这种情况,你需要了解用户的 体验。

简历经常变动。 你可能会学习到新技能,换工作,或者其他原因影响你的简历。 因此,你需要一个简单的机制来更新网站。 最后,由于这是一个个人项目,你必须尽量将成本保持在最低 水平。

所有这些因素都可以转化为功能性和 非功能性需求。

功能性需求

功能性需求 定义了解决方案必须提供的具体特性、功能和能力。 在这种情况下,具体如下: 如以下所示:

  • 能够创建、编辑和更新简历的内容,包括个人信息、教育背景、工作经历、技能, 和项目

  • 支持非文本内容,如 图片

  • 在任何浏览器上都可以访问, 通过互联网

  • 能够 基于 网站数据生成洞察

非功能性需求

非功能性需求定义了解决方案必须提供的 定性属性。 在这种情况下,具体如下: 如以下所示:

  • 低延迟 – 快速的页面 加载时间

  • 高可用性 – 访问时可用 可用性

  • 易于维护性 – 易于更新和修补 网站

  • 低成本 – 便宜的 按需付费服务

现在,你已经有了个人网站的需求。 按照 第一章 的方法论,你现在需要检查已知的 公认模式。

架构模式

AWS 架构中心进行简单搜索(https://aws.amazon.com/architecture/)并未找到任何 参考架构图或示例代码。 然而,它返回了一个 YouTube 系列,其中有一集名为 基础回顾:在 AWS (https://www.youtube.com/watch?v=N0nhkyhaqyw&ab_channel=AmazonWebServices)。

观看它;这是一个很好的 起点。

在 AWS 云环境之外,理解什么是静态网站非常重要。 一个 静态网站 是一种内容已预先构建并作为静态文件(通常是 HTML、CSS 和 JavaScript 文件)提供给用户的网站类型。 静态网站不需要 服务器端处理。

动态网站,另一方面,基于用户请求和其他数据在服务器端生成内容。 你将在接下来的章节中看到并构建这些。

最简单的静态网站示例是将一个单一的 HTML 文件保存在本地桌面,并在浏览器中打开它。 这可以运行;然而,除了你自己之外,没人能访问它。 这就是为什么你需要一个托管平台来托管你的 静态网站。

在构建好 静态文件后,你将文件上传到托管平台,其他人便能通过该平台访问这些文件。 这就是 AWS 和解决方案架构的作用所在。 扮演着角色。

架构

到现在,你已经了解了什么是静态网站,明确了需求,并准备创建一个架构 解决方案。

有两种 可能的选项:

  • 不带 特定服务的图

  • 带有 特定服务的图

遵循正式的流程,您创建一个没有特定服务的图表。 之后,在选择服务时,您可以根据需求将这些不特定的服务与具体服务匹配并替换掉。

例如,您知道自己需要一个 内容分发网络(CDN),因此您应该表示该内容。 之后,如果 Amazon CloudFront 满足您的需求,将无关的 CDN 图标替换为 CloudFront 图标,并放入您的 架构图中。

然而,对于这个简单的场景,并在了解架构模式后,您可以直接跳到一个图表,图表中列出了 AWS 服务。

请记住,您需要一个地方来存储静态文件,并且需要一个机制来使 它们可用。

您的图表应当类似于 图 2**.1:一个三部分组成的图表,包含 Amazon S3、Amazon CloudFront 和 Amazon CloudWatch。 客户端通过 CloudFront 连接,它从 S3 中获取您网站的静态文件。 这两个服务都将指标 发送到 CloudWatch。

图 2.1 – AWS 上的静态网站架构

图 2.1 – AWS 上的静态网站架构

尽管 客户端以计算机图标表示,但它们也可以是其他类型的设备,如手机 或平板电脑。

AWS 服务

该架构仅使用了三个服务。 在这一 节中,您将了解这些服务的功能以及它们如何满足 您的需求。

Amazon 简单存储服务(S3)

Amazon S3 是一个 高度可扩展且耐用的对象存储服务。 S3 具有许多特点。 与我们使用案例相关的特点如下:

  • S3 是一种对象 存储服务,意味着它将数据存储为对象(文件),并将其存放在 桶(目录)中。

  • 设计上具有高可用性,数据会在同一地区内的多个 AWS 可用区之间自动复制,确保即使发生停机或 组件故障,您的数据仍然可以访问。

  • 完全托管的服务;您无需担心管理存储基础设施的操作开销,因为这一切都由 为您处理。

  • 支持版本控制,可以在同一个存储桶中保存对象的多个变体,允许你保存、检索和恢复存储在 桶中的每个对象的每个版本。

  • 高度具有成本效益的存储解决方案,采用按需计费定价和分级 存储类。

将这些陈述与 你的需求关联起来:

  • 你希望存储文件(例如 HTML、CSS 和图像),并希望它们随时可供招聘人员访问。 S3 是 高度可用的。

  • 你希望解决方案容易维护,无需进行操作系统补丁更新和其他繁琐的工作。 S3 是一项 完全托管的服务。

  • 同样,你希望能够轻松更新你的简历,如果犯错,能够回滚到之前的版本。 S3 支持 文件版本控制。

  • 最后,你需要以尽可能低的成本来实现这一点。 S3 提供免费层,只对实际使用量收费,且被认为是一个 具有成本效益的服务。

它符合所有条件,成为存储你 静态文件的理想服务。

你知道 S3 有原生功能可以作为静态网站托管吗? 你可以在 AWS 网站上了解更多 信息,地址是 https://docs.aws.amazon.com/AmazonS3/latest/userguide/WebsiteHosting.html

然而,它 有两个 主要的限制:

  • S3 是一项区域性服务,因此,网站可以通过该桶所在 AWS 区域的特定网站终端访问。

  • 它不 支持 HTTPS。

这引出了下一个服务:CloudFront。 如果你想了解更多关于 S3 的信息,包括免费层的内容,可以阅读 相关文档 ,地址是 https://aws.amazon.com/pm/serv-s3

Amazon CloudFront

Amazon CloudFront 是一项 加速分发静态和动态网页内容的服务,内容包括 <st c="9126">.html</st> <st c="9133">.css</st> <st c="9139">.js</st>和图像文件,传送给你的用户。 它是 Amazon 的 CDN。

CDN 是一个地理上分布的服务器群组,它将内容缓存到靠近最终用户的地方。 简而言之,它的工作方式是,用户在离他们更近的 CloudFront 位置终止连接,然后通过 Amazon 的高速骨干网络完成剩余的传输。 如果你的内容已经在该位置缓存,它会直接返回,而不需要传输到 源服务器。

其一些关键特性如下:

  • 全球分布式:通过在靠近用户的边缘位置缓存静态内容,CloudFront 可以更快速地提供网站文件,从而提高加载速度,带来更好的用户体验。 这一点对互联网连接较慢或位于距离源 S3 存储桶较远地区的用户尤为有益。

  • 高可用且容错:CloudFront 构建在 AWS 高可用且容错的基础设施之上。 边缘位置和基础服务都考虑了冗余和容错设计,最大限度地减少单个 组件故障的影响。

  • 增强的弹性:CloudFront 支持为单个分发配置多个源服务器(例如,Amazon S3 存储桶或 Web 服务器)。 如果主要源服务器不可用,CloudFront 会自动切换到次级或三级源服务器,确保内容持续 交付。

  • 内容交付优化:CloudFront 通过自动压缩文件、最小化数据传输量并支持高级缓存机制(如缓存控制头和查询 字符串转发),来优化静态内容的交付。

再次,将这些特性与 你的需求进行对比:

  • 你需要一种通过互联网在任何设备上都能使用的分发机制。 你不知道用户会在哪里,或者他们可能使用什么类型的设备和带宽限制。 CloudFront 全球分布的特性和 开箱即用的缓存功能,可以让你受益。

  • S3 是高可用的,但你还需要 CDN 高可用。 当你将多个组件串联在一起时,任何一个组件的故障都会影响整个系统。 CloudFront 还通过使用次级源 或存储桶,进一步提高了你的可用性。

  • 最后,成本是一个重要因素。 CloudFront 的定价模型基于传输的数据量和请求次数,并采用按需付费模式。 如果客户端的浏览器支持,CloudFront 会自动压缩你的文件,从而减少 数据传输。

如果你想了解更多关于 CloudFront 的信息,包括免费套餐包含的内容,可以在 AWS 文档中阅读: https://aws.amazon.com/cloudfront

Amazon CloudWatch 指标

Amazon CloudWatch 实时监控你在 AWS 上运行的资源和应用程序。 你可以使用 CloudWatch 收集和追踪指标、日志、事件 和追踪信息。

CloudWatch 拥有许多功能,但在本项目中,我们将只关注 CloudWatch 指标。 CW 指标的一些关键特性如下: 以下是 一些特点:

  • 全面覆盖:它收集来自多个 AWS 服务的指标,包括 Amazon S3 和 Amazon CloudFront,以及其他许多服务。 这种全面的覆盖使你能够从一个集中位置监控和分析整个 AWS 基础设施和应用程序的性能与健康状况。 集中管理。

  • 警报和通知:它支持基于指标阈值或模式创建警报。 当特定条件满足时,这些警报可以触发通知(例如,电子邮件、短信或 AWS Lambda 函数),使你能够主动应对潜在问题或采取 自动化措施。

  • 成本效益:其定价基于接收的指标数量、数据保存期限以及按需付费模式,使你能够随着 AWS 基础设施和应用程序的增长,扩展你的监控工作,而无需承担高额的 前期成本。

对于任何你部署的解决方案,你都需要进行监控。 这意味着你需要知道它是否正常工作,如果没有,你需要知道为什么没有。 即便这是一个简单的包含你简历的网站,你也想知道是否有人在访问它,以及他们的体验如何。 这将满足 根据网站 数据生成洞察的能力 的要求。

CloudWatch 深度集成进 AWS 生态系统。 它会原生显示 CloudFront 和 S3 指标,例如:请求次数、错误率和延迟。 你可以访问这些指标,同时最大限度降低成本。 如果没有访问量,你将 没有费用。

如果你想了解更多关于 CloudWatch 指标的信息,包括免费层包含的内容,可以阅读 AWS 文档: https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/working_with_metrics.html

编码解决方案

恭喜你,你已经设计了一个满足所有需求的架构。 现在是时候构建它了。 在本 章中,你将使用 AWS 控制台,在 北弗吉尼亚 区域构建它。

编辑网站

首先, 在本书的 Git 仓库中下载资源,网址为 https://github.com/PacktPublishing/AWS-Cloud-Projects。你可以通过工作站终端使用 Git 工具下载,或者直接下载 ZIP 文件形式的仓库。 如何使用 Git 和 GitHub 的详细步骤指南超出了本书的范围,但如果你想深入学习这个话题,可以参考本书《精通 Git》,它在 https://www.packtpub.com/product/mastering-git/9781783553754中全面讲解了相关内容。

你会在 <st c="14804">chapter2/code</st> 文件夹中找到三个文件。 在你喜欢的代码编辑器中打开 <st c="14831">index.html</st> 文件。 在那里,你会发现一个标准的 HTML 文件,头部引用了一些样式,HTML 正文包含多个分区,通过标签 <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 ###

如果您不熟悉 HTML,以下是 1,000 英尺的概述:HTML 文件是浏览器读取的文件,用于渲染网页。 它们由<st c="15890">.html</st> <st c="15899">.htm</st> 扩展名表示。 HTML 文档由一系列元素组成,这些元素位于标签之间。 标签通过 <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>

您可以在 w3school 网站上找到关于许多其他标签的文档 ,网址为 https://www.w3schools.com/tags/

然而,如果仅使用纯 HTML,您的网站将不会具有良好的美学效果。 为了直观地展示这一点,请在浏览器中打开 <st c="16485">index.html</st> 文件。 如果您尚未修改它,它将看起来像是 图 2**.2

图 2.2 – index.html 浏览器可视化

图 2.2 – index.html 浏览器可视化

现在,在文本编辑器中打开它,并删除头部中的这些链接标签:

 <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">

刷新您的 浏览器页面。 现在,它将看起来像是 图 2**.3

图 2.3 – 无样式的 index.html 浏览器可视化

图 2.3 – 无样式的 index.html 浏览器可视化

希望你能看出其价值。 HTML 中的样式为元素添加样式,例如颜色、字体、大小等。 HTML 中的所有内容都可以添加样式,甚至是 <st c="20226">div</st> 元素。 重新添加您已删除的五个链接标签。

现在,在文本编辑器中打开名为 <st c="20309">index.css</st> 的文件。 在此代码中,您可以找到为 HTML 文件中每种标签类型指定的字体大小和颜色。 同样,您还可以找到 定位属性:

 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>,只是一个照片文件。 要在 HTML 中插入图片,使用 <st c="21142"><</st>``<st c="21143">img></st> 标签。

现在你已经理解了这三个文件以及它们之间的关系,替换内容为你自己的简历信息和照片。 如果你有信心,也可以修改一些样式。

发布网站

到目前为止,你所做的一切都只是在使用 你的本地工作站。 在本节中,我们将使你的网站 在全球范围内可用。

使用控制台访问你的 AWS 账户,如同在 第一章中所述。 导航到 S3: https://s3.console.aws.amazon.com/s3/home?region=us-east-1#

创建一个桶。 在其配置设置中,给它一个唯一的名称,并保持 阻止所有公共 访问 选中。

进入新创建的 S3 桶,上传之前从书籍 GitHub 仓库下载的三个文件: <st c="21882">index.html</st> <st c="21894">index.css</st>,以及 <st c="21909">avatar.png</st>。如前所述,这些是示例文件,你可以并且应该用你自己的文件替换它们。 如果在本章结束之前你还没有完成这个操作,你将看到一个展示书籍某位 作者简历的网站。

导航到 CloudFront 控制台(https://us-east-1.console.aws.amazon.com/cloudfront/v4/home?region=us-east-1#/distributions),并创建一个 新的分发:

  1. 选择你的桶作为 Origin 域名

  2. Origin 访问 公开 更改为 Origin 访问 控制设置

  3. 创建一个新的 OAC,选择默认选项,并在 Origin 访问控制下选择它。

  4. Web 应用防火墙(WAF) 部分,不启用 安全保护。

  5. 在创建您的分发之前,请仔细阅读所有选项。 注意一些有趣的选项,例如缓存策略、自动压缩对象的能力,以及不同的定价类型。

当您创建 分发时,屏幕顶部将出现一个黄色弹出窗口,如 图 2**.4所示。选择 复制策略,然后选择 前往 S3 存储桶权限以 更新策略

图 2.4 – CloudFront OAC 弹出窗口

图 2.4 – CloudFront OAC 弹出窗口

您将看到您的 S3 存储桶设置。 选择 编辑 存储桶策略 部分下,粘贴您复制的策略,并且 保存。

该策略应如下所示。 它允许 CloudFront 服务访问您存储桶内的资源。 在这种情况下,就是 <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"
                }
            }
        }
    ]
}

返回到您的 CloudFront 分发并记下分发名称。 请注意,CloudFront 分发可能需要一两分钟才能 变得可用。

在末尾附加 <st c="24134">index.html</st> ,并且在您的分发状态显示为 已启用后,使用浏览器打开它。 URL 应具有以下格式;其中突出显示的部分在您的情况下应该不同:

 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>
			![Figure 2.5 – CloudFront distribution status during an update](https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/aws-cld-proj/img/B22051_02_5.jpg)

			<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>
			![Figure 2.6 – CloudFront distribution status after an update](https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/aws-cld-proj/img/B22051_02_6.jpg)

			<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://d1hjtv5xjv873g.cloudfront.net/


			<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>
			![Figure 2.7 – CW metrics graph for CloudFront](https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/aws-cld-proj/img/B22051_02_7.jpg)

			<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>
			![Figure 2.8 – CloudFront default certificate](https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/aws-cld-proj/img/B22051_02_8.jpg)

			<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>
			![Figure 2.9 – Final static website architecture with improvements](https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/aws-cld-proj/img/B22051_02_9.jpg)

			<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>

第二部分:中级项目

第二部分 中,您将继续在 第一部分中学到的内容和构建的项目。然而,本部分的难度有所提升。 您将以一步步的方式构建四个应用,使用的 AWS 服务包括 EC2、Lambda、API Gateway、Rekognition 和 DynamoDB。 到本章结束时,您将能够独立构建自己的分布式 Web 应用。

本部分包括以下章节:

  • 第三章, 构建一个食谱分享应用

  • 第四章, 构建一个无服务器食谱分享应用

  • 第五章 实现图像分析器以检测照片友好性

  • 第六章 构建内容翻译管道

第四章:3

构建一个食谱分享应用程序

一个Web 应用程序 是一个通过互联网可以从 Web 浏览器(如 Google Chrome 或 Mozilla Firefox)访问的软件程序,它可以像 第二章中的示例一样简单并具有信息性,在该示例中,你将简历提供给最终用户,或者包含复杂的业务逻辑和关键数据 管理功能。

Web 应用程序可以分解为两个部分:前端 后端。前端是用户可见的,通常使用 HTML、CSS、JavaScript 和现代框架(如 React.js 或 Vue.js)构建。 后端将处理业务逻辑、身份验证、数据处理及与外部服务和数据库的通信,通常使用 Python、Java 或 C# 等编程语言进行开发。 前端与后端之间的通信通常通过应用程序编程接口 (API)进行,使开发人员能够抽象出复杂性,并高效地在不同应用程序之间重用功能。

在本章中,你将开发一个分享食谱的应用程序,用户可以创建、删除或查看他们的食谱。 此外,你还将实现后端和前端,开发一个功能齐全的 Web 应用程序。

总结来说,本章涵盖以下主题 按顺序:

  • 你将要构建的——一个用于 分享食谱

  • 你将如何构建它——使用 S3 和 CloudFront 构建前端,使用 EC2 托管 API,使用 DynamoDB 存储 你的食谱

  • 构建它——通过 CloudFormation 和使用 AWS 控制台

  • 如何改进解决方案——改进监控和应用日志,强制执行安全协议以访问应用程序,并且 实施身份验证

在本章结束时,你将拥有在 AWS 上构建动态 Web 应用程序的实际经验,利用不同的服务实现特定功能,并理解前端和 后端开发的基础知识。

技术要求

要构建和部署你自己的食谱分享应用程序,你需要访问 AWS 账户,并可选地配置一个域名,如果你希望通过 HTTPS 实现安全通信。 需要提醒的是,正如你在本章中所看到的,我们提供了一个第二种选择,配置为 HTTP,不需要拥有 域名。

此外,本书在其 GitHub 仓库中有一个专门的文件夹,你可以在这里找到必要的代码片段以供跟随 学习: https://github.com/PacktPublishing/AWS-Cloud-Projects/tree/main/chapter3/code

场景

上一章中,你创建了一个个人网站来分享你的简历,这个网站已经在招聘人员中变得非常受欢迎,其他同行也在寻找类似的方式来分享他们的简历。 这对你的职业生涯非常有帮助,你开始思考云技术如何在你的副业和兴趣项目中提供帮助;其中一个与 你的烹饪技能 有关。

你花费大量空闲时间创造食谱和重新发明甜点,通常把它们写在笔记本里。 与此同时,你已经开始在社交媒体上建立自己的个人档案,并且已经有 80 万粉丝,他们对你菜肴的照片作出反应,并向你索要食谱。 由于你的名气越来越大,朋友和家人开始称你为“厨师”,并经常向你请教一些他们曾经尝试过的特定食谱的建议。 过去。

直到现在,你还需要去查找你的食谱笔记本,拍照并分享,但随着时间的推移以及你创作的食谱数量越来越多,这变得越来越难以管理,你需要考虑 一个替代方案。

在熟悉云技术的过程中,你开始寻找替代当前食谱分享方法的方案,用于你的第二个云项目——一个名为食谱 分享应用程序

需求

在我们开始 解答 如何 解决这个问题之前,重要的是要澄清 我们 将要构建什么,并以清晰简洁的需求列表进行结构化,就像我们在 第一章 中介绍的那样,并在 第二章 中举例说明。

在这 个项目中,您希望开发一个食谱分享应用程序,为人们提供一个方便的平台来发现、分享和访问不同的食谱。 与前一章不同,这个应用程序需要处理与食谱管理相关的动态内容。 有不同的关键人物将访问 您的应用程序:

  • 平台管理员:平台所有者,可能希望创建新配方、维护或 删除配方。

  • 终端用户/消费者:使用平台访问特定配方的最终用户,不应具备创建、更改或删除 任何记录的权限。

实际的实施应是应用开发的最后一步,精确和详细的需求收集是定义清晰的 开发计划的关键。

您使用的技术、采用的服务和设计的架构应是您列出以实现 目标的技术和非技术要求的结果。

业务需求

您进行的市场研究后,以及在一周内获得的点赞和评论数量,您得出结论,人们倾向于在星期五和星期六花更多时间烹饪,特别是晚餐时间。 您还分析了用户的地理分布,85%位于美国,12%位于欧洲,其余 3%分布在 全球其他地区。

一家食品配送服务向您提出签署广告合同的要求,但他们只同意在您的应用程序中达到 100,000 活跃用户之后才会给出收入流。 在那之前,您的应用程序将没有收入来源。

根据这些发现和潜在的收入机会,您已经确定了以下关键 业务需求:

  • 在年底之前全球达到 100,000 用户 的目标

  • 增强 在欧洲的存在

  • 在支持增长的同时保持成本效益 且成本不显著

功能需求

您的 应用程序应服务于两个不同的用户群体: 管理员 终端用户。对于最初的项目,您将开始两个不同的页面, <st c="6170">/user</st> 供终端用户使用, <st c="6198">/admin</st> 供管理员使用,以支持这两个 不同的角色。

你还希望通过简洁的用户界面创造无缝体验。 此外,你希望你的应用能够响应式,支持不同的设备,如平板、手机和笔记本电脑。

描述功能需求的一个关键步骤是创建界面原型,如 图 3.1 3.2 3.3

图 3.1 – 用户界面首页原型

图 3.1 – 用户界面首页原型

让我们拆解不同的功能 和接口:

  • <st c="6742">/</st>``<st c="6744">用户</st>

    • 访问 食谱标题列表

    • 能够选择特定食谱并访问所有 详细信息

    • 响应式

图 3.2 – 用户页面 UI 原型

图 3.2 – 用户页面 UI 原型

  • <st c="7061">/</st>``<st c="7063">管理员</st>

    • 访问 食谱标题列表

    • 能够 删除食谱

    • 支持 食谱创建

    • 控制 最大支持的食材、步骤和 食谱数量

    • 响应式

图 3.3 – 管理页面 UI 原型

图 3.3 – 管理页面 UI 原型

非功能性需求

你的 应用需要处理突发访问模式,因为预计的使用量应仅在就餐时间接近时增加。 另外,你计划在未来几个月增加欧洲用户群,因此你需要为全球用户提供服务。 此外,成本效益至关重要,因为你的应用没有收入来源。 总结一下,以下是你需要的: 需求:

  • 全球分发,服务全球用户 分布在全球各地的用户

  • 自动扩展以处理突发 使用模式

  • 成本效益

技术要求

功能需求 部分中所述,您希望支持多设备,因此您的应用需要具备响应式设计,以保持一致且良好的用户体验。 因此,前端您希望选择一个简化响应式设计并加速开发过程的框架。 对于后端,您希望采用 Python 作为编程语言,因为它简单、灵活,并且拥有庞大的库和框架生态系统, 同时支持 AWS SDK。 除了与 AWS 服务的所有交互外,您还需要开发自己的 API,因此您选择了 FastAPI,一个用 Python 构建的现代 Web 框架,旨在高效、用户友好且轻量级。 我们将使用以下技术:

  • 现代前端框架 – React.js

  • 后端编程语言 – Python

  • FastAPI 作为 API 开发框架

数据需求

在您的应用中,您处理食谱数据,有多种方式可以存储它们。 食谱可以作为单独的文档存储,记录或条目之间没有关系。 您不期望对数据进行任何复杂的查询,而是希望实现简单的操作来执行 以下内容:

  • 列出食谱:展示已创建的食谱列表。

  • 删除一个食谱:如果管理员不再希望某个特定的食谱成为组合的一部分,应当能够删除该条目。

  • 创建一个食谱:创建一个新的食谱与 用户分享。

另外,您希望实现一个高度可扩展的数据存储,要求最低或无维护工作,理想情况下是一个管理服务。 作为您食谱文档的结构,您设计了 <st c="9671">recipe_example.json</st>

 {   "ID":"GUID",
   "Title":"recipe title",
   "Ingredients":[…],
   "Steps":[…] }

考虑到每个食谱包含 10 个步骤和 10 个材料,您得出每个食谱大约为 1 KB 的结论。 在读取操作方面,假设在高峰时段有 20,000 个并发用户 ,您将有 20,000 个并发读取操作,并且您希望确保即使在 高峰时段也能保持性能的一致性。

架构模式

AWS 架构中心提供了一个由 AWS 合作伙伴的云架构专家精心编制的全面资源集合,包含经过测试和推荐的解决方案,可以作为起点。 对于这个项目,AWS 提供了一种完全适用于你的场景的架构模式: 将基于 React 的单页面应用部署到 Amazon S3 和 CloudFront (https://docs.aws.amazon.com/prescriptive-guidance/latest/patterns/deploy-a-react-based-single-page-application-to-amazon-s3-and-cloudfront.html). 阅读这些推荐的指南将帮助你了解你将要遵循的过程。

要深入了解每个 AWS 服务,AWS 文档可能是最好的信息来源。 每个服务都有自己的文档,强烈建议你查看并通读它,以掌握从基础到更高级的概念。 此外,理解 AWS 在你项目中的角色也很重要。 AWS 将为你提供支持、托管,并帮助你满足需求,但基本的网页开发知识是必不可少的。 在进行实现之前,了解与你的应用架构相关的一些关键概念是至关重要的。 例如,你应该能够 回答以下问题:

  • 什么是 单页面应用 (SPA),它与传统的 网页应用有何不同?

  • API 在你的应用中扮演什么角色? 为什么你 需要一个 API?

第一个问题,a SPA 是一个加载单一 HTML 页面并在用户与应用互动时动态更新该页面的网页应用。 与传统的多页面应用不同,后者每次用户操作都需要从服务器加载一个新页面,SPA 初始时会加载所有必要的 HTML、CSS 和 JavaScript 文件,后续的交互通过 JavaScript 和对 服务器的请求无缝进行。

确保你能够回答剩下的问题,在跳入 AWS 之前建立扎实的知识基础。

架构

到目前为止, 你应该已经熟悉了将要使用的技术,并且你可能已经在本地实现了一个小的概念验证。 下一步是创建一个架构图,以支持你的项目。 图 3**.4 是一个抽象图,参考了组成完整架构的主要层次,是进行 架构设计的一个良好起点。

图 3.4 – 抽象架构

图 3.4 – 抽象架构

最终用户与展示层交互,以获取前端应用程序,并向计算层发出请求,但永远不会直接访问数据层。 相反,计算层负责通过 API 执行数据操作。

设计 API 非常关键,以确保你使用正确的模型来执行所有需要的数据操作,同时还应考虑数据和功能要求。 图 3**.5 展示了基于 所做分析的初步 API 结构。

图 3.5 – API 结构

图 3.5 – 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 EC2 实现,计划将 API 部署在此处。 对于数据层,在考虑所有要求之后,你最终选择了 Amazon DynamoDB 作为数据存储。 为了简化,你将把计算层和数据层合并成一个名为后台的单一层,最终,你的架构图应如下所示 图 3**.6

图 3.6 – 用于食谱共享应用程序的 AWS 架构

图 3.6 – 用于食谱共享应用程序的 AWS 架构

建立高层架构后,让我们更深入地探讨你选择的具体 AWS 服务,了解它们如何与之前定义的需求对齐。

AWS 服务

截至本文撰写时,AWS 提供了 200 多种服务,支持不同的用途,并且管理层级各异。 选择 AWS 服务是一个重要的过程,选择应由预先定义的需求驱动,而不是相反。 在这一章节中,你将探索你解决方案中采用的服务,并了解它们如何与已定义的需求对齐。 部分服务内容已经在前几章中覆盖过。 因此,为避免内容重复,我们将简要提及当前用例的优势,并引用可以找到详细解释的章节。

Amazon S3

你的 前端是一个使用 React.js 构建的 SPA,它会被转化为静态文件,如 HTML、CSS 和 JavaScript,应当将这些文件视为对象。 第二章所述,S3 是 AWS 提供的一个可扩展、高可用且持久的对象存储服务,是托管静态网站的成本效益高的解决方案, 包括 SPA。

重要提示

S3 设计时保证了 11 个 9 的数据耐久性。 这意味着,如果你在 S3 存储 10,000 个对象,你可以预期每 1000 万年因硬件故障或其他潜在数据丢失原因,最多丢失一个对象。

如果你想深入了解 Amazon S3 架构,推荐观看 AWS re:Invent 2023 - 深入了解 Amazon S3 的会议: https://www.youtube.com/watch?v=sYDJYqvNeXU

Amazon CloudFront

如果你计划让 你的应用程序全球服务用户,并希望确保使用 HTTPS 协议进行安全访问,而 S3 不支持此协议。 这只是将 CloudFront 纳入架构的众多原因之一,若要了解服务的详细解释及其优势,建议查看 AWS 服务 章节中的内容: 第二章

Amazon 虚拟私有云(VPC)

Amazon VPC 允许 你在 AWS 云中创建一个逻辑隔离的虚拟网络。 它使你能够定义一个虚拟网络环境,在其中启动和 管理 AWS 资源,如 Amazon 弹性计算云 (EC2) 实例,以安全和受控的方式。 作为 VPC 配置的一部分,你可以定义带有多个子网的网络拓扑,这些子网可以是公共的或私有的,意味着分别具有或不具有互联网访问权限,以便隔离流量并增强 安全性。

Amazon EC2

技术要求来看,你决定开发自己的 API,现在你需要一个服务来部署和托管它。 Amazon EC2 允许你在 VPC 内配置虚拟机(实例)来运行你的应用程序,或者在此情况下,运行你的 API。 EC2 提供了多种实例类型,具有不同的 CPU、内存、存储和网络容量配置,允许你选择适合特定应用程序需求的实例类型,确保最佳性能 和成本效益。

EC2 提供了不同的定价模型,如果你对需求有清晰的了解,可以带来额外的成本效益,同时还提供按需选项,采用纯粹的按量付费模式,这正是你为 此项目选择的。

如果你想了解 更多关于 EC2 定价模型及其工作原理的信息,你可以在 AWS 文档中阅读: https://docs.aws.amazon.com/whitepapers/latest/how-aws-pricing-works/amazon-ec2.html

应用程序负载均衡器 (ALB)

ALB 是一个 完全托管的负载均衡 解决方案,旨在将流量分配到多个目标,具体来说就是 EC2 实例。 作为一个托管解决方案,它在设计上具有高度的可扩展性,并根据流量负载自动进行扩展。 此外,根据你的需求,ALB 带来了两个 主要优势:

  • 健康检查:每个 负载均衡器都需要至少一个目标组,你可以为目标配置健康检查,以确保流量只发送到健康的目标,避免不良的用户体验,并提高应用程序的弹性和容错能力。 你的应用程序。

  • SSL 终止:ALB 支持 SSL 终止,卸载加密和解密的计算负担,减轻你的 EC2 实例的负担。

ALB 还 与 AWS Web 应用防火墙无缝集成,这为防范常见攻击提供了额外的安全保护,例如 SQL 注入, 跨站脚本攻击 (XSS),以及其他网页 应用漏洞。

亚马逊 DynamoDB

选择你的数据库解决方案应根据你的数据和需求来决定。 对于这个项目,你需要将食谱存储为单独的文档。 此外,你已经定义了关于查询一致性和高性能的需求,即使在多个并发的 查询操作下。

亚马逊 DynamoDB 是一种完全 托管的 NoSQL 数据库服务,更具体地说,是一种键值和文档存储,它在任何规模下都能提供单毫秒级的性能。 通过选择 DynamoDB,你将利用其天生的高可用性,因为底层的数据复制采用按需付费模式并自动扩展,以处理突发的工作负载,就像 你的应用程序的情况。

重要提示

DynamoDB 本质上是一个分布式服务,但即使你需要高一致性,这也不应成为障碍。 DynamoDB 提供两种一致性模型:最终一致性(默认)和强一致性。 使用最后一种选项,你可以确保高一致性和数据完整性,确保返回的数据始终是最新的。

如果你想了解更多关于 DynamoDB 的故事、10 周年后的经验教训以及未来计划,查看这篇来自 Amazon Science: https://www.amazon.science/latest-news/amazons-dynamodb-10-years-later

AWS CloudFormation

第一章中,我们简要介绍了 AWS CloudFormation 作为配置基础设施的工具,但考虑到这是它首次被广泛使用的章节,我们将进一步深入讲解并详细说明 它。

CloudFormation 是一个 基础设施即代码 (IaC) 服务,允许你以声明性方式定义并配置 AWS 资源,这些资源通过模板文档来描述,模板可以用 YAML 或 JSON 编写。 像所有 IaC 工具一样,CloudFormation 支持基础设施生命周期自动化,从创建、更新到删除。 它支持漂移检测,用于识别可能在模板外部进行的更改,这些更改可能导致不一致。 不建议手动更改由 CloudFormation 管理的资源,因为这可能导致配置漂移,即资源的实际状态与 模板中定义的状态不符。

CloudFormation 的一个主要优势是它能够将资源管理和配置作为一个单一的单元,称为栈。 该栈可以包含来自各种 AWS 服务的资源,如 EC2 实例、VPC、S3 存储桶等。 CloudFormation 会根据 模板中定义的依赖关系,负责按正确的顺序创建和配置这些资源。

编码解决方案

到目前为止, 你应该已经牢固掌握了所使用的核心服务、选择这些服务的原因,最重要的是,如何使这些服务与你的需求相符合。 你现在终于可以进行 实际的实施了。

克隆项目

如果你正在 跟随前几章的内容,你应该已经克隆了与本书相关的代码库,但如果你是刚刚开始,可以先克隆该仓库,或者选择将代码库作为一个 ZIP 文件 下载。 该仓库的结构是以每章一个文件夹为单位的,本章的所有代码位于 <st c="22055">chapter3/code</st>

<st c="22081">chapter3/code</st> 文件夹内,你将找到三个子文件夹,如 图 3**.7所示:

  • <st c="22159">frontend</st>:此处包含 你的前端代码

  • <st c="22210">backend</st>:此处包含 你的 API 代码

  • <st c="22256">platform</st>:此处包含两个不同的 CloudFormation 模板,用于部署 你的应用程序的主要基础设施。

图 3.7 – 第三章文件夹结构

图 3.7 – 第三章 文件夹结构

为什么有两个不同的 模板可供选择?

SPA 有两种连接方式:一种是通过 CloudFront 获取前端资源,另一种是通过浏览器中的 JavaScript API 请求与后台进行通信,如下图所示: 图 3**.6

虽然 CloudFront 会自动提供 HTTPS 来交付前端资源,但您的 API 需要额外的配置。 为了使用 HTTPS 保护 API,您需要拥有一个域名并申请证书以 证明所有权。

我们理解您现在可能没有域名,或者不想购买域名,这不应该成为部署应用程序的障碍,因此我们已为您提供解决方案!

我们为本节设计了两种不同的选项,因此在 <st c="23227">平台</st> 文件夹中有两个不同的模板。 下表将选项与模板进行映射,帮助您选择 正确的路径:

描述 CloudFormation 模板 推荐
选项 1 您要么拥有一个域名,要么愿意购买一个域名来配置与 您的 API 的 HTTPS 通信 <st c="23498">ch3-https-complete.yaml</st>
选项 2 您希望在没有拥有或购买域名的情况下测试应用程序 一个域名 <st c="23606">ch3-http.yaml</st>

表 3.1 – CloudFormation 模板与您选择的选项之间的映射

关于 HTTP 和 HTTPS 之间差异的详细解释超出了本书的范围,但如果您想了解更多,您可以阅读以下 文章: https://aws.amazon.com/compare/the-difference-between-https-and-http/

您遵循的步骤取决于您选择的选项。 为了简化过程,选项 1 的特定步骤将标记为 (仅适用于选项 1),选项 2 的步骤将标记为 (仅适用于选项 2)。没有任何标记的步骤适用于两种选项。 请注意,即使选择了选项 2,建议阅读选项 1 的 HTTPS 配置步骤,以获取 更多知识。

重要说明

虽然此应用程序和 CloudFormation 模板旨在适用于任何 AWS 区域,但如果选择选项 1,则必须使用相同的区域来创建证书并部署解决方案。 这是因为选项 1 需要使用 AWS 证书管理器创建证书,而这是一个 区域性服务。

第一部分 – DNS 配置和证书签发(仅适用于选项 1)

配置 HTTPS,您需要拥有一个域名,并通过获取证书来证明所有权,本节将介绍如何配置您的 DNS 服务并为 您的域名签发证书。

域名是通过域名注册商购买的,注册商管理互联网域名的预定和注册。 在 AWS 中,Route 53 可以同时作为您的域名注册商,用于 购买域名,以及作为 DNS 服务来管理它们。 此外,您还可以选择流行的第三方注册商,如 GoDaddy 或 Namecheap 等,来购买 您的域名。

Route 53 中的 DNS 配置

在本 示例中,我们刚从第三方提供商那里购买了一个域名,并将演示如何在 Route 53 中为外部购买的域名设置 DNS 管理

在控制台中,通过在搜索栏输入 <st c="25559">route 53</st> ,如 图 3**.8所示,或者你也可以通过以下 链接直接访问: https://console.aws.amazon.com/route53

图 3.8 – 控制台访问 Route 53 服务

图 3.8 – 控制台访问 Route 53 服务

在 Route 53 控制台的左侧面板中,执行以下操作:

  1. 点击 托管区域

  2. 然后,点击 创建 托管区域

  3. 填写 <st c="25967">awscloudprojects.site</st>

  4. 选择 公共托管区域 作为 类型。

  5. 点击 创建 托管区域

您的配置窗口应该如下所示 图 3**.9,除了 域名 字段

图 3.9 – Route 53 托管区域创建表单

图 3.9 – Route 53 托管区域创建表单

如果你 返回到 托管区域 菜单,你应该能够看到你的域名列出。 要访问与你的托管区域关联的名称服务器,请按照 以下步骤操作:

  1. 点击你创建的域名。

  2. 请注意相关的名称服务器,因为你将需要它们来配置 DNS。

你应该在你的托管区域详情中看到四个名称服务器值,如 图 3**.10所示:

图 3.10 – 托管区域详情

图 3.10 – 托管区域详情

以下步骤涉及更新你域名的名称服务器,具体步骤可能会根据你的域名注册商而有所不同。 无论你的注册商是谁,AWS 都提供了与流行 注册商配置名称服务器的逐步指南: https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/migrate-dns-domain-in-use.html

重要提示

一个 托管区域 在 Amazon Route 53 中是一个容器,保存特定域名及其子域的所有 DNS 记录和路由配置。 它允许你根据定义的 路由策略管理和路由流量到你的 AWS 资源或外部资源。

证书颁发

你现在将继续 使用 AWS 证书管理器 (ACM) 服务进行证书颁发过程。 在控制台中,转到 ACM 服务 ,地址为 https://console.aws.amazon.com/acm

图 3.11 – 控制台访问 ACM 服务

图 3.11 – 控制台访问 ACM 服务

要为你的域名颁发证书,你需要按照 以下步骤操作:

  1. 点击 请求一个 证书 按钮。

  2. 证书类型 屏幕上,选择 请求公共证书 选项,点击 下一步

  3. 在表单中填写必要的信息。大多数字段可以保留默认值,但对于app.example.comapi.example.com等,您可能需要进行调整。

  4. *.example.com

  5. 确保验证方法设置为DNS 验证,这是 AWS 推荐的方式。

  6. 点击请求

图 3.12展示了表单的最终状态,包含所有必要字段。

图 3.12 – 证书请求表单

图 3.12 – 证书请求表单

在请求证书后,您将看到它的状态为待验证。要验证证书并证明域名所有权,您需要在您的托管区域创建一个 DNS 记录。

如果您的域名由 Route 53 管理,您可以点击创建 Route 53 记录,如图 3.13所示,这样可以更轻松地进行设置。

图 3.13 – 使用 DNS 记录验证证书

图 3.13 – 使用 DNS 记录验证证书

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

图 3.14 – ACM 证书列表

图 3.14 – ACM 证书列表

最后一步是记下certificateARN,您需要在 CloudFormation 模板中作为参数输入它:

  1. 导航到您创建证书所在区域的 ACM 控制台。

  2. 从左侧面板中选择证书列表

  3. 定位到您的“已颁发”证书,如图 3.14所示。

  4. 点击证书,在 证书状态下,你将 找到 ARN

图 3.15 – 证书 ARN 访问

图 3.15 – 证书 ARN 访问

重要说明

在 AWS 中,ARN 是 AWS 服务的唯一标识符。 它遵循以下 格式: <st c="31982">arn:partition:service:region:account-id:resource-type/resource-id</st>

第二部分 – 解决方案部署

现在,你将使用 CloudFormation 模板来部署支持你的应用程序的基础设施,包括前端和后端,模板文件位于 <st c="32233">chapter3/code</st> 文件夹中。 根据你选择的选项,选择不同的模板,它将创建不同的组件,正如你在 下表中看到的那样。

选项 1(配置了 HTTPS 选项 2(配置了 HTTP
模板 <st c="32465">ch3-https-complete.yaml</st> <st c="32489">ch3-http.yaml</st>
前端 CloudFront 和 S3 CloudFront 和 S3
后端
  • 1 VPC

  • 2 公共子网

  • 2 私有子网

  • 1 私有 EC2 实例

  • 1 ALB

  • 1 NAT 网关

  • EC2 实例角色,具有与 DynamoDB 交互的最小权限 食谱表

|

  • 1 VPC

  • 1 公共子网

  • 1 公共 EC2 实例

  • EC2 实例角色,具有与 DynamoDB 交互的最小权限 食谱表

|

数据存储 DynamoDB DynamoDB

表 3.2 – 每个 CloudFormation 模板的资源创建

从控制台,进入 CloudFormation 服务,网址为 https://console.aws.amazon.com/cloudformation/。如果你选择了选项 1,请确保在控制台右上角的下拉区域列表中选择与你为证书选择的相同区域,如 图 3**.16所示。

图 3.16 – 控制台访问 CloudFormation

图 3.16 – 控制台访问 CloudFormation

要继续堆栈创建,请按照以下步骤操作:

  1. 点击创建堆栈

  2. 先决条件 – 准备模板部分,选择选择一个现有模板

  3. 指定模板部分,选择上传模板文件

  4. 点击选择文件

  5. 根据您所遵循的选项,从chapter3/code/platform文件夹中选择模板。

  6. 点击下一步

您的创建堆栈窗口应如下所示图 3.17

图 3.17 – CloudFormation 创建堆栈表单

图 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> 代码仓库的 URL(例如, https://github.com/packtpublishing/aws-cloud-projects)。
<st c="35633">ALBCertificateArn</st> 你刚刚创建的证书的 ARN。

表 3.3 – CloudFormation 模板参数

图 3**.18中,你 可以看到预期状态的示例,其中 <st c="35907">ALBCertificateArn</st> 不存在。

图 3.18 – CloudFormation 中的堆栈参数

图 3.18 – CloudFormation 中的堆栈参数

继续操作,确认已创建 <st c="36639">IAMPolicy</st> 用于控制 API 访问 DynamoDB 表,并 点击 提交

图 3.19 – CloudFormation 堆栈提交

图 3.19 – CloudFormation 堆栈提交

你的应用程序的资源现在正在被配置。 你需要等待,直到堆栈状态更改为 CREATE_COMPLETE。你应该能够看到类似于 图 3**.20的状态。

图 3.20 – CloudFormation 堆栈创建状态

图 3.20 – CloudFormation 堆栈创建状态

在我们的例子中, 堆栈部署大约花了 10 分钟,但请注意,这 可能会有所不同。

第三部分 – 附加配置(仅选项 1)

快完成了! 你只需要进行一个附加配置,就能让你的应用运行起来,那就是在托管区中创建一个指向 ALB 的子域记录。 这还将启用一个友好的 API 名称,例如 <st c="37914">api.<your_domain></st>。按照以下步骤操作:

  1. 前往 Route 53 控制台。

  2. 选择你的域名的 托管区。

  3. 点击 创建记录

  4. 进入 <st c="38129">api</st>).

  5. 对于 记录类型,选择 A - IPv4 地址

  6. 点击 记录名称 下的切换按钮 启用 别名

  7. 将流量路由到 下拉菜单中,选择 应用程序和经典的别名 负载均衡器

  8. 选择你的应用程序 部署的 AWS 区域。

  9. 选择负载均衡器 部分,选择与你的 CloudFormation 堆栈关联的 ALB。

  10. 如果 你在所选区域有多个负载均衡器,你可以通过检查 CloudFormation 堆栈的输出 部分来找到正确的负载均衡器 DNS 名称,在 CloudFormation 控制台中查看。

  11. 点击 创建记录 按钮保存 新记录。

你的记录创建表单应该像 图 3**.21

图 3.21 – 你的 ALB 的 Route 53 别名记录

图 3.21 – 你的 ALB 的 Route 53 别名记录

在进入下一部分之前,记下你创建的 DNS 记录,因为你将在 下一部分使用它。

第四部分 – 前端配置与部署

CloudFormation 堆栈已经部署了前端所需的服务,唯一剩下的步骤是将应用程序文件复制到 S3\。 但在此之前,你需要修改一些应用程序中的配置。 由于 React 开发不是本书的主要内容,我们已经创建了包含参数的配置文件,以便定制 你的应用程序。

导航到项目文件夹中的 <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 端点

图 3.22 – 配置文件示例 (config.tsx)

图 3.22 – 配置文件示例 (config.tsx)

除了 <st c="40955">API_URL</st> 之外,所有配置项都是可选的,仅用于应用程序的微小定制,因此我们现在将重点关注 API 端点的配置。 <st c="41092">API_URL</st>,顾名思义,是用于发送请求的端点,根据您选择的选项,您需要从 不同的位置获取此值。

选项 1 的解决方案

在此选项中,您现在应该已经为您的 ALB 创建了 Route 53 记录,并且这是您应该为 <st c="41427">API_URL</st> 参数使用的值。

例如,在我们的案例中,按照 图 3**.22,我们创建了一个 <st c="41506">api.awscloudprojects.site</st> 记录,因此 <st c="41543">API_URL</st> 应设置为 <st c="41568">https://api.awscloudprojects.site</st> (不要忘记包含 协议部分)

选项 2 的解决方案

如果您选择这个选项,这意味着您没有为您的 API 创建 DNS 记录,也没有配置 ALB。 此外,由于您没有设置 HTTPS,访问 API 使用的协议是 HTTP。 因此,在这种情况下,您需要提供 EC2 公共 DNS。

您可以通过以下链接访问正在运行的 EC2 实例 https://console.aws.amazon.com/ec2/home?-Instances:instanceState=running,但您也可以选择通过 CloudFormation 输出中的 <st c="42180">APIDNSName</st> 访问新部署实例的 DNS。

在设置了 <st c="42217">API_URL</st> 配置后,您可以保存文件并继续构建过程,这个过程包括几个步骤,将代码转换为可用于网页浏览器的生产就绪的打包文件。 在我们的示例中,我们使用了 <st c="42429">npm</st> 作为包管理器,因此您需要运行以下命令:

 $ npm install && npm run build

结果是一个包含需要复制到 S3 存储桶中的文件的文件夹。 文件夹名称可能会有所不同,但通常为 <st c="42652">build/</st> <st c="42662">dist/</st> ,并且创建在前端根目录,如 图 3**.23所示。

图 3.23 – 构建命令后的文件夹结构

图 3.23 – 构建命令后的文件夹结构

现在,最后一步是将构建文件夹复制到 S3,按照以下说明操作:

  1. <st c="43093">frontend-chapter-3-</st> 后面跟着一串随机字符(例如, <st c="43162">frontend-chapter-3-XXXXX</st>)。 点击其名称以 打开它。

  2. <st c="43239">dist</st> 文件夹添加文件。

  3. 在 S3 存储桶中,点击 上传 按钮。 这将允许您从本地机器上传文件到 S3 存储桶。

  • <st c="43458">dist</st> 文件夹在您的本地机器上,选择该文件夹中的所有文件并确认。 接下来,在 S3 控制台中,点击 <st c="43603">dist</st> 文件夹,选择 <st c="43649">assets</st> 文件夹, 并确认。

可选择性地,您可以直接将内容拖放到 S3 窗口,但无论您使用哪种方法,您的 S3 上传窗口应该像 图 3**.24所示。

图 3.24 – 上传到 S3 的前端文件

图 3.24 – 上传到 S3 的前端文件

注意

文件名是由构建过程自动生成的,因此您的文件名可能与 前面的图示不同。

请确保您有以下文件:

  • <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>

  • 您可能在应用程序中包含的静态文件,例如图像

之后,在底部点击 点击 上传

您刚刚完成了所有的部署和配置,现在是时候 进行测试了。

第五部分 – 测试和探索您的应用程序

这一最后 部分专注于测试和探索你的应用程序,我们将其分为两部分:后端和前端。 让我们从 后端开始!

测试和探索后端

到现在为止,你 应该已经在 EC2 实例中运行了一个 API,再次强调,根据你选择的选项,你需要使用不同的 URL 进行测试,以及你在上一节更新的 <st c="45137">API_URL</st> 参数所使用的值,在 <st c="45162">config.tsx</st> 文件中。 要测试你的 API,你可以向其中一个端点发送请求,如果一切正常,你应该会收到响应和一个成功的 状态码。

要执行测试,你 可以将端点定义为 <st c="45427">{API_URL}/{ROUTE}</st>,其中 <st c="45452">API_URL</st> 是你在上一节的 <st c="45487">config.tsx</st> 文件中使用的 URL。 这里, <st c="45534">ROUTE</st> 是你想要访问的特定路由。

有许多不同的工具可以执行请求,你可以选择你喜欢的工具,但是如果你更喜欢视觉化工具,你可以使用,例如 Postman,或者选择通过运行一个 <st c="45812">curl</st> 命令来采用编程方法。

在以下代码中,你可以看到一个向我们 API 端点发出的 <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> 成功状态码,这证明了 你的 API 正常工作。

测试和探索前端

对于最终的测试,你将探索前端应用程序,并确保你在 <st c="46554">需求</st> 部分中定义的所有功能 按预期工作。

要访问你的前端,你需要进行以下操作:

  1. 进入 CloudFront 控制台。

  2. 选择您用 CloudFormation 堆栈创建的分发。 (如果您有多个分发,并且不确定哪一个是由 堆栈创建的,请打开 CloudFormation 服务,转到您之前创建的堆栈,并检查输出值 <st c="46950">CloudFrontDistributionId</st>)。

  3. 复制分发的 URL(它应该遵循 结构 <st c="47042">https://XXXXXX.cloudfront.net/</st>)。

  4. 如果您愿意,您也可以从 <st c="47188">CloudFrontDistributionUrl</st>中获取该值。

  5. 如果您复制并粘贴 URL 到浏览器中,您应该能够访问您新创建的应用程序并在 用户 管理员 页面之间导航。 如果您尝试访问 管理员 页面,您应该获得与 图 3**.25相同的体验。

图 3.25 – 食谱分享应用程序管理页面

图 3.25 – 食谱分享应用程序管理页面

因为您还没有创建任何食谱,所以列表应该是空的,请尝试创建一些食谱,并尝试查看 管理员 用户 页面之间的体验,以确保满足正确的功能需求。

如果您选择了选项 1,您应该能够看到预期的添加、删除和列出的食谱,但对于选项 2,还有一些额外的步骤 需要执行。

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

尽管 安全性始终是一个关注点,现代浏览器已经提供了保护措施,使在互联网上保持安全姿态更加容易。 在本例中,我们使用的是 Google Chrome,但其他浏览器如 Mozilla Firefox 也适用。

如果您仔细观察,在我们的 URL 左侧有一个警告显示为 不安全,如 图 3**.26

图 3.26 – 食谱分享应用程序未安全警告

图 3.26 – 食谱分享应用程序未安全警告

之所以会发生这种情况,是因为 HTTP 不是一个安全协议,而你的应用正在尝试对你的 API 发出 HTTP 请求。 此外,你的应用在 CloudFront 域中运行,正在通过 HTTP 向不同的域发出请求(一个 EC2 实例域),这通常 看起来很可疑。

如需深入故障排除,你可以在开发者工具中打开控制台,并查看我们收到的 以下错误:

图 3.27 – 控制台错误示例

图 3.27 – 控制台错误示例

仅限演示用途,你可以指示浏览器绕过其默认行为并接受 HTTP 连接,但需要强调的是,虽然这在本次练习中可以使用,但这并不是最佳实践,不应 常规执行此操作。

如果你想跳过这个阻塞,你可以进行如下操作: 以下操作:

  1. 点击红色的不安全 通知/查看网站信息 按钮,位于 URL 地址栏的左侧。

  2. 转到网站的设置

  3. 滚动到不安全内容

  4. 阻止(默认) 更改为 允许

这些指示适用于 Google Chrome,可能会根据版本或使用的浏览器有所不同。完成后,你的应用程序应该能够正常工作,请求将 被授权。

测试并探索你的 DynamoDB 表

最后一步是测试你 API 和 DynamoDB 中的数据层之间的集成,你的食谱数据存储在这里。 如果你想探索资源的创建和删除,请按照 以下步骤操作:

  1. 转到你的DynamoDB 页面,位于你的 AWS 账户中。

  2. 点击探索项目 左侧菜单上。

  3. 选择你的食谱表。

  4. 在你测试创建和删除食谱操作时,列出表中的项目。 这些操作应该在你的 DynamoDB 探索 项目 控制台中反映出来。

图 3**.28 展示了食谱在创建后如何存储在 DynamoDB 中。 作为练习,比较你的 DynamoDB 项目的结构与本章开始时定义的要求。

图 3.28 – 探索 DynamoDB 食谱表

图 3.28 – 探索 DynamoDB 食谱表

第六节 – 清理

虽然 我们尝试使用 AWS 免费套餐中的服务,并且大多数采用的服务是无服务器的,并基于需求自动扩展,但如果你保持应用程序运行,未来可能会产生费用,因此本节解释了如何删除与你的 AWS 账户中与 本项目相关的所有资源。

使用 IaC 的主要优势之一,特别是在这个 CloudFormation 示例中,是简化了基础设施的提供 和删除。

要删除所有创建的资源,你只需要执行 两个步骤:

  1. <st c="51993">frontend-chapter-3-</st> 后面跟着一串随机字符(例如, <st c="52063">frontend-chapter-3-XXXXX</st>

  2. 点击 清空 – 这将删除你桶内的所有内容。

图 3.29 – 清空 S3 桶的过程

图 3.29 – 清空 S3 桶的过程

  1. 删除 CloudFormation 堆栈

    1. 前往你的 AWS 账户中的 CloudFormation 控制台。

    2. 选择你创建的堆栈。

    3. 点击 “删除” 删除

注意

如果你没有在列表中看到你的 CloudFormation 堆栈,请尝试更改右上角的区域,并选择你部署应用程序的区域。 之后,你应该按照所描述并展示在 图 3**.30中的删除过程进行操作。

图 3.30 – CloudFormation 堆栈删除

图 3.30 – CloudFormation 堆栈删除

清理证书和 DNS 管理配置(选项 1)

如果你选择了 第一个选项并创建了 证书并配置了 DNS,那么你需要执行以下 附加步骤:

  1. 删除 证书

    1. 进入你的 证书管理器 控制台。

    2. 选择你创建的证书。

    3. 点击 删除

图 3.31 – 证书删除

图 3.31 – 证书删除

注意

如果你没有在列表中看到你的证书,尝试更改右上角的区域,选择你部署应用程序的区域。 然后,你应该按照删除过程继续操作,具体步骤如 图 3**.31

  1. 清理 DNS:如果你想继续在 Route 53 中管理 DNS,你可以直接 删除 为你的 API 创建的记录:

    1. 进入你的 Route 53 控制台。

    2. 在左侧面板中选择 托管区域

    3. 选择你为 你的域名创建的托管区域。

    4. 选择 API 的记录。

    5. 点击 删除记录

图 3.32 – DNS 记录清理

图 3.32 – DNS 记录清理

此外,如果你不想继续使用 Route 53 管理你的域名,删除 Route 53 中的托管区域,并更新域名注册商中的名称服务器,指向新的 DNS 服务。

未来工作

恭喜你,你 拥有一个完全功能的 Web 应用程序来存储和分享食谱! 但是对于你开发的所有项目,必须时刻记住,你的架构总有改进的空间,并且你应该定期进行审查,以便理解哪些地方可以改进。 这正是你接下来要 做的事情。

使用安全协议

很显然,HTTP 不是一个好的选择。 因此,如果你遵循了选项 2,你可以专注的第一个改进是迁移到选项 1 并为 API 通信配置 HTTPS。

基础设施自动扩展

到目前为止,无论你选择了哪种选项,你都有一个 EC2 实例支持你的后台,但如果负载增加会发生什么? 计算资源不足会带来不好的用户体验,并可能导致实例故障,那么你该如何应对 故障的实例呢?

以故障为前提进行架构设计是实现弹性应用程序的路径。 因此,始终是一个好习惯去问自己,假如这个组件失败会怎样? 在我们的案例中,如果我们的 API 所在的 EC2 实例失败,比如由于负载过大,会发生什么? 为了确保弹性和可扩展性,你应该 使用自动化 API 配置,举个例子,可以使用 AWS 自动扩展 (ASGs)。

ASG 会根据定义的指标自动配置和终止 EC2 实例,比如平均 CPU 使用率。 你可以创建一个 AMI,它是一个预配置的虚拟机镜像,包含运行后台所需的所有配置和代码,并将其与 ASG 关联。 为了限制需要配置的实例数量,你可以设置最小和最大实例数,比如四个实例作为上限,确保永远不会超过这个限制。 通过监控实例状态,ASG 将在指标超过阈值时从 AMI 启动新的实例,并在指标低于 另一个阈值时终止实例。

这种方法通过替换不健康的实例和根据定义的指标进行自动扩展,提供了自愈能力,使 API 具备弹性 和可扩展性。

托管服务和 CI/CD

本章中,你体验了一个构建过程,涉及到在本地更改应用程序,构建并将文件复制到 S3 桶,这个过程非常容易出错。 此外,尽管到目前为止,你是唯一一个在应用程序上工作的开发者,但通常会有一个开发者团队共同协作,而当前的部署方式对于团队协作 来说具有挑战性。

AWS 提供了一个 服务,已管理好托管和 持续集成与持续部署 CI/CD)流水线 ,它简化了构建、部署和托管现代单页应用(如你的食谱共享应用)的过程。 通过 Amplify,你可以连接代码仓库(例如 GitHub、AWS CodeCommit),并配置一个 CI/CD 流水线,能够在代码提交到仓库时自动构建、测试和部署应用。 对于托管,Amplify 利用 S3 和 CloudFront,类似于你当前的设置,因此你仍将从前面提到的所有 AWS 服务 优势中受益。 本章中会有更多相关内容。

身份验证

当你 向你的 API 发出请求时,你无需使用任何身份验证机制。 这意味着世界上任何人,只要拥有端点 URL,都可以发出请求、创建食谱并删除它们,这显然不理想。 在应用程序中实现身份验证对于确保数据的安全性和隐私至关重要,尤其是当涉及到 敏感数据时。

Amazon Cognito 是一个 AWS 服务,简化了将用户身份验证和授权添加到你的 web 和移动应用程序中的过程。 它充当用户身份提供者,允许你管理用户注册、登录和访问控制等功能。 下一章将进一步介绍相关内容。 敬请期待。

日志记录与监控

你只能对 你所衡量的内容采取行动,而在当前架构下,你无法看到应用程序中发生了什么。 你获得了多少次访问? 你的用户位于哪里? 过去 24 小时内是否出现了错误?

虽然 有时监控与日志记录可以互换使用,但它们是两个不同的概念,尽管是互补的。 日志记录 涉及记录应用程序中的历史事件、错误和活动,而 监控 则侧重于收集和分析有关性能、健康状态和 运行状态的数据。

作为 AWS 服务组合的一部分,你可以找到 CloudWatch,这是一个综合性的监控和日志解决方案,分为两个服务:CloudWatch Logs 用于日志记录和 CloudWatch Metrics 用于监控。 通过 利用这些服务,我们可以深入了解应用的行为、性能 和健康状况。

因此,作为改进,你可以将应用日志发送到 CloudWatch Logs,并且创建一个包含所有应用组件的监控仪表板,包括 CloudFront、S3、EC2 和 DynamoDB。 这将为你提供应用程序的整体视图,并为你提供分析的工具。

缓存

食谱 是一次创建,多次访问,并且不常变更,非常适合进行数据缓存。 如果你分析当前的设置,每次用户刷新页面或选择一个食谱时,都会发送请求并在数据库中执行读取操作,这在性能和 成本角度上都可以改进。

DynamoDB 加速器 (DAX) 是一个 完全托管的、集群化的内存缓存服务,用于 DynamoDB。 它旨在通过缓存频繁的查询和响应来提高 DynamoDB 的读取性能。 DAX 兼容 DynamoDB API,这意味着你可以将其与现有应用集成,而无需进行重大代码修改。 但这并不是 唯一的选择。

对于缓存层,你可以使用任何缓存技术,比如 Redis 或 Memcached,它们作为托管解决方案可以在 Amazon ElastiCache 中使用。

这些只是你在应用中可能找到的许多未来工作示例中的六个,因此我们向你提出的挑战是,尝试寻找其他选项,并始终问自己:我能改进我当前的架构吗?

我们将以一个改进版本的应用为例,考虑之前提到的未来工作,如 图 3**.33 所示。

图 3.33 – 最终架构

图 3.33 – 最终架构

3**.6图中展示的初始架构相比,这个新版本已经包含了部分未来计划的工作。 在顶部,CloudWatch 将提供监控功能,帮助你更好地了解应用程序的运行状况,了解过去发生的错误,最重要的是,在事件发生时能够及时采取行动。 如本章所述,这个架构遵循了安全最佳实践,并且仅允许 HTTPS 作为应用程序的访问协议。 为此,你在 Route 53 中配置了你的域名,并颁发了证书来证明你对该域名的所有权。

对于数据层,考虑到食谱通常是稳定的,发布后不会有太多更改,你选择了 DAX 作为缓存层,以提高 用户体验,性能提升达到最多 10 倍——从毫秒级降低到微秒级。 以便获取一个项目。

总结

在这一章中,你实践了在 第一章 中介绍的架构设计框架。 与前一章相比,你现在拥有了一个更强大的应用程序,能够处理动态内容,最终你得到了一个功能齐全的食谱分享应用,可以作为任何项目的起点并应用于你 想到的任何项目。

你有机会体验了将单页面应用(SPA)构建并部署到 AWS 的过程,使用了 S3 和 CloudFront,这使得应用能够服务数千个 用户。

你探索了新的 AWS 服务,如 DynamoDB、EC2 和 ALB。 你还学习了使用 CloudFormation 进行基础设施即代码(IaC)的强大功能。 此外,你还看到了如何配置带有自定义域名的 HTTPS,并与 ALB 关联,以及为什么不推荐使用 HTTP。

最后,你探讨了应用程序可能的改进方向,使其更具可扩展性、成本效益和安全性。

在下一章中,你将把当前的食谱分享应用提升到一个新的水平,并了解如何仅使用 无服务器技术来架构应用程序。

第五章:4

构建无服务器食谱分享应用

在上一章中,你开发了一个食谱分享应用,前端托管在 Amazon S3 和 CloudFront 上,后端使用 Amazon EC2 实例和 DynamoDB。 对于最终用户来说,只能看到功能和整体用户体验,但由提供者定义如何架构应用以及使用哪些技术 来实现。

传统的应用部署涉及服务器的配置和管理、环境配置、资源扩展、安全补丁应用以及系统健康监控。 这种方法需要大量的操作开销,并且常常导致资源利用效率低下,因为资源是为 高峰需求而配置的。

相比之下,无服务器计算抽象化了底层基础设施,使开发者能够专注于编写代码。 使用无服务器计算时,资源的配置、扩展和服务器管理由云提供商处理,从而实现更灵活、事件驱动的方法,并且采用 按需付费模式。

事件驱动架构由通过事件相互作用的独立服务组成。 例如,当用户请求创建一个新食谱时,该请求就变成了一个事件。 这个事件会触发必要的代码来处理与创建食谱相关的业务逻辑。 通过使用这种方法,系统无需提前准备和分配所有资源。 相反,它会在事件发生时响应,从而使架构更加高效 且具有适应性。

在本章中,你将通过完全采用 无服务器技术重新架构你的食谱分享应用,来尝试采用无服务器技术。

总之,本章涵盖了以下主题 按顺序:

  • 你将要构建的内容——一个完全由 无服务器技术支持的最新版本的食谱分享应用

  • 你将如何构建它——使用 Amazon API Gateway 和 Lambda 作为后端,Amazon Cognito 用于身份验证

  • 构建它——通过 CloudFormation 并使用 AWS 控制台

  • 如何改进解决方案——支持食谱的媒体内容,并将身份验证扩展到最终用户,以便提供更 个性化的体验

在本章结束时,你将获得动手实践经验,通过使用 AWS 无服务器技术(如 Lambda、API Gateway、Cognito、S3 和 DynamoDB)重新架构一个动态 Web 应用。 你还将理解无服务器计算的好处,如可扩展性和成本效益,在现代 应用开发中的应用。

技术要求

要跟随并实现食谱共享应用的无服务器版本,你需要拥有自己的 AWS 帐户。

此外,本书的 GitHub 代码库中有一个专门的文件夹,你可以在其中找到跟随学习所需的代码片段: https://github.com/PacktPublishing/AWS-Cloud-Projects/tree/main/chapter4/code

场景

在成功部署个人网站作为你的简历的一部分后, 第二章,你首次接触了云技术,并开始在这一领域建立信心。 在上一章中,借助你的食谱共享应用,你将一个更复杂的应用演变为有后台处理的应用,后台负责处理食谱操作,如创建、删除和检索,用户基础也增长得超出了预期。

你的应用现在被认为是最受欢迎的食谱和烹饪应用之一。 你花在扩展和管理基础设施上的时间越来越多,而不是基于有价值的用户反馈来改进应用,更不用说随着应用的受欢迎程度不断 增长,成本方面的影响了。

上个月,你参加了一场关于无服务器技术的会议,你了解到这些技术非常适合你的需求。 你越是深入探索,越意识到它们可以为你的食谱共享应用提供更高效、可扩展且具有成本效益的解决方案。 使用无服务器架构,你可以专注于编写代码和构建功能,而无需担心配置和管理服务器或基础设施,这正是你所 寻找的。

经过一些研究后,你决定重新架构你的应用,利用 AWS 无服务器服务,以便受益于自动扩展、按需计费和减少 操作开销。

需求

如同前一章中所做的,你将从收集该项目的需求开始。 这将作为 所有技术选择的基础,因此必须清楚地了解目标 和限制。

总体来说,你仍然希望服务于两种 不同的用户类型:

  • 管理员:平台所有者,负责创建和 管理食谱

  • 最终用户或消费者:访问共享的食谱并点赞 喜欢的食谱

考虑到这个项目是前一个项目的升级版,我们将专注于变化并分解 新的需求。

业务需求

凭借你之前的 食谱分享应用,你超出了所有的预期。 到目前为止,当人们想到烹饪并寻找灵感时,他们会直接使用你的应用,且你的市场不局限于美国。 相反,你的用户分布均匀,分别为美国 41%、欧洲 35%、亚洲 20%,其余 4%分布在全球其他地区,去年你达到了 15 万用户。

由于你的成功,你能够与来自不同领域(广告、外卖和食品生产)的公司签订多个合同,但你的增长计划仍在继续。 在前进的过程中,你已经确定了以下关键目标来 专注:

  • 实现 10%的年 用户增长

  • 提高 你的 成本效益

功能需求

关于功能需求,相比前一章你不期望有重大变化,因此,概括起来,这些是 如下:

  • 两种不同的用户类型(管理员 和用户)

  • 简单 的用户界面

  • 响应能力

由于你一直在管理基础设施,没能投入太多时间去为应用开发新功能。 然而,根据用户反馈,你希望增加两个 新功能:

  • 身份验证 和授权

  • 能够对食谱进行点赞,并按点赞排序 进行排序

模拟图是创建应用程序预期行为的可视化表现的好策略,正如你在上一章中看到的那样。 因此,在这一部分,你将进行类似的练习,只关注计划中的新特性,如 图 4.1 4.2 4.3所示。对于主页,你将保持相同的布局,如 第三章 图 3**.1

你不指望不同的个人资料访问你的应用程序,因此相同的划分适用:用户 和管理员。

注意

我们不会列出那些保持不变的功能,如访问食谱标题列表,因为这些内容已经在上一章中讨论过,我们希望避免重复。 假设你已经跟上了进度,你应该已经熟悉了初步需求,如果不熟悉,我们建议你回顾一下上一章中的 需求 部分。

让我们探索每个个人资料 以及界面 和行为方面的预期变化:

  • <st c="7359">/user</st>:像一个 特定食谱。

图 4.1 – UI 模拟用户页面

图 4.1 – UI 模拟用户页面

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

图 4.2 – UI 模拟图 – 身份验证

图 4.2 – UI 模拟图 – 身份验证

非功能性需求

随着你的应用程序的普及,成本和可扩展性成为新的目标。 此外,你希望通过将管理基础设施的时间转向应用程序创新来加速功能的推出。 总结一下,我们需要:

  • 成本效益

  • 事件驱动架构

  • 基础设施管理

技术需求

与上一章相比 并考虑到用户的整体反馈,你希望这次重新架构能够尽可能平滑,不对当前用户的界面和用户体验产生影响。 你希望在编程语言和框架的选择上,尽可能保持之前的技术选型和项目结构。 尽量保持不变。

作为最新研究的一部分,你希望将新的平台架构仅基于 无服务器技术。

数据需求

这个最新版本是你之前版本的扩展,所有数据需求仍然适用。 你的应用程序的核心是存储和管理食谱,食谱由一系列步骤 和食材组成,但你想实现的一个功能是给食谱添加点赞。 对于你在食谱上执行的操作,你必须进行以下操作:

  • 列出食谱:展示已创建的 食谱列表。

  • 删除食谱:如果管理员不再希望某个特定的食谱出现在他们的目录中,应该允许删除 该项。

  • 创建食谱:创建一个新的食谱以便与 用户分享。

  • 点赞食谱:增加特定食谱的点赞数。

根据列出的操作,你需要支持的唯一更改是存储每个食谱的点赞数,因此你定义了一个更新版的食谱文档,如下所示: <st c="9630">recipe_example_2.json</st> 食谱示例:

 {  "ID":"GUID",
   "Title":"recipe title",
   "Ingredients":[…],
   "Steps":[…],
   "Likes":X }

架构模式

每个项目都有其独特之处,但 在设计应用时,有一些共性是可以并且应该加以利用的。 AWS 提供了一个专门的无服务器架构和模式门户,叫做 Serverless Land (https://serverlessland.com/),包含了最新的 无服务器架构的资讯、博客、视频、代码和学习资源,专门面向 AWS。 每当你计划构建无服务器应用时,它总是一个很好的起点。

与传统的部署策略相比,Serverless 意味着一种不同的范式,深入理解核心服务是关键。 AWS 提供了一个无服务器开发者指南(https://docs.aws.amazon.com/serverless/latest/devguide/welcome.html),其中包括核心服务的学习路径,并且也是关于 无服务器相关信息的绝佳资源。

最后,正如前几章所述,每个 AWS 服务都有专门的页面,包含所有服务相关信息。 例如,对于 AWS Lambda,您可以访问它 https://aws.amazon.com/lambda/

架构

尽管用户体验和界面应尽可能与之前版本的食谱分享应用程序保持一致, 第三章,但平台架构是需要重点注意变化的地方。

在本章中,您将采用与设计架构时相同的自上而下的方法。 您将从最高抽象层开始,逐步深入到组件级架构,在这里定义所使用的每个服务,以及它们如何协调工作以构建 您的应用程序。

查看不同的架构层时,您将遵循与上一章相同的结构,包含三个明确定义的层次,就像在 第三章中展示的那样, 图 3**.4

  • 展示层:如何托管和提供 前端

  • 计算层:如何整合和执行 业务逻辑

  • 数据层:存储和检索 您的数据

展示层和计算层通过 API 作为这两层之间的接口。 该 API 负责暴露端点,执行所有操作以执行并抽象出业务逻辑。 在这种情况下,考虑到需求,主要更新是新增了对食谱点赞的新功能,如 图 4**.3所示:

图 4.3 – API 结构

图 4.3 – API 结构

以下是 具体 说明:

  • <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> 端点,尽管该端点并未用于应用程序,但它作为理解认证和端点 保护工作流的学习资源。

图 4**.4 代表了你将实现的架构,基于所有的要求。 前端将使用与上一章相同的方法,利用 S3 和 CloudFront 进行托管和服务。 数据层仍将使用 DynamoDB 来存储菜谱数据。 然而,你将引入 Amazon Cognito 作为认证服务,将菜谱管理活动限制为授权用户。 对于 API,你将使用 Amazon API Gateway 并将其与 AWS Lambda 函数关联,以实现 API 端点功能。

图 4.4 – 用于你的新菜谱共享应用程序的 AWS 架构

图 4.4 – 用于你的新菜谱共享应用程序的 AWS 架构

接下来将描述每个提到的服务,以及选择这些服务的主要优势和原因。

AWS 服务

从大量可用服务中进行选择可能具有挑战性,理解需求是做出决策的关键。 部分服务已经在前几章中介绍过,为避免重复,我们将仅提及当前用例的优势(如果之前没有提到),并指向相关章节以获取 详细解释。

Amazon Simple Storage Service (S3)

Amazon S3 是一种无服务器技术的例子,你应该已经熟悉它,因为它在 前两章中有详细解释。 如果你想复习,可以参考 第二章 第三章

Amazon CloudFront

与 Amazon S3 类似,CloudFront 在本书的前一个项目中 被广泛使用,且在前面的 AWS 服务章节中有详细覆盖,涉及 第二章 第三章。要复习相关内容,我们建议查阅前面的章节。

Amazon DynamoDB

数据需求一直是选择数据库 技术的主要驱动因素。 在本章中,数据需求没有变化,因此 Amazon DynamoDB 依然是我们的选择。 其主要特性和优势在 AWS 服务 章节中已描述,因此,如果你希望详细了解 DynamoDB,我们建议 查看该部分内容。

AWS CloudFormation

如同你在前一章中所做的那样,你将继续使用 AWS CloudFormation(CloudFormation)作为你的 基础设施即代码 (IaC) 工具。 CloudFormation 在 前一章中有详细解释,因此我们建议你查看该章节,以了解该服务及其优势。

Amazon Cognito

Amazon Cognito 是一项完全托管的服务,提供认证、授权和用户管理功能,用于 你的 Web 和移动应用程序。 使用 Amazon Cognito,你可以轻松实现用户注册、登录和账户恢复等功能。 它支持多种认证方式,包括用户池(用于管理应用程序的用户目录)和身份池(用于与社交媒体或企业身份提供者集成)。 Amazon Cognito 与其他 AWS 服务(如 Amazon API Gateway)无缝集成,这些服务也是你无服务器架构的一部分。 这种集成使你能够实现 无服务器认证 和授权机制,以确保只有经过认证的用户才能访问并执行操作, 确保你的应用程序安全。

Amazon Lambda

Amazon Lambda 是一个无服务器 计算服务,允许您在无需配置或管理服务器的情况下运行代码。 使用 Lambda,您可以专注于编写应用程序代码,AWS 会处理 底层计算资源的配置和管理。 Lambda 会根据传入的事件或请求自动扩展代码执行,确保您的应用程序能够处理流量波动,而无需 人工干预。

Lambda 支持多种编程语言,其中 Python 是符合您技术要求的支持运行时之一。 此外,Lambda 无缝集成了其他 AWS 服务,如 Amazon API Gateway,使您能够创建事件驱动的架构并开发高度可扩展、容错且 具成本效益的应用程序。

API Gateway

Amazon API Gateway 是 一个完全托管的服务,使您能够轻松创建、发布、维护、监控和保护任何规模的 API。 它作为您的无服务器应用程序的入口,处理客户端请求并将其路由到适当的后端服务,如 AWS Lambda 函数。

Amazon API Gateway 支持 两种类型的 RESTful API: REST API HTTP API。选择两者之一 必须基于所支持的功能。 REST API 提供更多高级功能,如 API 版本控制、请求/响应数据 转换、缓存和全面的访问控制机制,而如果您需要一个不包含 高级功能的简化且具有成本效益的选项,可以考虑使用 HTTP。

如果您想了解如何在 Amazon API Gateway 中选择 HTTP API 和 REST API,您可以 访问 https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-vs-rest.html

编码解决方案

现在是将所有 概念付诸实践的时刻,通过编码实现到目前为止描述的解决方案,审视并改进您在前面章节中已使用的服务,并熟悉本架构中引入的新服务。

克隆项目

正如你在 上一章中所做的那样,第一步是从与本书相关联的 Git 仓库中将项目复制到本地。 如果你已经跟随上一章,你应该已经在本地计算机上有该 Git 仓库的副本。 如果不是这种情况,你可以直接从与本书相关的 Git 仓库中克隆,或者将其下载为 ZIP 文件。

导航到 <st c="18611">chapter4/code</st> 文件夹。 在其中,你会找到两个子文件夹,如 图 4**.5所示:

  • <st c="18695">前端</st>: 包含你的前端代码。

  • <st c="18742">平台</st>: 包含一个 CloudFormation 模板,用于部署你应用程序的主要基础设施。

图 4.5 – 第四章文件夹结构

图 4.5 – 第四章 文件夹结构

解决方案部署

现在,时机已到, 通过名为 <st c="19040">ch4-application-template.yaml</st>的 CloudFormation 模板部署你的所有应用基础设施,该模板位于 <st c="19095">/platform</st> 子文件夹中,位于你的 <st c="19123">chapter4/code</st> 文件夹内(<st c="19145">chapter4/code/platform/ch4-application-template.yaml</st>)。

表 4.1中,你可以看到由你的 CloudFormation 模板创建的所有资源,但可以随意探索代码本身,并尝试将其与 图 4**.4中的架构进行匹配。

模板 ch4-application-template.yaml
前端 CloudFront 和 S3
后端
  • 1 个 HTTP API,拥有 6 个端点

  • 6 个 lambda 函数,每个对应一个 端点

  • 1 Cognito 用户池

|

数据存储 DynamoDB

表 4.1 – CloudFormation 模板详情

从控制台进入 CloudFormation 服务(console.aws.amazon.com/cloudformation/),并选择你希望应用程序所在的区域。你可以在控制台窗口右上角的下拉菜单中选择 AWS 区域,如图 4.6所示。

图 4.6 – 控制台访问 CloudFormation

图 4.6 – 控制台访问 CloudFormation

为什么选择区域很重要?

在 AWS 中,服务可以根据其可用性和数据复制机制分为区域服务或全球服务。区域服务部署并在特定 AWS 区域内运行,而全球服务旨在提供跨多个区域的一致体验。

CloudFormation 是一个区域服务的例子。因此,选择正确的区域至关重要,因为这确保了你的资源部署在离目标用户更近的位置,从而提供更低的延迟和最佳的用户体验

要继续创建堆栈,请按以下步骤操作:

  1. 点击创建堆栈

  2. 前提条件 – 准备模板部分,选择选择一个现有模板

  3. 指定模板部分,选择上传模板文件

  4. 点击选择文件

  5. chapter4/code/platform文件夹中选择模板。

  6. 点击下一步。你的创建堆栈窗口应显示为图 4.7

图 4.7 – 一个 CloudFormation 创建堆栈表单

图 4.7 – 一个 CloudFormation 创建堆栈表单

下一步是配置你在 CloudFormation 堆栈中的参数。在表 4.2中,你可以找到每个参数的详细说明。

参数 描述
<APIName> 你希望与之关联的 API 名称
<st c="22269">UserEmail</st> 你关联到用户的电子邮件必须有效,因为你会收到一个临时密码,并且稍后需要验证该 电子邮件
<st c="22409">UserPoolName</st> 你将为 Cognito 用户池命名
<st c="22471">Username</st> 稍后,这将是你用来登录 应用程序的用户名

表 4.2 – CloudFormation 模板参数

参数窗口的示例如 图 4**.8所示。

图 4.8 – CloudFormation 堆栈参数

图 4.8 – CloudFormation 堆栈参数

你可以继续操作 直到最后一页。 确认创建 IAM 角色,这些角色将用于提供对 Lambda 函数的访问权限,以执行对 DynamoDB 表的操作,即删除一个食谱,然后 点击 提交

图 4.9 – CloudFormation 堆栈提交

图 4.9 – CloudFormation 堆栈提交

等待堆栈状态更改为 CREATE_COMPLETE,如 图 4**.10所示。这意味着所有资源已成功配置,你现在可以 继续操作。

图 4.10 – CloudFormation 堆栈创建状态

图 4.10 – CloudFormation 堆栈创建状态

在我们的案例中,堆栈部署大约花费了 五分钟,但请考虑到这 可能会有所不同。

重要说明

如果你已经跟随前一章节(第三章)并且忘记清理该章节中创建的所有资源,你可能会在尝试部署本章节中的 CloudFormation 模板时遇到问题。 部署可能会失败,因为在 AWS 中,DynamoDB 表名在单个账户的同一区域内必须是唯一的。 由于本章节是前一章节的扩展,我们使用了相同的表名来存储 食谱。

要解决此问题,请确保按照 清理 章节中的描述,正确清理并删除前一章节中的所有资源,然后再继续进行本章节。

前端配置和部署

在所有 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 模板的Outputs标签中找到。

要访问它,请按以下步骤操作:

  1. 转到 CloudFormation 控制台:console.aws.amazon.com/cloudformation/

  2. 点击您的堆栈。

  3. 在右侧菜单中,选择输出标签,如图 4.11所示。

图 4.11 – CloudFormation 输出标签

图 4.11 – CloudFormation 输出标签

表 4.3 映射了 Stack 输出与配置文件的参数(aws-exports.tsconfig.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)

图 4.12 – 配置文件示例(aws-exports.ts)

并且config.tsx文件应该如下所示,见图 4.13

图 4.13 – 配置文件示例(config.tsx)

图 4.13 – 配置文件示例(config.tsx)

  1. 保存文件。

一旦更新了配置文件,您可以启动build过程,将代码转化为可供浏览器使用的网页打包文件。在我们的示例中,我们使用npm作为包管理器,所以您需要安装依赖并启动build过程:

 $ npm install && npm run build

请注意,之前的命令应在frontend文件夹的根目录下运行。为了测试您是否处于根目录,可以使用以下命令:

 $ pwd
…/chapter4/code/frontend

结果是一个文件夹,里面包含需要复制到我们 S3 存储桶中的文件。 文件夹名称可能不同,但通常是 <st c="29225">build/</st> <st c="29235">dist/</st>。它创建在前端根目录下,如你在 图 4**.14中所见。

图 4.14 – 前端文件夹结构

图 4.14 – 前端文件夹结构

现在,最后一步是将构建文件夹复制到 S3,使用以下指令:

  1. 定位到 S3 存储桶。

  2. 首先,你需要找到之前使用 CloudFormation 模板创建的 S3 存储桶。 存储桶的名称应以 <st c="29766">frontend-chapter-4-</st>开头,后面跟着一串随机字符(例如, <st c="29836">frontend-chapter-4-XXXXX</st>)。 点击其名称以 打开它。

  3. <st c="29913">d</st><st c="29914">ist</st> 文件夹中添加文件。

  4. 在 S3 存储桶内,点击 上传 按钮。 这将允许你从本地机器上传文件到 S3 存储桶。

  5. 将必要的内容添加到 存储桶中。

  6. 首先,点击 <st c="30132">dist</st> 文件夹,在本地机器上选择该文件夹中的所有文件并确认。 接下来,在 S3 控制台中,点击 <st c="30277">dist</st> 文件夹,选择 <st c="30323">assets</st> 文件夹, 并确认。

  7. 你也可以选择将内容直接拖拽到 S3 窗口中,但无论你使用哪种方法,你的 S3 上传 窗口应该像 图 4**.15所示。

图 4.15 – 前端文件上传到 S3

图 4.15 – 前端文件上传到 S3

文件名由 <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>

  • 你可能已在应用程序中包含的静态文件,例如,图片

  1. 之后,在页面底部,点击 按钮 上传

你刚刚完成了所有的 部署和配置工作,现在是时候 测试它了。

测试并探索你的应用

这一部分主要讲解测试和探索你的应用,我们将其分为两部分:后端和前端。 与前一章不同,今天我们从 前端开始!

我们已经将 CloudFront URL 作为输出提供在 CloudFormation Stack 中,因此你可以通过 <st c="31625">CloudFrontDistributionUrl</st> 输出获取它。

你也可以直接从 控制台获取值:

  1. 进入 CloudFront 控制台 访问 https://console.aws.amazon.com/cloudfront/

  2. 点击左侧菜单中的 分发

  3. 选择你创建的分发。

  4. 复制 分发域名 值,来自 详细信息 部分,如 图 4**.16所示。

图 4.16 – CloudFront 分发控制台

图 4.16 – CloudFront 分发控制台

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

图 4.17 – 应用前端示例

图 4.17 – 应用前端示例

你的新应用由 三个元素组成:

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

  • 用户:导航到 用户 页面。

  • 管理员:导航到 管理员 页面。

让我们来 看一下。

管理员页面

这个新解决方案的一个改进是身份验证。 要进行测试,导航到管理员页面,您应该会被提示进行身份验证,如 图 4**.18所示。

图 4.18 – 身份验证表单

图 4.18 – 身份验证表单

通过部署应用程序 CloudFormation 模板,您应已收到类似 图 4**.19 的邮件,发送到您在堆栈部署过程中定义为参数的用户电子邮件,包含用于您所定义的用户名的临时密码。

图 4.19 – 临时密码邮件示例

图 4.19 – 临时密码邮件示例

使用这些值作为您的用户名和密码并继续。 您应该会被提示定义新密码,请继续并点击 更改密码

您已经定义了新密码,最后一步是验证您的电子邮件以便进行账户恢复。

图 4.20 – 邮件验证表单

图 4.20 – 邮件验证表单

选择您的电子邮件地址并点击 验证。通过此操作,您应收到一封新邮件,包含 您的验证代码,如 图 4**.21所示。

图 4.21 – 账户验证邮件示例

图 4.21 – 账户验证邮件示例

粘贴验证代码并继续。 现在您已完成身份验证设置,您的界面应如下所示: 图 4**.22

图 4.22 – 身份验证后的管理员页面

图 4.22 – 身份验证后的管理员页面

如您所见,身份验证状态组件已经改变颜色,现在显示您已 以您的用户名认证。 在我们的例子中,用户名是 <st c="35138">admin</st>。此外,如果您将鼠标悬停在访问令牌上,您将能够访问当前的 访问令牌。

图 4.23 – 带有访问令牌的工具提示

图 4.23 – 带有访问令牌的工具提示

您可以自由浏览应用程序,点击左箭头返回管理员页面,您将看到在未退出登录前您保持认证状态。 返回管理员控制台;首先创建一些食谱,来体验 用户体验。

请注意,根据要求,我们为应用程序添加了一个新功能,使用户可以点赞我们的食谱。 此外,我们还可以根据点赞数对食谱进行排序,例如删除点赞数少的食谱,如 图 4.24所示。

图 4.24 – 管理员用户体验,显示每个食谱的点赞数

图 4.24 – 管理员用户体验,显示每个食谱的点赞数

用户页面

用户 页面与 上一章类似,但我们为 食谱添加了点赞的新功能。

导航到 用户 页面,选择一个食谱,点击 喜欢。这应该会增加特定食谱的点赞数,如 图 4.25所示

图 4.25 – 作为普通用户向食谱添加点赞的示例

图 4.25 – 作为普通用户向食谱添加点赞的示例

如果您想体验点赞功能,只需刷新页面,点赞按钮将重新出现 最后,尝试更改排序,以根据 用户反馈选择最受欢迎的食谱。

测试和探索后端

您的后端现在是通过 HTTP API 网关构建的,每个端点都有一个 Lambda 函数,负责执行相关的操作。 例如,接下来我们来看看 <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 功能负责根据 ID 在 DynamoDB 中删除特定食谱。

因此,每次 执行时,API 网关将触发关联的 Lambda 函数。 在这种情况下,函数将从路径中获取 <st c="38474">recipe_id</st> 并调用 <st c="38511">delete_item</st> API,用于 您的表。

继续探索其他示例:

  1. 进入 API 网关控制台 并访问 https://console.aws.amazon.com/apigateway

  2. 选择您在 CloudFormation 堆栈参数中指定的 API 名称。

  3. 选择 API 选项: <st c="38776">[您的</st> <st c="38782">API 名称]</st>

  4. 点击左侧菜单中的 集成 选项。

  5. 选择您想要 探索的路由。

  6. 点击 Lambda 函数 字段中的蓝色箭头。 这将把您重定向到您特定的 Lambda 函数的页面。

图 4.26 – 通过 API 网关控制台访问 Lambda 函数

图 4.26 – 通过 API 网关控制台访问 Lambda 函数

您的应用程序已 通过 Cognito 身份验证进行保护,因为您无法在未经过身份验证的情况下访问管理员页面。 但是,如果用户试图直接访问 API,会发生什么呢?

这就是 API 授权发挥作用的地方。 对于这个应用程序,我们已经为要求部分中定义的特定路由配置了身份验证,您可以在 API 网关控制台中进行探索:

  1. 进入 API 网关 控制台 https://console.aws.amazon.com/apigateway

  2. 选择您在 CloudFormation 堆栈参数中指定的 API 名称。

  3. 选择 API 选项: <st c="40097">[您的</st> <st c="40103">API 名称]</st>

  4. 点击左侧菜单中的 授权 选项。

您应该能看到类似于 图 4**.27的内容,其中包含两个端点,并且与一个身份验证器相关联。 在这种情况下,使用的是 JWT Auth

图 4.27 – API 网关授权面板

图 4.27 – API 网关授权面板

在右侧的授权器 详细信息中,您可以看到它期望在 Authorization 头中接收授权令牌,并会根据您的 Cognito 用户池配置进行验证。

为了理解行为,我们 创建了 <st c="41284">/auth</st> 路由,该路由当前不需要授权,意味着它是公开可访问的。 我们将做一些更改,以了解如何将其设置为受保护路由并需要一个 授权令牌。

在这个例子中,我们使用了 <st c="41520">curl</st>,但你也可以使用其他工具进行相同的测试,例如 Postman:

  1. 执行 <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.
    
  2. 选择一个授权器以查看其详细信息 下拉框中, 选择 CognitoAuthorizer

  3. 点击 附加授权器

图 4.28 – 授权器附加过程

图 4.28 – 授权器附加过程

你的 授权 菜单现在应该包含 JWT Auth 标记,出现在 /auth | GET 选项前,如 图 4**.29所示。

图 4.29 – 路由授权器页面

图 4.29 – 路由授权器页面

  1. 再次执行请求并确认我们收到 <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.
    
  2. 更改请求以包括授权令牌。 要获取授权令牌,按照以下步骤操作:

    1. 浏览器中打开你的应用程序。

    2. 导航到 管理员 控制台。

    3. 如果你没有进行身份验证,请继续进行 登录过程。

    4. 管理员 页面上,将鼠标悬停在访问令牌上,并复制完整的访问令牌,如 图 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"}

通过此更改,你可以再次向该 路由发起请求。

尝试更改你长 JWT 中的一个字符,你会注意到,即使只是修改一个字符,令牌也会变得无效,与该令牌相关的任何请求都会 被拒绝,因为签名验证将失败,防止 未经授权的访问。

清理

使用无服务器技术的主要优势之一 是它们通过设计提供按需付费的模型,这意味着你只为实际使用的部分付费。 然而,从长远来看,如果你让应用继续运行,可能会产生费用,因此建议在不再使用时清理你的基础设施。 由于我们通过基础设施即代码(IaC)进行部署,清理过程非常简单,包含以下 两个步骤:

  1. 清空 桶:

    1. 进入你的 AWS 账户中的 S3 控制台。

    2. 选择你的前端 S3 桶(桶的名称应以 <st c="44504">frontend-chapter-4-</st>开头,后跟一个 随机字符串)。

    3. 点击 清空;这将 删除桶内的所有内容。

图 4.30 – 清空 S3 桶的过程

图 4.30 – 清空 S3 桶的过程

  1. 删除 CloudFormation 堆栈:

    1. 进入你的 AWS 账户中的 CloudFormation 控制台。

    2. 选择你创建的堆栈。

    3. 点击 删除

注意:如果你在列表中看不到你的 CloudFormation 堆栈,尝试在右上角更改区域,选择你部署应用的区域。 之后,你应该继续进行删除过程,该过程在 图 4**.31中描述并表示。

图 4.31 – CloudFormation 堆栈删除

图 4.31 – CloudFormation 堆栈删除

通过之前的 步骤,你成功移除了为 食谱分享应用创建的所有资源。

使用无服务器技术重新构建您的食谱分享应用程序是一次令人兴奋的实验。 然而,像任何项目一样,总是有改进的机会。 下一部分将探讨潜在的改进和未来的考虑事项,以进一步优化您的无服务器 食谱分享应用程序。

未来工作

恭喜,您已经使用完全无服务器技术构建了您的新版本食谱分享应用程序,并且现在可以根据使用情况进行扩展,而无需担心应用程序的基础设施。 这个新的食谱分享应用程序已经包含了上一章中提到的一些未来工作,例如身份验证或使用安全协议,但始终有 改进的空间。

通过媒体内容丰富您的应用程序

到目前为止,您的应用程序展示了 一组原料和步骤,这是跟随食谱所需的最基本内容。 然而,人们首先寻找的是预期结果的照片,而您的应用程序仍然缺少这一功能。 作为未来工作,您可以考虑为食谱添加照片和视频,以改善用户体验并丰富 食谱内容。

用户资料

在您当前的身份验证机制下,只有授权用户才能管理食谱,但对于最终用户,您几乎无法了解他们的偏好和资料。 点赞功能让 您了解食谱的受欢迎程度,但这并不意味着它适合每个人的口味。 例如,某些用户可能有饮食限制,如果您能够提供更为定制化的体验,这可能会增加您的应用程序的受欢迎度。 作为未来的项目,您可以考虑让用户创建自己的个人资料,填写他们的偏好和饮食限制,并根据 他们的喜好筛选食谱。

在上一章中,已经列出了许多可能的改进。 其中大多数仍然适用于您当前版本的应用程序,例如,内容缓存或定义监控和日志平台,因此我们仅专注于为当前的 未来工作列表 新增的两个功能。

*图 4.32 展示了基于我们强调的两个建议改进,您的架构可能的样子。

图 4.32 – 最终架构

图 4.32 – 最终架构

请注意,数据层添加了一个亚马逊 S3 存储桶,负责存储与每个食谱相关的所有媒体内容。 作为学习练习,思考一下如何存储食谱照片的路径,并尝试 实现它们。

作为提示,您可以 按照当前用于成分和步骤的相同逻辑,将每个媒体文件的路径存储在 食谱文档中的数组中……

总结

在本章中,您投入了重新架构之前的应用程序,现在更加健壮且功能丰富。 此外,您仅专注于无服务器技术,例如 Amazon API Gateway 用于我们的 API,Amazon Cognito 用于身份验证层,Amazon Lambda 用于计算,应该清楚这些技术在可伸缩性、成本效率和运营工作方面的优势。 对于像 Amazon S3 和 Amazon CloudFront 这样的前端以及 Amazon DynamoDB 作为数据层这样未更改的组件,您能够实践和审查它们,因此您应该更加熟练 使用它们。

在下一章中,您将探索使用 AWS 技术开发 图像分析器。

第六章:5

实现一个图像分析器以检测照片的友好度

本章聚焦于 机器学习 ML 能够为你的应用带来的价值。 你将构建另一个无服务器应用,但这次,你将利用 AWS 原生的 ML 服务,而不是复杂的 编程逻辑。

你将使用 Python 构建你的应用,并使用 Terraform 构建架构。

本章涵盖以下主要内容: 按顺序:

  • 你将构建的内容 – 一个照片 质量分析器

  • 你将如何构建它 – 使用无服务器 AWS 服务

  • 构建它 – 使用 Terraform 和 Python

  • 如何改进应用程序 – 使用机器学习、先进的安全功能和自定义 域名

在本章结束时,你将拥有一个自己的应用,使用机器学习识别照片是否足够专业,适合作为个人资料照片。 这是更高级机器学习应用的介绍,你将在 第七章中看到。

技术要求

为了根据本章的指引实现你自己的照片分析器,你需要一个 AWS 账户。

本章在本书的 GitHub 仓库中有一个专用文件夹,你可以在其中找到跟随本章所需的代码片段: https://github.com/PacktPublishing/AWS-Cloud-Projects/tree/main/chapter5/code

场景

你为一家 营销公司工作。 你的公司接收客户的信息和照片,整理它们,并为客户创建社交媒体个人资料

然而,你的客户抱怨他们没有获得足够的点击量。 经过研究,数据科学团队将点击量不足归因于 不专业的照片。

你的任务是创建一个系统,在照片上传到 社交媒体之前,识别它是否足够专业。

要求

你想构建一个可以 评估照片是否专业的应用。 但是,什么是“专业”的标准呢? 你决定,专业的照片要求主体微笑并且眼睛睁开。 眼睛睁开。

你如何在照片中识别这些特征? 编写能够识别照片中特定特征的逻辑并非易事,尤其是照片可能有多种文件格式。 一个机器学习(ML)模型最有可能取得 良好的结果。

由于贵公司所受的安全合规标准,你的解决方案不应存储 个人信息。

此应用程序与之前在章节中构建的其他应用程序不同,它不需要用户界面。 但它需要与现有的 营销公司应用程序集成。

所有这些需求可以转化为功能性、非功能性、数据和 技术需求。

功能需求

功能性 需求定义了解决方案必须提供的具体功能、特性和能力,在这种情况下,具体如下: 以下内容:

  • 能够识别照片是否足够好,适合用作 头像

  • 可与 其他应用程序交互

  • 支持 多种照片格式: <st c="3040">.</st>``<st c="3041">png</st>, <st c="3047">.jpeg</st>

非功能性需求

非功能性 需求定义了解决方案必须提供的定性属性,在这种情况下,具体如下: 以下内容:

  • 高可用性

  • 低成本

  • 可扩展性 – 每秒最多支持 20 个请求 每秒

数据需求

数据需求 定义数据源、处理、治理和合规性需求,在这种情况下,具体如下: 以下内容

  • 不得存储任何 个人数据

技术需求

技术需求 定义了解决方案必须使用或集成的具体技术、编程语言、框架和工具,在这种情况下,具体如下: 以下内容:

  • 必须与多个其他 Python 应用程序集成

  • 必须使用 Terraform 来提供 新的基础设施

  • 分类算法必须 使用机器学习(ML)

架构模式

从 AWS 开始 架构中心,你可以搜索 <st c="3896">图像识别</st> 或者 <st c="3917">图像分类</st>。不幸的是,结果中并未输出任何参考架构。 但是,一份指导性文档 名为 AWS 上的图像分类解决方案 脱颖而出(https://docs.aws.amazon.com/prescriptive-guidance/latest/image-classification/introduction.html)。

虽然这份文档的重点是识别图像中的对象,但它也适用于你的用例。 对于图像分析,AWS 建议你采用以下四种方法之一:

  • 使用预训练的托管解决方案,例如, Amazon Rekognition

  • 调整托管解决方案,例如,Amazon Rekognition 自定义标签

  • 使用无代码解决方案训练模型,例如,Amazon SageMaker Canvas

  • 手动 在你自己的模型上训练

针对每种选择,它们详细说明了灵活性、投入和成本等方面的优缺点。 你可以与 你的需求进行对比。

架构

一个可能的不可知的 架构,应用你在前几章学到的内容,看起来像 图 5**.1。不同的应用程序连接到前端组件,处理连接终止,SSL 证书等,并协调和负载平衡后端连接,提交的照片被解析 和分析。

图 5.1 – 照片分类架构

图 5.1 – 照片分类架构

使用 AWS 服务的图表看起来像 图 5**.2:一个三组件图表,包括 API 网关, Lambda 和 Rekognition。 不同类型的应用程序将通过 HTTPS 连接到 API 网关,调用 Lambda 函数,后者查询 Rekognition 进行图像分析,并相应地解析 响应。

图 5.2 – AWS 上的照片分类架构

图 5.2 – AWS 上的照片分类架构

在接下来的部分,你将找到关于为什么 Rekognition 是这个用例更好工具的详细解释。 现在, 相信我们。

在此架构中,你将前端和后端合并到 API Gateway 和 Lambda 中。

你可能会问自己:“为什么我不能让我的消费应用程序直接与 Rekognition 交互?”你不能这样做的原因有:

  • 它要求所有消费应用程序都必须访问 AWS 凭证

  • 它不允许解析和自定义 响应

  • 它不允许 自定义身份验证/授权

如图所示,你的 消费应用程序可以是任何类型,并且可以位于任何地方;它们可以是 EC2 上的虚拟机、其他云提供商上的容器,或者仅仅是 你的工作站。

AWS 服务

此架构使用了三项服务,但你以前已经使用过其中的两项。 在这一部分,你将理解它们如何满足此项目的要求。

Amazon Rekognition

对于这个用例,你 不想创建编程逻辑来识别照片特征,因此你选择使用 ML 实现相同的功能。

如 AWS 的指导文档中所述,你可以从头开始创建自己的模型。 但是,它与使用预训练的 托管服务相比如何?

首先,在比较这两者之前,你需要找出一个可以处理此任务的服务。 AWS 提供了大量的 AI 和 ML 服务:

  • Amazon Rekognition:一种 计算机视觉服务,旨在分析图像和视频,应用于各种用例,如面部分析、物体检测以及 文本识别。

  • Amazon Transcribe:一种 自动语音识别 ASR)服务,可以将音频 文件 转换为 文本。

  • Amazon Translate:一种 神经机器翻译服务,可以在 多种语言之间进行翻译。

  • Amazon Comprehend:一种 自然语言处理 NLP)服务,可以从非结构化 文本数据中提取见解和关系。

  • Amazon Kendra:一个智能搜索服务,可用于索引和搜索多媒体内容,包括图像 和视频。

  • Amazon Lex:一个用于构建对话界面和聊天机器人的服务,采用自然语言理解和自动 语音识别。

  • Amazon Polly:一个 文本转语音服务,可以将文本转换为 逼真的语音。

Amazon Rekognition 看起来非常适合。 其主要功能如下:

  • 面部分析

    • 检测并分析图像 和视频中的面部。

    • 识别面部特征,如性别、年龄范围、情绪和 面部毛发。

    • 通过与用户提供的数据集中的面部进行比较,识别和识别面部

    • 基于淫秽或 挑逗内容,检测图像或视频中的不安全内容。

  • 物体和 场景检测

    • 检测并标记 图像和视频中的物体、人物、文本、场景和活动。

    • 高精度识别物体和概念。

    • 为检测到的物体 和场景提供边界框。

  • 文本识别

    • 检测并识别 图像 和视频中的文本。

    • 从不同的表面 和方向提取文本内容。

  • 内容审查

    • 检测并过滤掉 图像和视频中的淫秽或挑逗内容。

    • 自动标记不当或 冒犯内容。

重要提示

考虑到使用 Amazon Rekognition 或任何面部识别技术时,必须考虑隐私和伦理问题,并遵守相关法律 和规定。

那么,您应该使用 Rekognition 面部分析功能,还是构建自己的模型呢? 两种方法都是有效的, 主要的比较点如下:

  • 易用性

    • Rekognition 是一个完全托管的服务,这意味着你不需要担心设置和维护底层基础设施或训练模型。 它提供了一个 API 来 分析图像。

    • 训练你自己的机器学习模型需要在数据准备、模型架构选择、训练技术和部署策略方面的专业知识。 它涉及显著的学习曲线和实践操作。 它还需要大量的 数据。

  • 定制化 和控制

    • Rekognition 提供了预训练的模型。 虽然它提供了一些定制选项,例如创建面部识别的自定义集合,但定制的程度 是有限的。

    • 训练你自己的模型允许你对模型架构、训练数据和微调过程拥有完全的控制权。 这使你能够根据特定的应用场景定制模型,并在 专业任务上达到更高的准确性。

  • 数据隐私 和安全

    • 使用 Rekognition 时,你的数据——在本例中是图像——会被发送到 AWS 进行处理,这可能会引发数据隐私和 安全问题。

    • 当训练你自己的模型时,你可以完全控制数据,并确保敏感信息永远不会离开你的环境,从而提供更好的数据隐私 和安全性。

  • 可扩展性 和性能

    • Rekognition 是一个高度可扩展的服务,能够处理大量数据和 并发请求。

    • 大规模训练和部署你自己的模型可能具有挑战性,因为它需要配置和管理计算资源、优化性能并处理 与基础设施相关的任务。

  • 成本和 资源管理

    • Rekognition 遵循按需付费定价模式,你为 API 请求付费。 对于较小的工作负载或 间歇性使用来说,这种方式具有成本效益。

    • 训练你自己的模型需要对硬件资源进行前期投资,并且需要持续的成本来管理和维护 基础设施。

总之,Rekognition 提供了一种便捷且可扩展的解决方案,适用于常见的计算机视觉任务,但其定制选项有限。 训练你自己的机器学习模型提供了更多的灵活性和控制,但需要显著的专业知识、数据 和资源。

在这种情况下,Rekognition 是最佳选择。 你没有成千上万张带有你想要识别特征的标记图像,也没有数据科学知识或时间来构建端到端的 机器学习框架。

根据你的要求,Rekognition 是一个高度可用且可扩展的服务,支持每秒最多 100 次请求。 它支持 <st c="11897">.jpeg</st> <st c="11907">.png</st> 图像格式,并且不会存储你提交的图像。 它也具有低成本优势;在 N. 弗吉尼亚地区,分析一张图像的费用为零点一美分,0.001$。 由于采用按需付费模式,你只有在分析图像时才会产生费用;空闲时没有 费用。

Amazon API Gateway 和 AWS Lambda

在本章的 架构 部分,你了解了为什么直接与 Rekognition 交互并不是理想选择。 然而,你会问自己,“我应该使用什么间接层?” 我该如何选择?”

你可以直接使用 Lambda。

Lambda 允许你解析请求和 Rekognition 响应。 通过使用 Lambda 函数 URL,你将 能够通过 HTTPS 从其他应用访问你的函数(参见 https://docs.aws.amazon.com/lambda/latest/dg/lambda-urls.html)。 然而,Lambda 函数 URL 仅支持 IAM 身份验证或无身份验证,而且你的一项要求是避免 AWS 凭证 的广泛传播。

或者,也许,你可以仅使用 API Gateway。 正如你在上一章中学到的,它为你提供了一个独特的域名,你可以通过 HTTP 进行交互,并且拥有众多功能。 然而,它也有一些缺点;尽管你可以进行一些请求和响应映射,但实现编程逻辑较为困难。 Rekognition 不会返回好/坏的照片诊断,而是返回一个图像属性列表,你必须解析这些属性来计算 决策。

API Gateway-only 方法存在阻塞限制。 API Gateway 并不能直接与所有 AWS 服务集成,尤其是与 Rekognition 不直接集成。 为此,你需要使用一个 Lambda 集成。

对于这个项目,你的间接层应该是两者的结合

重要提示

Lambda 函数 URL 适用于需要一个公共端点且不要求高级 API 网关功能的用例,例如请求验证、流量控制、自定义授权器、自定义域名, 和缓存。

它们是调用 Lambda 函数进行测试的一个很好的方式。 在测试过程中使用它们。

您可以将它们用于本章的用例,然而,为了模拟一个真实的项目, 您不会这样做。

API 网关与 Lambda 将允许您执行以下操作: 以下操作:

  • 通过认证和授权请求控制对服务的访问:您可以配置 API 密钥、IAM 角色和其他自定义 认证机制。

  • 简化 API 版本管理和生命周期管理:您可以创建并部署多个版本的 Rekognition 集成 API,并无缝管理版本之间的过渡。

  • 实现内置请求限流和速率限制功能:这有助于保护您的后端服务,例如 Rekognition,免受过多请求的压垮,这可能导致服务中断和 更高的成本。

将其与您的需求联系起来,Lambda 和 API 网关允许您使用一个广为接受的协议 HTTPS,从多种类型的应用接收请求,集成 Rekognition 进行图像分析,将响应处理为好/坏照片的诊断,并以按需计费的无服务器方式进行处理,而无需将图像存储在任何底层架构组件中。 您可以通过高可用性和 可扩展的组件完成所有这些工作。

编写解决方案代码

再次恭喜你——你设计了一个满足公司所有需求的架构。 现在,是时候构建它了。 在本章中,我们将使用 AWS N。 弗吉尼亚地区。 您可以将 Terraform 变量更改为您 首选的地区。

构建基础设施

解决方案需求要求使用 Terraform 构建基础设施,因为该公司已经在使用该 IaC 语言。

在本书的 GitHub 仓库中,在 <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>,以及一个 Python 子目录。

首先专注于两个 Terraform 文件: <st c="15849">apigw.tf</st> <st c="15862">lambda.tf</st>。回想一下你的架构有三个组件。 你不需要创建自己的 Amazon Rekognition,因为它 软件即服务 (SaaS),因此它没有 Terraform 资源表示。

重要说明

虽然许多人使用一个 <st c="16140">main.tf</st> 文件来描述他们的基础设施,但 Terraform 会考虑目录中所有具有 <st c="16237">.tf</st> 扩展名的文件。 文件名 并不重要。

首先浏览一下 <st c="16317">lambda.tf</st> 文件。 在里面,你 会找到五个资源定义; <st c="16382">aws_lambda_function</st> 是用来创建你的 Lambda 函数的资源, 其名称为 <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]
}

在这个相同的 Terraform 文件中, <st c="17297">lambda.tf</st>,你还创建了一个名为 <st c="17342">Detection_Lambda_Function_Role</st>的 IAM 角色,它附加了两个 IAM 策略: <st c="17411">aws_iam_policy_for_terraform_aws_lambda_role</st> <st c="17460">AmazonRekognitionReadOnlyAccess</st>。这是必要的,目的是让你的 Lambda 函数能够访问其他 AWS 服务,在这个案例中是 Rekognition 和 CloudWatch Logs。 注意这些 IAM 策略如何基于最小权限原则,只允许 Lambda 函数对 所需服务进行读取访问。

因为你的营销公司已经在使用 Python,你也为你的 Lambda 函数选择了 Python。 维护一个或少数几种编程语言有助于提高开发人员的生产力。 你将在下一部分深入研究应用代码,但请注意这个 Terraform 项目是如何处理代码部署的;它使用的是<st c="18102">.zip</st>文件。 这个 Lambda 函数使用 Python 3.8 作为运行时,但等你读到这篇文章时,你可能需要将其升级到更高的版本。 如果是这种情况,只需更改<st c="18288">runtime</st>变量即可。

在第二个 Terraform 文件中,<st c="18336">apigw.tf</st>,你将找到八个资源。 要使 API 网关工作,它需要多个组件:阶段、资源和方法。 此外,它还需要权限与其他组件交互,在本例中就是你的`Lambda 函数。

<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> }

前两个Terraform 资源<st c="18923">my-api</st><st c="18934">root</st>,创建了一个名为<st c="18976">my-api</st>的区域 API 网关,以及根资源上的<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
  ]
}

这段代码创建了四个组件,如图 5**.3所示:<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>方法,并将集成请求类型设置为 Lambda。 你不会更改 Lambda 的响应,只是将其代理回去。

图 5.3 – API 网关方法设置

图 5.3 – API 网关方法设置

<st c="21098">apigw.tf</st> 文件的末尾,你会找到一个名为 <st c="21139">apigw_lambda</st>的资源,它修改了 Lambda 权限,允许 API 网关 调用它。

在你喜欢的终端中,导航到 <st c="21272">chapter5/code</st> 文件夹,运行以下 Terraform 命令并 确认。 这将创建本节中提到的所有资源:

 $ 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>

记下你的 部署 URL。 你稍后会用到它。

打开你的 AWS 控制台,导航到 API Gateway、Lambda 和 IAM 来验证之前创建的内容。 确认所有资源已创建。

理解图像分析代码

你在上一节部署的 Terraform 基础设施 代码创建了一个包含应用逻辑的 Lambda 函数。 打开位于 <st c="23370">rekognition.py</st> 文件中的目录,该文件位于 <st c="23413">python</st> 文件夹内,路径为 <st c="23427">chapter5/code</st> 文件夹。

你会找到像上一章一样的模板代码,用于与 Lambda 生态系统集成。 但更有趣的是它与 Rekognition <st c="23625">DetectFaces</st> API 的交互方式( https://docs.aws.amazon.com/rekognition/latest/APIReference/API_DetectFaces.html)。

这段代码调用了 <st c="23750">DetectFaces</st> API 并解析响应,确保照片中没有多于一个人,且此人正在微笑并且眼睛睁开:

 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' 情感 = rekognition_response['FaceDetails'][0]['Emotions']


			<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>
			![Figure 5.4 – Image analyzer API architecture](https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/aws-cld-proj/img/B22051_05_4.jpg)

			<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 -out


			<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>
			![Figure 5.5 – Postman configuration](https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/aws-cld-proj/img/B22051_05_5.jpg)

			<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

构建内容翻译流水线

在本章中,你将首次接触到 持续集成与持续交付 (CI/CD)。 你将构建一个事件网站,能够自动 根据用户的首选语言渲染内容,但与之前的方式不同,它将以自动化的方式进行部署。

与上一章类似,你也将使用 AWS 机器学习服务、Python 和 Terraform。

总的来说,本章涵盖了以下 主要内容:

  • 你将要构建的是——一个多语言的 Web 应用程序,使用 CICD 流水线

  • 你将如何构建它——使用 S3、CloudFront、Lambda@Edge、Translate 和 CICD 工具

  • 构建它——使用 Terraform 和 Python

  • 如何改进应用程序——为基础设施采用 CICD,并支持 更多语言

在本章结束时,你将获得 AWS CI/CD 服务的实际操作经验,并能够构建自己的 应用程序流水线。

技术要求

本章在本书的 GitHub 仓库中有一个专门的文件夹,你将在那里找到跟随本章进行操作所需的代码片段: https://github.com/PacktPublishing/AWS-Cloud-Projects/tree/main/chapter6/code

为了跟随本章,你需要访问一个 AWS 账户。

场景

你的公司 在北美举办技术活动,如会议和网络研讨会。 你的营销同事会分别在各大社交媒体平台上宣传这些活动。 然而,他们认为如果能有一个单一的页面,用户可以在上面找到所有的 即将举办的活动,那将会更有帮助。

你的任务是 为该功能创建一个 概念验证 Web 应用程序。

在与一位高级领导的谈话中,她提到可访问性是公司的一项原则。 她还提到,虽然贵公司所有的活动都以多种语言进行直播,但这些活动总是只用英语进行宣传。 这反映在它们的 出席人数上。

需求

您需要 构建一个应用程序,显示所有即将举行的公司活动,并将用户带到活动的注册页面。 语言可访问性很重要;应用程序应根据用户的 首选语言动态呈现。

由于事件不断发生,并且新事件已计划,您需要一种机制来 进行更改。

公司的云成本创下了历史新高。 这款应用程序应尽可能低成本,同时保持高可用性。 如果人们尝试访问它,而它处于停机状态,那将反映在低活动出席率中。 但是,您不希望进一步增加 云成本。

您可以将需求格式化为各种类别:功能性、非功能性, 以及技术性。

功能性需求

功能性需求定义了解决方案必须提供的特定功能、功能和能力。 在这种情况下,它们是 如下:

  • 显示公司 未来的活动

  • 能够创建、编辑和 删除事件

  • 能够回滚到 先前的版本

  • 支持图像 和文本

  • 接口必须适应用户的 首选语言

非功能性需求

非功能性需求定义了解决方案必须提供的定性属性。 在这种情况下,它们是 如下:

  • 低成本

  • 北美地区的低延迟

  • 高可用性

  • 易于维护

技术需求

技术需求定义了解决方案必须使用或集成的特定技术、编程语言、框架和工具。 在这种情况下,它们是 如下:

  • 必须集成 Terraform 代码库

  • 必须使用自动化机制进行内容翻译

架构模式

转到 AWS 架构中心并搜索 <st c="3664">内容本地化</st>。您将找到 AWS 上自动语言翻译指南 AWS 上内容本地化 参考架构。

参考架构用于创建多语言字幕的解决方案,而指导则侧重于数据库中翻译的产品信息。 虽然这些并不完全匹配,但你可以看到一个模式:两者都利用了 Amazon Translate 进行实际的 内容翻译。

在继续之前,搜索 <st c="4147">CICD</st> 这将返回大量结果。 浏览它们。 其中一个特别有趣的 AWS Fargate 上的 .NET 应用程序 CI/CD。它使用 CodeCommit 作为代码仓库,使用 CodeBuild 构建构件,最后,使用 ECS 部署它们。 所有这些都作为 CodePipeline 阶段进行编排。

在撰写本文时,CodeCommit 已被 AWS 弃用。

没有任何 架构完全符合你的要求。 你必须自己设计 它。

架构

有多种 方法可以将网页呈现为用户首选的语言。 你可以使用特定的框架工具,例如 <st c="4733">i18n</st> 在 React 中,或者使用基础设施重定向,例如 <st c="4787">Lambda@Edge</st>

重要提示

这是一本实用的 AWS 书籍,而不是特定的网页框架书籍,因此这一章实现了基础设施 重定向方法。

然而,如何识别用户的首选语言呢? 你可以在页面顶部添加一个按钮,让用户选择语言。 这是一个常见的方法。 不过,你可以做得更好。 你可以让它基于 请求属性 自动检测用户的偏好。

在决定如何实现语言渲染后,回到解决方案需求,你会发现它们与 第二章 第三章类似。然而,由于这是一个概念验证,你希望最小化市场推出时间,因此你决定重新使用静态架构,并配置自动检测语言属性并发送适当资源的功能。 使用 AWS 服务时,架构如下所示: 图 6**.1。使用两个或更多 S3 存储桶存储你的应用页面(在此案例中为英语和西班牙语),并使用 CloudFront 配合 <st c="5799">Lambda@Edge</st> 来检查用户的请求并获取特定的 语言资源。

图 6.1 – 多语言静态网站架构

图 6.1 – 多语言静态网站架构

该架构可以工作,但并未满足所有需求,比如易于维护性或自动翻译。 您可以添加、修改和删除事件;然而,在 第二章中,它是一个单一的桶。 在这个新架构中,每次要进行更改时,您必须将其复制到所有桶中。 您还缺少一个自动化机制来创建翻译后的内容。 虽然您可以使用 S3 对象版本控制来支持回滚,但这并不是一个理想的机制,尤其是当您必须保持多个 不同桶中的内容同步时。

正如您之前 在架构中心看到的,CI/CD 可以帮助构建并推送更改到应用程序。 在这种情况下,您可以将 Web 应用程序文件存储在代码库中,并使用 CI/CD 管道来协调翻译并将内容同步到多个桶中。 图 6**.2 展示了使用 AWS 服务的架构。 应用程序管理员 Admin 将应用程序文件以英文形式存储在 GitHub 仓库中。 对仓库的更改会触发一个 CodePipeline,该管道与 Amazon Translate 互动生成翻译版本的文件,并将其部署到各自的桶中。 GitHub 仓库在 AWS 云中展示,但它实际上位于外部。 这仅仅是为了表示方便 的目的。

图 6.2 – 带有内容翻译管道架构的多语言网站

图 6.2 – 带有内容翻译管道架构的多语言网站

使用这种架构, 管理员只需要在一个地方、使用一种语言进行更改。 虽然示例中显示的是西班牙语,但修改可以传播到任意数量的 配置语言。

AWS CI/CD 服务是众多选项之一。 您也可以使用第三方 CI/CD 工具来实现该架构。 示例 包括 Jenkins、GitHub Actions 或 GitLab CI/CD。

AWS 服务

该架构 使用了四项新服务。 在本节中,您将了解这些新服务的功能,以及它们为何满足 您的需求。

其他服务,如 S3 或 CloudFront,已经被预先部署。 请参阅前面的章节,深入了解它们的功能。

Lambda@Edge

你已经在其他章节中学习了 Lambda ,但 Lambda@Edge 不同。 与在 AWS 区域中运行的 Lambda 不同,这些特殊的 Lambda 函数在你将它们与 CloudFront 分发关联时,会在 AWS 边缘位置运行。

Lambda@Edge 背后的主要理念 是将计算能力更靠近用户,使得操作如修改边缘的请求或响应成为可能,这正是你想要做的。 目标。

Lambda@Edge 函数与 CloudFront 紧密集成。 这些函数可以响应四种类型的事件触发: 事件:

  • 查看器请求:当查看器请求 CloudFront 分发的内容时,此事件会触发。 此事件中的 Lambda@Edge 函数可以在请求发送到 源服务器之前修改请求头或请求的对象路径。

  • 源请求:当 CloudFront 需要从源服务器请求内容时,此事件会触发。 此事件中的 Lambda@Edge 函数可以在请求发送到 源服务器之前修改请求头或请求的对象路径。

  • 源响应:当 CloudFront 从源服务器接收到响应时,此事件会触发。 你可以在此事件中使用 Lambda@Edge 函数检查并修改源服务器的响应 ,然后再缓存并返回给 用户。

  • 查看器响应:此事件会在 CloudFront 返回请求的内容给查看器之前触发。 此事件中的 Lambda@Edge 函数可以修改 CloudFront 的响应头或响应体,然后再发送给 查看器。

在你的场景中,你可能需要根据用户的请求更改对象路径。 源请求触发器适用。 事件。

这些特殊的 Lambda 函数用于许多其他用例,例如添加 HTTP 安全头、阻止不需要的请求、重定向到不同的页面、A/B 测试等。

没有免费层,但 这些 Lambda 函数的费用是每次请求 $0.0000006,外加每 GB-秒 $0.00005001。 你可以在 AWS 网站上查看详细信息 ,网址是 https://aws.amazon.com/lambda/pricing/

Amazon Translate

你需要一个 自动化 翻译机制。 Amazon Translate 就是这样一个机制,而且还提供更多功能。 它是一个基于 API 的托管服务,支持 75 种不同语言。 它使用机器学习提供按需的高质量翻译, 即按翻译付费。

它支持文本和文档翻译。 在你的情况下,你将发送 HTML 文档。 然而,根据网页应用框架,你可能需要发送文本片段。 如果你使用 React 和 i18n,你需要创建 <st c="10750">translation.json</st> 文件。

还有其他第三方翻译服务。 然而,Translate 与 AWS 生态系统集成得非常好。它可以使用 IAM 角色和临时凭证来进行访问,而无需用户名和密码,而且你的数据不需要通过 互联网传输。

如果你是新用户,它还包括一个 免费层。

AWS CodePipeline 和 AWS CodeBuild

你需要 某个东西来 将所有组件 串联起来,并协调 步骤。

AWS CodePipeline 是一个完全 托管的 持续交付/部署 (CD) 服务,帮助你自动化应用程序和基础设施更新。 然而,在深入了解 CodePipeline 的好处以及它如何满足你的需求之前, 什么是 CI/CD?

CI/CD 是一种软件 开发实践,旨在自动化和简化构建、测试和 部署应用程序的整个过程。

持续集成 (CI) 是指频繁将代码更改合并到中央代码库中的实践。 每当开发人员推送代码更改时,CI 过程会自动构建应用程序,运行单元测试,并检查是否有任何 集成问题。

CD 是 CI 之后的下一步。 CD 侧重于自动化整个软件发布过程,包括构建、测试和打包应用程序。 其目标是确保应用程序始终处于可发布状态,并且可以在最小的人工干预下迅速、安全地进行部署。 持续部署是持续交付的延伸。 在这一实践中,每一次通过自动化测试和检查的代码更改都会自动部署,无需人工干预。 在你的项目中,你将使用 持续部署。

一个典型的 CI/CD 过程包括以下组件:

  • 代码仓库:这是一个开发人员提交代码变更的地方,在你的 情况下是 GitHub。

  • CI 工具:这些工具编译源代码,运行测试,并生成可部署的软件包。 流行的 CD 工具包括 TravisCI 或 AWS CodeBuild。

  • 持续交付工具:这些工具可以自动检测代码变更,从你的代码仓库中检索最新版本,并执行一系列步骤。 流行的 CD 工具包括 Jenkins、GitHub Actions、 AWS CodePipeline。

  • 持续部署工具:这是一个在应用程序构建和测试后自动化部署的工具,它们实现了蓝绿部署、金丝雀部署等流行的部署策略。 流行的工具包括 AWS CodeDeploy 或 Ansible。

CI/CD 实践旨在通过自动化从代码提交到部署的整个过程,更快速、更可靠、更高质量地交付软件。 它们消除了人工操作,减少了人为错误的风险,使团队能够更频繁、更一致地发布更新。 在你的情况下,它使你能够拥有一个英文的单一代码仓库,并将其部署到多个语言的多个存储桶中。

CodePipeline 是一个可行的持续交付选择。 它有免费的套餐,原生集成在 AWS 生态系统中,语法易于理解,并且是一个 AWS 项目。

由于你的部署目标是 S3 存储桶,你不需要传统的持续部署工具。 你正在进行持续部署,这意味着如果你在代码仓库中做出更改,这些更改会直接推送到你的 web 应用程序。 然而,你将使用持续集成工具 CodeBuild 来 实现这一点。

你感到困惑吗? CodeBuild 是一项完全托管的持续集成服务,它可以编译源代码、运行测试并生成包。 在你的案例中,部署就是将文件复制到 S3 存储桶。 CodeBuild 可以做到这一点。 CodeBuild 会从构建规范文件中读取并执行指令, <st c="14476">buildspec.yml</st>,在一个可配置的环境中运行,例如 Linux 虚拟机或一个 Docker 容器。

传统的持续部署工具面向那些需要传统计算环境(例如虚拟机)的应用程序。 如果你像在 第三章中一样实现了一个带 API 后端的 web 应用程序,你将会利用 这些 工具。

构建 CI/CD 流水线 这一节中,你将更详细地了解这些工具,并与它们进行互动。

编码解决方案

这个解决方案有两个部分:web 应用程序和 CI/CD 流水线。 你将按顺序构建 它们。

在本章中,你将把资源部署到 北维吉尼亚 地区

构建 web 应用程序

在本节中,你 将使用 Terraform 构建在 图 6**.1 中讨论的架构。

如果你还没有这么做,从 https://github.com/packtpublishing/aws-cloud-projects克隆这本书的仓库。 然后导航到 <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> 在你喜欢的代码编辑器中,并仔细检查代码。 这段代码创建了两个 S3 桶,里面包含了 第二章的 HTML 和 CSS 文件,一个使用 OAC 连接到 S3 的 CloudFront 分发,一个在源请求时触发的 Lambda@Edge 函数,以及为所有这些组件之间的交互所需的角色和权限。 以确保其正常工作。

有一些值得注意的代码片段,例如,桶名称是 输入变量:

 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"

同样值得注意的是一些 CloudFront 的变量:如 <st c="16720">PriceClass_100</st> 价格类别、转发头以及低 TTL 缓存值:

 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
  }
}

根据要求,你的公司只期望观众位于北美。 CloudFront 有不同的定价策略,按照该策略,它不会将你的内容分发到所有边缘位置。 该价格类别仅在北美和欧洲的边缘位置分发你的内容,从而使数据传输成本降低。 这并不意味着其他地区的用户无法访问你的内容,只是意味着数据将通过互联网传输,而不是通过 AWS 网络的骨干网。 AWS 网络。

缓存的存活时间降低至 0 到 1 秒之间。 这使得 CloudFront 在一秒钟后从源服务器重新获取资产。 这个配置帮助你测试和排除故障,无需等待缓存过期。 你之后可以增加 缓存的存活时间。

最后,还有 Accept-Language 转发头。 有多种方法可以实现用户的首选语言。 例如,你可以使用用户的 IP 地址推断他们的国家,或者使用 CloudFront 添加的头部,如 CloudFront-Viewer-City CloudFront-Viewer-Country-Name。在本项目中,你将使用 Accept-Language 头,因为你认为尽管一个人可能物理上位于某个国家,但他们可能并不懂该国的语言。 这种情况在旅行时常常发生。

Accept-Language 头指示用户的语言偏好。 它是一个列表。 浏览器根据用户的设置来设置这个值。 在 Chrome 中,设置项位于 语言 部分,如 图 6**.3所示。

图 6.3 – Google Chrome 语言设置界面

图 6.3 – Google Chrome 语言设置界面

在 CloudFront 中,你必须转发这个头部,以便 Lambda@Edge 函数能够进行评估。

接下来,进入 Python 代码 <st c="19952">lambda.py</st>,该文件位于 <st c="19974">lambda</st> 文件夹内。 这段代码将支持你的 Lambda@Edge 函数。 尽管代码简短,但该函数解析了Accept-Language 头,并检查列表中的第一个值是否以 es开头。如果是,它将把 源更改为存放西班牙语版本资源的存储桶:

 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

你需要用自己的 domainName 参数来更改这段代码。 这是你西班牙语资源 S3 存储桶的 URL。 这段代码使用列表中的第一个值,因为 Accept-Language 头是按照 用户的偏好顺序排列的。

Terraform 会读取目录中的所有 <st c="20957">.tf</st> 文件,并将所需的更改应用到你的基础设施中。 你可以通过重构代码并将其移至单独的目录,单独运行这些 Terraform 模块。 然而,最佳实践是将所有项目资产保存在一个单一的 Terraform 状态文件中。 目前,请不要运行 Terraform <st c="21283">apply</st> 命令。 你将在 下一部分执行此操作。

构建 CI/CD 管道

在前一部分中,你 已经学习了如何构建在 图 6**.1中讨论的架构。 在本节中,你将学习 CI/CD 组件,并使用 Terraform 构建完整的 图 6**.2 架构。

在你的代码编辑器中打开 <st c="21589">cicd.tf</st> 文件。 这个 Terraform 文件创建了一个 CodeStar 连接到 GitHub 仓库,一个 S3 存储桶,存储桶名称由 <st c="21727">codepipeline_bucket_name</st> 变量值决定, 该值在 <st c="21778">dev.tfvars</st> 文件中定义, 创建一个使用 <st c="21811">buildspec.yml</st>的 CodeBuild 项目,一个具有两个阶段(源代码 构建)的 CodePipeline,以及为所有组件设置角色和策略,以便它们能够成功地相互交互。

CodeStar 是最简单的。 它只是一个与 GitHub 代码仓库的连接。 但是,要使其工作,你必须创建你自己的 GitHub 仓库。 如果你不熟悉这个过程,可以参考这个指南。 学习如何在五分钟内创建新仓库并提交你的第一个更改 ,请访问 https://docs.github.com/en/repositories/creating-and-managing-repositories/quickstart-for-repositories

在这个仓库中,你将保存你的网站文件。 创建仓库后,修改 <st c="22471">github_repository_url</st> 变量,在 <st c="22505">dev.tfvars</st> 文件中使其与您的 GitHub URL 匹配。

查看 CodePipeline 部分。 它创建了一个包含两个阶段的流水线,但你可以看到每个阶段的工件是如何通过 <st c="22677">input_artifacts</st> <st c="22697">output_artifacts</st> 变量连接的。 这个功能确保你在下一个 阶段中使用的是前一个阶段构建的内容。 它使用一个 S3 存储桶,正如你在 <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> }
    }
  }
}

第一阶段克隆 仓库,第二阶段触发一个 CodeBuild 项目。

现在,转移你的注意力到 CodeBuild 部分。 它使用 Lambda 计算环境,这意味着它通过 Lambda 函数运行指令,而不是使用 EC2。 CodeBuild 执行的指令在 <st c="23986">buildspec</st> YAML 文件中定义:

 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>。你 可以看到 CodeBuild 将执行的五个命令。 总结来说,CodeBuild 会将本地目录的内容复制到每个存储桶中,然后执行一个 Python 函数。 最后,它会将该 Python 函数的结果文件复制到 西班牙语存储桶:

 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>

你需要将所有 AWS S3 命令中的 URL 替换为你自己的。

为什么 CodeBuild 在本地目录中有文件? 这是因为 CodeBuild 是在 CodePipeline 从 GitHub 拉取之后执行的。 现在,打开 <st c="25114">translate.py</st> 文件位于 <st c="25134">app</st> 文件夹中。

重要提示

<st c="25165">s3 sync</st> 命令通过递归地复制文件来同步 S3 中的目录。 它仅传输 更改过的文件。

记住,这条流水线的目标是将对网站源代码的更改传播出去;你可以通过 <st c="25401">s3 sync</st> 命令来完成。 然而,你还希望将资源自动翻译成西班牙语并传播到另一个存储桶。 这就是 <st c="25549">translate.py</st>,利用 Amazon Translate 完成的任务。 代码调用了 <st c="25617">translate_document</st> API,并将 <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> 文件。 这些是你新的网站资源。 在本地工作站上查看这些文件,了解网站将 呈现的样子。

现在你已经了解了所有解决方案组件及它们在 Terraform 中的表示方式,接下来是时候创建它们了。 运行 <st c="26932">terraform apply</st> 并使用你的 变量文件:

 terraform apply -var-file="dev.tfvars"

成功的 执行应输出 <st c="27049">Apply Complete!</st>

在一切正常工作之前,你必须执行一个手动步骤:授权 CodePipeline 访问你的 GitHub 仓库:

  1. 导航到 CodePipeline 控制台 https://us-east-1.console.aws.amazon.com/codesuite/settings/

  2. 设置中, 选择 连接

  3. 你将会看到 <st c="27347">app-dev-codestar</st> 待处理 状态连接。 选择它并点击 更新 待处理连接

  4. 在弹出窗口中,选择 安装新应用,如 图 6**.4所示,然后使用你的 GitHub 凭证登录。

图 6.4 – 连接到 GitHub AWS 菜单

图 6.4 – 连接到 GitHub AWS 菜单

你的 <st c="27821">app-dev-codestar</st> 连接 现在应该显示 可用 状态。

测试解决方案

导航到 CloudFront 控制台并提取你的分发 URL。 访问它,你看到了什么? 它应该是 第二章 2的前端。

你 S3 桶中的文件没有改变。 要触发变化,你首先需要将应用文件上传到你的 GitHub 仓库。

有多种方法可以做到这一点。 它是 Git 兼容的,因此你可以克隆仓库,并通过这种方式添加文件。 另一种方法是通过 GitHub 控制台手动上传这三个文件。

使用 Git 方法,从 <st c="28454">app</st> 文件夹中执行以下命令,替换 URL 为 你自己的:

 $ <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)

导航到你的 分发 URL。 现在你应该能看到新的网页,取决于你的浏览器设置,可能是英语或西班牙语。 图 6**.5 展示了并排对比。 试试看两种版本。

图 6.5 – 英语和西班牙语 Web 应用版本的并排对比

图 6.5 – 英语和西班牙语 Web 应用版本的并排对比

导航到 CodePipeline 和 CodeBuild 控制台并查看 输出。

对你的 index.html <st c="31082">index.css</st> 本地文件进行任何更改,并将更新后的版本上传到 git。 验证这些更改如何触发 你的 CodePipeline。

清理工作

正如你在 上一章中看到的,使用 Terraform 进行清理非常简单。 你只需使用 <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> 命令。 它将删除所有内容,但 如果你的存储桶为空,则会保留 Lambda 函数。 几小时后,你可以手动删除 Lambda 函数。

未来的工作

你的概念验证已经成功;现在你需要将其投入生产。 本节内容将为你提供一些增强功能的灵感。

实现自定义名称

通常的增强功能 适用此处。 友好的 DNS 名称不仅有利于记忆,还能提升安全性,以避免用户误连接到其他 Web 应用程序。 以免出错。

如果你拥有域名和证书,正如你在 第三章中学到的那样,你也应该在这个应用程序中配置它们。 在这个架构下,这是在 CloudFront 级别完成的。

扩展应用功能

尽管这个 Web 应用程序满足了所有要求,但它还可以支持更多语言。 修改该解决方案以支持至少一种 更多语言。

为此,你需要创建一个新的桶,并修改 Lambda@Edge 代码以查找不同的 请求头值。

你可以在 https://learn.microsoft.com/en-us/graph/search-concept-acceptlanguage-header查看每种语言的请求头值。

为基础设施代码采用 CI/CD

你已经在本书的各个章节中构建了 许多 基础设施组件。 正如你在本章中学到的,CI/CD 同样适用于 IaC。 例如,与你在终端中运行 IaC 命令不同, <st c="33664">terraform apply</st>,你可以并且应该通过 CI/CD 工具来执行它。

这种方法有 几个好处:

  • 范围访问:人类操作员只能访问 CI/CD 工具,无法直接访问 基础设施

  • 更好的可追溯性:知道是谁做了 什么,何时做的

  • 标准化:再也不会有“在我机器上能用”的评论

如果你对这个 主题感兴趣,AWS 提供了深入的指导 https://docs.aws.amazon.com/prescriptive-guidance/latest/patterns/create-a-ci-cd-pipeline-to-validate-terraform-configurations-by-using-aws-codepipeline.html

总结

在本章中,你构建了一个动态渲染的 Web 应用程序,考虑到用户的偏好来提供更好的用户体验。 尽管你是为了适应用户的首选语言而构建它的,但同样的方法也可以用于根据其他信息(例如访问的网站或 设备类型)来适配应用程序。

为了构建这个应用,你使用了一个高级的 CloudFront 动态渲染功能,结合 Lambda@Edge 和由 Amazon Translate 提供支持的机器学习算法。

本章的第二部分集中在 CI/CD。 你利用了 AWS 原生服务,构建了一个完全自动化的管道,接收英文资源,翻译它们,并将其部署到 Web 应用中。 如今,CI/CD 在大多数 应用中得到广泛使用。

本章以家庭作业结束:这些任务是你可以自行实施的,以磨练你的技能并改进该 项目的功能性。

在下一章中,你将继续利用 AWS 机器学习服务,但这次你将构建一个 类人聊天机器人。

第三部分:高级项目

第三部分 本书中,你将继续学习关于新的 AWS 架构和服务。 最后一部分重点讲解了人工智能、机器学习和数据分析等高级功能。 你将利用大型语言模型、无服务器 ETL 工具和 AWS 原生仪表板。 在这一部分的最后,你将找到一些额外的资源,供你在构建下一个 大型项目时参考。

这一部分包含以下章节:

  • 第七章 利用机器学习实现聊天机器人

  • 第八章 构建商业智能应用

  • 第九章 探索未来工作

第八章:7

使用机器学习实现聊天机器人

在前面的章节中,你已经有机会进行实验并熟悉 人工智能 AI)技术在不同领域的应用。 从计算机视觉开始 通过分析你的照片到文本翻译的自动化,你现在应该已经有了两个完全功能的项目,展示了 AI 在现代应用中的强大力量,但这只是冰山一角。

在今天的数字化环境中,用户越来越倾向于在应用程序中寻找有趣和互动的体验,而聊天机器人已经成为一种强大的方式来满足这一需求,利用 自然语言处理 NLP)和 对话式 AI 提供个性化、实时的帮助,并促进一种 类人互动的感觉。

总结来说,本章涵盖以下主题, 按顺序:

  • 你将构建的内容 - 一个用于 安排会议的聊天机器人应用程序

  • 你将如何构建它 - 使用 Amazon Lex

  • 构建它 - 通过 CloudFormation 并使用 AWS 控制台

  • 如何改进解决方案 - 使用来自 Amazon Lex 扩展你的聊天机器人功能

在本章中,你将提升对 AI 技术的理解,并探索开发聊天机器人以帮助安排会议而无需人工干预的用例。 在本章结束时,你将了解 Amazon Lex 的工作原理,更重要的是,如何将聊天机器人整合到你的 项目中。

技术要求

要设置你自己的聊天机器人应用程序,你需要访问 AWS 账户。 本书在其 GitHub 仓库中有一个专用文件夹,你可以在其中找到必要的代码片段来跟随 进行操作: https://github.com/PacktPublishing/AWS-Cloud-Projects/tree/main/chapter7/code

场景

在成功 构建和部署多个利用云和无服务器技术的应用后,你已经熟练掌握了这些现代架构。 然而,仍然需要大量时间和精力的一个领域是会议安排。 平均而言,你需要三次或更多的互动才能协调可用时间、讨论议程事项并最终确定每个会议的后勤安排。 这种来回沟通可能既乏味又耗时,经常使你从更 重要的任务中分心。

在探索如何优化和加速这些重复性流程时,你偶然发现了聊天机器人这一概念。 随着你对 AI 及其实际应用的兴趣日益增长,你意识到聊天机器人不仅仅是对话界面——它们可能处理特定的操作并且 自动化工作流。

创建一个聊天机器人来简化会议安排流程的想法引起了你的兴趣。 通过利用自然语言处理(NLP)和对话式 AI,一个设计良好的聊天机器人可以理解与会议相关的请求,并自动创建 会议请求。

受到提高效率潜力的激励,并希望能应用你的 AI 知识,你决定开始一个新项目:开发一个智能聊天机器人应用,改变会议安排的方式。 通过云技术、无服务器架构和 AI 能力的正确结合,你的目标是创建一个无缝的对话体验,自动化整个会议安排过程,节省宝贵时间,让你能够专注于更多 战略性任务。

需求

现在,你将开始收集该项目的需求。 这项练习与你在前几章所做的工作相一致,将帮助你设计应用程序并定义技术选择,以便进行 实现。

收集需求意味着要理解将与应用程序互动的用户角色、他们将执行的操作,以及从技术和 功能角度可能存在的任何限制。

总的来说,你仍然希望服务于与 你的应用互动的两类不同用户:

  • 最终用户/会议请求者:平台的一部分,公开可访问,配有聊天机器人帮助 安排会议。

  • 管理员/会议所有者:通过日历视图管理会议请求并查看已接受的 会议。

这些需求可以被翻译为功能需求、非功能需求和数据需求。

功能需求

在你定义好应用程序的用户角色后,你可以按用户类型细分功能需求:

  • 会议请求者

    • 应用程序应公开可用,并且不需要身份验证。

    • 响应式设计,以便任何人都可以通过任何设备与应用程序进行互动。

    • 你的聊天机器人应能够处理输入中的小错误。

    • 理解描述性日期的能力,如“明天”或“下周一”。

  • 会议拥有者

    • 列出待处理的会议请求,并具有批准或拒绝它们的能力。

    • 包括一个显示所有已批准会议的日历,管理员可以在其中进行导航。

    • 日历应支持按天、周和月不同的视图。

    • 管理员页面应仅通过身份验证访问。

    • 发生冲突的会议不应被聊天机器人拒绝;如果提议的时间段已被占用,应用程序应包含一个与会议请求相关的警告标志。

列出主要功能或能力是定义功能需求的有效方法,然而,通过视觉表示来补充它们可以显著提升价值并加速开发过程。考虑到这一点,你创建了两个简单的原型:一个是面向终端用户界面的,另一个是面向管理员界面的,如图 7.17.2 所示:

  • /home 看起来是这样的:

图 7.1 – 用户页面的 UI 原型

图 7.1 – 用户页面的 UI 原型

  • /admin 看起来是这样的:

图 7.2 – 管理员页面的 UI 原型

图 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"
};

会议之间没有关系,你也不预见需要运行复杂查询,因此你希望采用高性能的无服务器数据服务,支持执行所有 列举的操作。

架构模式

AI 解决方案有 潜力为各行各业的企业带来显著的价值,但通常,从零开始规划这些方案可能既费时又昂贵,并且复杂。 作为 AWS 解决方案库的一部分,AWS 拥有一个名为 人工智能解决方案 https://aws.amazon.com/solutions/ai/),其中包含了一组精选的 架构,可以帮助你加速 AI 的采用,并缩短将其嵌入当前产品的时间。 这些解决方案属于不同的领域,涵盖从预测分析和计算机视觉到个性化和推荐等多个领域。 当你在 AWS 上思考 AI 项目时,这是一个很好的起点。

更具体地说,有一个子部分 名为 聊天机器人与虚拟助手 (https://aws.amazon.com/solutions/ai/chatbots-virtual-assistants/) 它是语言理解领域的一部分,可以作为此项目的良好基础。

架构

要架构化你的 应用程序,关键是要定义组成它们的构建块。 从更高层次开始,你定义了一个由四个层组成的分层方法: 四个层:

  • 展示层:如何托管和提供 前端

  • 计算层:如何集成和执行 业务逻辑

  • 数据层:用于存储和检索 数据

  • 聊天机器人层:负责开发 聊天机器人的层

对于展示层,你决定采用与上一章相似的策略,并使用 React 开发单页面应用。 对于计算层,你从设计 API 开始,该 API 将作为前端与计算层中包含的业务逻辑之间的接口。 考虑到你的功能需求,你列出了需要执行的各种操作,并按照 图 7**.3中所示的方式结构化了你的 API:

  • GET /meetings:获取在指定时间窗口内已批准的会议列表 时间窗口

  • GET /pending:获取待处理的会议请求列表 会议请求

  • POST /chatbot:通过发送用户提示与聊天机器人进行交互 用户提示

  • PUT /status:将会议请求的状态更改为批准 或拒绝

图 7.3 – API 结构

图 7.3 – API 结构

图 7**.4 展示了你将在满足所有需求的基础上实施的架构。

图 7.4 – 你聊天机器人应用的 AWS 架构

图 7.4 – 你聊天机器人应用的 AWS 架构

前端将通过 S3 和 CloudFront 服务的结合进行托管和提供。 对于 API,您将利用 Amazon API Gateway HTTP API,使用与您列出的操作相映射的端点。 在审查数据需求后,您选择了 DynamoDB 作为您的数据存储。 最后一个组件是聊天机器人,经过研究后,您选择了 Amazon Lex 作为托管解决方案,因其具有成本效益、简便性以及与其他 AWS 服务如 Lambda 函数的整体集成,能够扩展您的聊天机器人的功能并在 您的代理下执行操作。

接下来将描述提到的每个服务及其主要优点和选择原因。

AWS 服务

丰富的可用服务范围中选择可能是一项艰巨的任务,充分理解需求对于做出明智的决策至关重要。 一些服务在前面的章节中已经介绍过,因此为了避免重复,我们将只突出当前用例中特有的优点,前提是这些优点之前未曾提及,并提供相关章节的参考,您可以在其中找到 详细解释。

Amazon CloudFront 和 Amazon 简单存储服务(S3)

我们已经 广泛 介绍了 Amazon S3 和 Amazon CloudFront 用于托管单页面应用程序的前端。 这两项 AWS 服务在前面提到的项目中发挥了至关重要的作用,如果您想回顾它们,建议查看 第二章 第三章

Amazon DynamoDB

Amazon DynamoDB 在 第三章 中介绍,作为第一版食谱共享应用程序的一部分。 如果您不熟悉该服务及其用途,建议查看 第三章 AWS 服务 部分。

Amazon Cognito、Amazon API Gateway 和 Amazon Lambda

Amazon API 网关 已被 用于 API 层,Amazon Lambda 用于计算层,Amazon Cognito 用于身份验证,这些都因其无缝集成在之前的项目中被使用。 如果你希望深入了解这些服务,可以参考 第四章

Amazon Lex

Amazon Lex 是一个 AWS 服务,它使得构建对话界面(称为聊天机器人或虚拟助手)变得更加简单。 作为 AWS AI 服务的一部分,Amazon Lex 简化并简化了创建用户可以通过语音或文本交流、理解其意图、以自然和人类的方式回应,并且最重要的是,根据用户请求执行操作的应用程序。 作为一种托管服务,使用 Amazon Lex 时,你不需要管理任何基础设施,因此,你也不需要为任何 未使用的容量支付费用。

使用 Amazon Lex,你可以利用超过 25 种语言和地区设置,截至目前,这 使得构建多功能聊天机器人变得更加容易,可以服务全球范围内的用户。

Amazon Lex 有一些基本概念,了解这些概念在配置 你的聊天机器人之前非常重要:

  • <st c="13935">AMAZON.FallbackIntent</st>,当无法识别其他意图时将会使用此意图。

  • 语句(Utterances):这些是配置每个意图时需要提供的一个或多个句子,聊天机器人将根据用户输入使用这些语句来识别意图。 例如,按照本章的案例,与“预定会议”意图相关的语句可能如下:

    • “我想预定 一个会议”

    • “帮我预定 一个会议”

  • 插槽(Slots):插槽是 Amazon Lex 需要从用户那里收集的信息,以便成功完成一个意图。 每个插槽都与一个插槽类型相关联,该类型定义了该插槽期望的数据种类。 AWS 已经提供了内置的插槽类型,如数字或日期,但你也可以通过创建自定义插槽类型来扩展它。 根据本章的示例,插槽的例子可以是安排会议所需的任何信息,比如与会者的姓名、日期、 开始时间以及会议的持续时间。

除了这些基础模块外,Amazon Lex 还与 AWS 生态系统中的其他服务进行集成,尤其是 Amazon Lambda。 在那里,你可以在达到特定状态时触发 Lambda 函数,例如,意图的完成。 在本项目的范围内,这种集成将使你能够触发 Lambda 函数,将会议详情 与用户对话过程中收集的 信息存储到你选择的数据存储中。

编码解决方案

在了解了架构和构成该架构的所有 AWS 服务之后,现在是时候根据所选的需求和 技术实现解决方案了。

克隆项目

第一步是克隆 与本书相关的 Git 仓库,正如在 技术要求 部分提到的。 如果你从上一章开始跟随,应该已经将其克隆到本地,但如果你现在才开始本章,检查是否能从 Git 克隆或下载为 ZIP 文件。

导航到 <st c="15920">chapter7/code</st> 文件夹,里面你会发现 两个子文件夹:

  • <st c="15982">frontend</st>:包含你的前端代码。

  • <st c="16030">platform</st>:包括部署应用主基础设施的 CloudFormation 模板。

解决方案部署

首先通过 <st c="16259">/platform</st> 文件夹中找到的 CloudFormation 模板部署你的所有应用基础设施。 表 7.1 列出了模板创建的所有资源,这些资源对应于 图 7**.4中展示的架构。

模板 Ch7-application-template.yaml
前端 CloudFront 和 S3
后端 DynamoDB
认证 Cognito 用户池
后端 一个 HTTP API,具有 四个端点四个 Lambda 函数,每个端点一个一个 Cognito 用户池
数据存储 DynamoDB
聊天机器人 One Lex 聊天机器人一个由 聊天机器人触发的 Lambda 函数

表 7.1 – CloudFormation 模板详情

从控制台,前往 CloudFormation 服务,网址为 https://console.aws.amazon.com/cloudformation/ 并选择您想要托管 应用程序的 AWS 区域。

重要提示 – 为此项目选择 AWS 区域

服务可用性是选择 AWS 区域用于项目的原因之一。 您将用于聊天机器人的 Amazon Lex 服务就是一个不可在所有 AWS 区域中使用的服务示例。 尝试在没有 Amazon Lex 服务的区域部署 CloudFormation 模板将导致错误。 您可以在以下链接查看支持的 AWS 区域完整列表: https://docs.aws.amazon.com/general/latest/gr/lex.html

区域选择可以通过位于右上角的下拉菜单完成,如 图 7**.5所示。

图 7.5 – 控制台访问 CloudFormation 和 AWS 区域下拉菜单

图 7.5 – 控制台访问 CloudFormation 和 AWS 区域下拉菜单

要部署与此项目相关的 CloudFormation 堆栈,请按照以下步骤操作:

  1. 点击 创建堆栈

  2. 前提 – 准备模板 部分,选择 选择一个 现有模板

  3. 指定模板 部分,选择 上传模板文件

  4. 点击 选择文件

  5. <st c="18127">chapter7/code/platform</st> 文件夹中选择模板。

  6. 点击 下一步

您的 创建堆栈 窗口应该如下所示 图 7**.6

图 7.6 – CloudFormation 创建堆栈表单

图 7.6 – CloudFormation 创建堆栈表单

接下来,您将被要求配置 CloudFormation 堆栈中的参数。在表 7.2中,您可以找到每个参数的详细解释。

参数 描述
APIName 这是项目的 API 名称。
UserEmail 这是您希望与用户关联的电子邮件地址。必须是有效的电子邮件地址,因为您稍后将收到临时密码并进行验证。
UserPoolName 这是您为 Cognito 用户池命名的名称。
用户名 在您的应用中,稍后您将使用此用户名进行登录。

表 7.2 – CloudFormation 模板参数

图 7.7 显示了填写完所有参数后,堆栈配置应呈现的样子。所示的值仅为示例,您的值可能会有所不同。

图 7.7 – CloudFormation 中的堆栈参数

图 7.7 – CloudFormation 中的堆栈参数

您可以点击下一步,继续到最后一页,系统会要求您确认创建 IAM 角色。此通知与将要创建并与每个 Lambda 函数关联的角色有关,以提供与 DynamoDB 表进行交互的最小权限,其中存储了会议数据。

点击提交,然后等待堆栈状态变化为CREATE_COMPLETE,如图 7.8所示。

图 7.8 – CloudFormation 堆栈创建状态

图 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 终端点

为了简化获取这些值的过程,我们已经将它们包含在我们的 Outputs 部分中 CloudFormation 模板。 要访问它,请按照 以下步骤:

  1. 转到 CloudFormation 控制台 https://console.aws.amazon.com/cloudformation/

  2. 单击 您的堆栈。

  3. 在右侧菜单中,选择 Outputs 选项卡,如 图 7**.9所示。

图 7.9 – CloudFormation 堆栈输出选项卡

图 7.9 – CloudFormation 堆栈输出选项卡

表 7.3 堆栈输出与 配置文件进行映射:

文件 参数名称 Cloudformation 堆栈输出
<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>

表 7.3 – CloudFormation 输出与 aws-exports.ts 参数之间的映射

4. 保存 文件。

最终,您的配置文件应如下所示:

configs.tsx

 export const API_URL = '[ApiUrl CloudFormation Output]';

aws-exports.tsx

 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> build/<st c="24627">或</st>dist/<st c="24636">,并且会在</st> ` 目录下创建,该目录位于 前端应用程序的根目录中。

最后一步是将构建文件夹复制到 S3,按以下说明操作:

  1. 首先,你需要找到之前使用 CloudFormation 模板创建的 S3 存储桶。 存储桶的名称应以 <st c="24931">frontend-chapter-7-</st> 开头,后跟一串随机字符(例如, <st c="25003">frontend-chapter-7-XXXXX</st>)。

  2. 点击存储桶的名称以 打开它。

  3. 在 S3 存储桶中,找到并点击 上传 按钮。 此操作将使你能够将文件从本地机器传输到 S3 存储桶。

  4. 点击 <st c="25258">dist</st> 文件夹,在你的本地机器上。 选择文件夹中的所有文件并确认(你应该在 <st c="25390">dist</st> 文件夹的根目录下看到两个文件: <st c="25403">index.html</st> <st c="25418">penguin.png</st>)。

  5. 接下来,点击 <st c="25471">dist</st> 文件夹,在你的本地机器上,选择 <st c="25517">assets</st> 文件夹, 并确认。

  6. 现在你的 S3 上传 窗口应该如下所示: 图 7**.10

图 7.10 – 上传到 S3 的前端文件

图 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>

  • 您可能在应用程序中包含的静态文件,例如图像

  1. 向下滚动到页面底部并点击Upload

您现在已经完成了应用程序的部署和配置过程,可以继续进行聊天机器人设置

Amazon Lex 配置和构建

您已经几乎完成,剩下的唯一步骤是配置您的聊天机器人。大部分配置已经通过 CloudFormation 模板完成,您只需进行 lambda 函数集成,以根据对话执行相应操作。

为了完成这一步,请按照以下步骤操作:

  1. 转到您部署 CloudFormation 堆栈的区域中的 Amazon Lex 控制台,网址为console.aws.amazon.com/lexv2/home?

  2. 在左侧菜单中,选择Bots

  3. Bots列表中,选择MeetyBot,如图 7.11所示。

图 7.11 – 选择 Amazon Lex 机器人

图 7.11 – 选择 Amazon Lex 机器人

  1. Deployment部分,选择Aliases,并点击TestBotAlias,如图 7.12所示。

图 7.12 – Amazon Lex 机器人别名部分

图 7.12 – Amazon Lex 机器人别名部分

  1. Languages列表中,选择English (US)

  2. <st c="27885">bot-function-meety</st> 作为 源, <st c="27923">$LATEST</st> 作为版本,如 图 7**.13所示。

  3. 点击保存

图 7.13 – 选择 Lambda 函数用于您的聊天机器人

图 7.13 – 选择 Lambda 函数用于您的聊天机器人

最后一步是配置函数的触发条件,当 BookMeeting 意图完成时触发该函数。 为此,执行以下操作:

  1. 在左侧菜单中,选择意图 英语 (美国)** 菜单下。

  2. 点击BookMeeting 意图。

  3. 滚动到完成 部分,并点击切换按钮将其激活。 这样可以确保每次此意图被完成时,Lambda 函数都会被触发。 您可以在图 7**.14中看到预期状态。

图 7.14 – Amazon Lex 聊天机器人 – 完成配置

图 7.14 – Amazon Lex 聊天机器人 – 完成配置

  1. 点击 保存意图 在右下角。

  2. 选择构建 在右上角。

    您的聊天机器人构建过程应该需要大约两分钟。 等待直到您看到绿色横幅和成功消息,如 图 7**.15所示。

图 7.15 – 来自 Amazon Lex 构建过程的成功消息

图 7.15 – 来自 Amazon Lex 构建过程的成功消息

恭喜! 您已经成功完成了应用程序的部署和配置, 现在应该已经拥有一个完全功能的 项目。 是时候进行测试了!

测试并探索您的应用程序

到目前为止,一切 应该已经准备好进行测试。 要访问您的应用程序,请执行 以下操作:

  1. 前往 CloudFront 控制台 https://console.aws.amazon.com/cloudformation/

  2. 选择你在本章中部署的堆栈。

  3. 转到输出选项卡。

  4. 点击 <CloudFrontDistributionUrl> 值,如图 7.16所示。

图 7.16 – CloudFormation 输出选项卡

图 7.16 – CloudFormation 输出选项卡

这应该会将你重定向到你的应用程序,预计会像图 7.17那样。

图 7.17 – 应用首页

图 7.17 – 应用首页

这是用户可以与聊天机器人互动以安排会议的页面。通过点击聊天图标,你将能够启动对话。

AWS 服务部分中讨论的那样,表达式是预定义在意图中的,用于帮助识别和理解用户的请求。

本章的 CloudFormation 模板创建了一个由三个意图组成的聊天机器人:

  • StartMeety:这是第一个负责欢迎消息的意图。

  • BookMeeting:负责预定会议的意图。

  • FallbackIntent:当无法基于用户输入识别其他意图时触发的默认意图。

探索并自定义你的聊天机器人

要查看每个意图的表达、响应和逻辑,请执行以下操作:

  1. 进入你部署了 CloudFormation 堆栈的区域的 Amazon Lex 控制台 console.aws.amazon.com/lexv2/home?

  2. 在左侧菜单中,选择Bots

  3. 选择MeetyBot

  4. 英语(美国)下,点击意图

    你的控制台应该像图 7.18那样。

图 7.18 – Amazon Lex 机器人意图部分

图 7.18 – Amazon Lex 机器人意图部分

  1. 点击StartMeety意图。

  2. 向下滚动到样本话语部分,查看该意图的预定义话语,如图7.19所示。

图 7.19 – Amazon Lex 聊天机器人意图样本话语

图 7.19 – Amazon Lex 聊天机器人意图样本话语

这些是当前用于识别 StartMeety 意图的可用话语,但你可以自由添加其他话语或根据需要自定义现有的。更改后,请确保保存该意图并重新构建聊天机器人,正如前一节所述。

对 BookMeeting 意图执行相同的操作。在这种情况下,Amazon Lex 期望不同的样本话语,而且与 StartMeety 意图不同,它还包括五个槽位,这些是实现该意图所需的数据元素:

  • FullName:与会者的姓名

  • MeetingDate:用户希望见面的日期

  • MeetingStime:会议的开始时间

  • MeetingDuration:会议的持续时间,应该是 30 分钟或 60 分钟

  • AttendeeEmail:用户希望用于联系的电子邮件

我们建议花一些时间探索每个槽位以及聊天机器人用来请求它们的提示。如前所述,欢迎根据你的偏好自定义提示和槽位。

在熟悉了聊天机器人的所有配置后,你可以继续并在你的应用程序中开始一次对话以预定会议。

测试你的聊天机器人

配置好你的聊天机器人及其意图后,现在是时候在你的应用程序中测试其行为了:

  1. 从使用在 StartMeety 意图中定义的某个话语开始,并注意聊天机器人的响应。

图 7.20 – 来自 StartMeety 意图的初始聊天机器人响应

图 7.20 – 来自 StartMeety 意图的初始聊天机器人响应

在这里,你可以看到,根据与 StartMeety 意图的某个样本话语匹配的输入,聊天机器人响应了一个欢迎消息,正如在该意图中配置的那样。

在这个例子中,你可以看到聊天机器人识别并确认了该意图,并作出了相应的回复。

  1. 接下来,你可以使用 BookMeeting 意图中定义的某个语句进行响应,这样聊天机器人就能 识别该语句。

图 7.21 – BookMeeting 意图对话流程

图 7.21 – BookMeeting 意图对话流程

聊天机器人识别了意图,并开始提问以收集槽值,目的是 实现该意图。 请注意,聊天机器人能够根据 明天 的语句推断出 当前日期。

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

图 7.22 – 聊天机器人确认提示

图 7.22 – 聊天机器人确认提示

  1. 确认后,你的意图达到了实现状态,并且根据机器人配置, <st c="36295">bot-function-meety lambda</st> 函数被触发。 lambda 函数包含三个 主要操作:

    • 根据提供的槽值,评估是否有任何已接受的会议可能与提议的会议时间发生冲突。

    • 创建会议请求并将其存储在 DynamoDB 表中。

    • 向最终用户发送自定义消息,确认 会议请求。

图 7.23 – 聊天机器人最终响应

图 7.23 – 聊天机器人最终响应

如果你想要 详细查看 lambda 函数代码,请按照 以下步骤进行操作:

  1. 前往你部署 CloudFormation 堆栈的区域中的 AWS Lambda 控制台 ,网址为 https://console.aws.amazon.com/lambda/

  2. 在左侧菜单中, 选择 函数

  3. 点击 <st c="37139">bot-function-meety</st> 函数。

  4. 向下滚动至 代码源 部分,你将找到所有包含在此 lambda 函数中的代码。

您已经检查了用户如何通过与您的聊天机器人对话发起会议请求。 现在,是时候深入了解 管理员 页面,在那里您可以查看日历中的已接受会议并管理待处理的 会议请求。

通过管理员门户管理会议请求

到目前为止,您已经测试了您的聊天机器人,尤其是其通过类人对话处理会议请求的能力,现在您将探索如何管理已创建的 请求。

在部署 CloudFormation 堆栈的过程中,您应该已经收到一封类似于 图 7**.24 的电子邮件,里面包含了您的用户名和临时密码。 这将用于 完成身份验证过程并访问 管理员 页面。

图 7.24 – 带有临时密码的电子邮件

图 7.24 – 带有临时密码的电子邮件

要访问管理员门户并管理会议请求,请按照以下步骤操作:

  1. 在您的应用程序主页上,点击 登录

  2. 填写 用户名 密码 字段,输入您收到的电子邮件中的值 并确认。

  3. 设置一个新密码 并继续。

  4. 选择您的电子邮件并点击 验证。您现在将收到一封带有 临时代码 的电子邮件。

  5. 从您的电子邮件中复制验证码并将其粘贴到 确认表单中。

您现在已经完成了身份验证设置,您的界面应如下所示: 图 7**.25

图 7.25 – 管理会议请求的管理员页面

图 7.25 – 管理会议请求的管理员页面

管理员页面分为两个 不同的部分:

  • 会议日历,显示所有已接受的 会议。

  • 待处理会议部分,展示了等待 您操作的会议请求列表。

操作 列中,你有两个可用按钮: 接受 拒绝。点击 接受 按钮会将会议请求的状态更新为 已接受,而选择 拒绝 按钮则会将其标记为 已拒绝。为了观察功能,尝试接受一个会议请求,并观看它出现在 会议 日历 中。

一个功能要求是,当新的会议请求与之前接受的会议时间重叠时,你应该收到通知。 要测试这个行为,请执行以下步骤:

  1. 在浏览器中打开一个新标签,访问主页(你可以复制来自 <st c="40274">/admin</st>)的 URL)。

  2. 尝试在与已接受会议相同的时间段安排一个新会议。

  3. 刷新 管理员 页面以显示新的 会议请求。

你可以验证,新请求现在会显示一个警告图标和一个工具提示,表示它与之前接受的会议冲突,如在 图 7**.26中所示。

图 7.26 – 会议冲突警告

图 7.26 – 会议冲突警告

现在,你已经有了一个完全可操作的 Web 应用程序,配备了一个能够根据与终端用户对话安排会议的聊天机器人。 此外,你还可以查看包含所有过去会议的日历,并管理你即将到来的会议日程。

清理

符合你的 非功能性要求,架构中的所有组件都采用按需计费模式,这意味着你只需为使用的部分付费。 然而,如果你让应用程序长时间运行,可能会产生不必要的费用。 因此,建议在不再使用时清理你的基础设施。 由于你是通过基础设施即代码(IaC)部署应用程序的,清理过程十分简单,包含 两个步骤:

  1. 清空 S3 存储桶:

    1. 进入你的 AWS 账户中的 S3 控制台。

    2. 选择你的前端 S3 存储桶(存储桶的名称应以 <st c="41671">frontend-chapter-7-</st>开头,后跟一个 随机字符串)。

    3. 点击 ;这将删除你存储桶中的所有内容。 内容。

图 7.27 – 清空 S3 存储桶的过程

图 7.27 – 清空 S3 存储桶的过程

  1. 删除 CloudFormation 堆栈:

    1. 在你的 AWS 账户中导航到 CloudFormation 服务控制台,确保你在最初部署时所在的相同区域。 区域。

    2. 选择你创建的堆栈。 堆栈。

    3. 点击 删除,如 图 7**.28所示。

图 7.28 – CloudFormation 堆栈删除

图 7.28 – CloudFormation 堆栈删除

通过这些操作,应删除为本章节创建的所有资源。 资源。

虽然这个项目 为你的聊天机器人应用程序提供了坚实的基础,但还有一些增强功能和未来的考虑事项,可以进一步提高其功能和用户体验。 这些将在 下一部分中介绍。

未来的工作

恭喜你成功实现了聊天机器人应用程序! 你已经迈出了利用 AWS 构建智能对话界面的重要一步,并且现在你拥有了将这项技术融入未来项目的基础。 这个项目代表了一个初始版本。 我们希望提出一些改进建议和可以实施的想法,帮助你扩展和丰富 你的聊天机器人。

扩展你的聊天机器人执行的操作

当前的聊天机器人 能够检测用户尝试安排会议时的冲突,但可以考虑通过实现逻辑来扩展其功能,以向用户建议可用的时间段。 此外,你可以引入一个调度窗口,例如从早上 9 点到下午 5 点,只接受该时间段内的会议请求:

 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> lambda 函数,以便将这些想法或您设想的任何其他增强功能集成到 您的聊天机器人中。

多语言支持

目前,您的 聊天机器人仅支持英语,但 Amazon Lex 提供了支持多语言的功能。 作为未来的增强功能,您可以配置您的聊天机器人支持额外的语言,使其更容易为来自不同语言背景的用户所使用。 您可以在 AWS 文档中找到如何实现的说明 ,网址为 https://docs.aws.amazon.com/lexv2/latest/dg/add-language.html

为不同的会话维护用户档案

CloudFormation 部署包括一个名为 <st c="45609">chatbot-meety</st>的 lambda 函数,负责通过发送用户输入并接收响应与您的 Amazon Lex 聊天机器人进行交互。 与 Amazon Lex 交互时的参数之一是 <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 服务(如 Amazon Lex、Lambda、API Gateway 和 DynamoDB)的强大功能,您创建了一种无缝对话体验,自动化了整个会议安排工作流程。 具体而言,在聊天机器人开发中,您探索了 Amazon Lex 的复杂性,包括意图、话语和插槽,并学习了如何定制和扩展聊天机器人的功能。 总体而言,在前三章中,您已经获得了人工智能领域的知识,并学会了如何使用 AWS 服务采用这些技术。

在下一章中,您将探索业务智能领域,并学习如何分析 点击流数据。

第九章:构建商业智能应用程序

在当今的数字时代,企业从各种来源生成大量数据,包括网站、移动应用程序和在线交易。其中一个数据来源是点击流数据,它记录了用户在网站或应用程序上的交互和活动。分析点击流数据可以提供有关用户行为、偏好和痛点的宝贵见解,从而使企业能够量身定制其产品、服务和营销策略,更好地满足客户需求。

在本章中,我们将探讨如何使用原生 AWS 服务构建商业智能应用程序,分析点击流数据。我们将覆盖整个过程,从数据采集和存储到数据转化、查询和可视化。

总结:本章将按以下顺序涵盖以下主题:

  • 你将要构建的内容——一个商业智能应用程序

  • 你将如何构建它——使用 Glue、Athena 和 QuickSight

  • 实际构建过程——通过 CloudFormation 并使用 AWS 控制台

  • 如何改进解决方案——自动化 ETL 管道和数据生命周期管理

本章结束时,你将获得使用 AWS 服务分析点击流数据,构建端到端商业智能应用程序的实践经验。

技术要求

要跟随本章内容并实现自己的商业智能应用程序,你需要拥有一个 AWS 账户。此外,本书在 GitHub 的专用文件夹中有一个文件夹,你可以在其中找到所有基础设施部署所需的代码以及本章中将使用的其他文件:github.com/PacktPublishing/AWS-Cloud-Projects/tree/main/chapter8/code

场景

你是一个电子商务网站的所有者,销售从电子产品到时尚商品等各种产品。你的网站已经运营了几年,并且随着时间的推移,你已经建立了一个相当可观的客户群。然而,你注意到你的转化率(即访问者中完成购买的比例)一直停滞不前,你不确定导致这一趋势的原因。

为了提高转化率并改善您网站的整体用户体验,您决定分析用户生成的点击流数据。 点击流数据 指的是 用户在您网站上的互动和活动记录,例如访问的页面、点击的链接、查看的产品以及在每个页面上停留的时间。

通过分析这些数据,您的目标是获得有关用户行为和偏好的有价值洞察,这可以帮助您识别潜在的瓶颈、痛点以及您网站用户体验中需要改进的地方。 此外,您希望揭示出一些模式和趋势,从而指导您的营销和产品开发策略,进而提高转化率 和收入。

需求

正如您到目前为止所做的那样,收集需求应作为起点。 考虑到当前情境,您的目标是分析点击流数据,并且有两类具有不同背景和技术能力的用户,希望从 您的数据中提取信息:

  • 业务分析师:业务分析师对创建和运行 SQL 查询没有信心,他们寻找更直观的替代方法来探索 数据。

  • 技术用户:技术用户熟悉并擅长使用 SQL,想要能够运行复杂的查询以回答 特定问题。

了解用户画像并理解他们如何与您的应用程序交互,是定义功能性和 非功能性需求的关键。

功能需求

功能需求 概述 提出的解决方案必须提供的基本特性、功能和能力,以满足期望的目标。 在这种情况下,功能需求应该做到 以下几点:

  • 点击流数据 中提取信息

  • 支持地理分析和 用户分布

  • 支持按需更新,以获取最新的 信息

  • 能够为技术用户运行临时 SQL 查询 的能力

  • 具有无限期存储点击流数据的能力 数据

非功能性需求

非功能性需求 描述 拟议解决方案应遵循的定性特征和约束,以确保其整体质量和性能。 在这种特定情况下,非功能性需求规定了以下内容:

  • 有限的 维护工作量

  • 成本效益

架构模式

AWS 架构 中心(https://aws.amazon.com/architecture/)提供了一套经过验证的解决方案,这些方案由 AWS 和 AWS 合作伙伴的专家共同开发和构建,可以作为你项目的起点。 在这个使用案例中,AWS 提供了一种来自 AWS 解决方案库的解决方案 名为 AWS 上的 Clickstream 分析 https://aws.amazon.com/solutions/implementations/clickstream-analytics-on-aws/。这个解决方案专注于从网站和移动应用程序中收集、摄取、分析和可视化点击流数据,这与该项目的 范围一致。

蓝图和解决方案应当是完全可行的,因为 AWS 会定期进行修订,但每个项目通常都有其独特性,可能需要一定程度的定制。 无论如何,这些始终是宝贵的资源,并且在你从零开始启动项目时,尤其是在 架构 设计阶段,将节省不少时间。

架构

正如你从本书的第一个项目开始所做的那样,你采用了自上而下的方法,从需求开始,这些需求应完全中立,描述你应用程序中的功能和约束,直到支持这些功能的具体服务。 这些服务支撑着整个系统。

你的商业智能应用程序可以分解为三层,如 图 8**.1所示:

图 8.1 – 商业智能应用程序层

图 8.1 – 商业智能应用程序层

让我们简要回顾一下 细节:

  • 摄取层:此层将来自各种来源的数据收集并导入到 系统中。

  • 处理层:此层准备、清洗并转换数据 以便进行分析。

  • 可视化层:以一种视觉吸引力强且交互性强的方式展示处理后的数据,供探索 和洞察。

理解各层的目的以及它们在整体应用中所扮演的角色是定义适合集成的服务的关键。 在它们之内。

简单性和最低的维护努力是您架构的两个主要支柱,考虑到您希望服务的两种角色。 您将需要两种方式来与数据进行交互或探索。 此外,您不希望重复数据并为每个与点击流数据交互的角色创建不同的数据源;因此,针对数据存储,您希望采用一种足够灵活的解决方案,既能与类似 SQL 的引擎进行探索,又能与商业智能解决方案 进行可视化。

经过一些研究后,您开始探索 Amazon QuickSight 作为可视化层,使用 Amazon Athena 执行 SQL 查询以分析点击流数据。 为了存储数据,您决定选择 Amazon S3,因为它与 Amazon Athena 和 Amazon QuickSight 都可以集成,且在存储项数上没有任何限制。 对于数据转换,您希望选择一种不需要任何基础设施 维护的解决方案,理想情况下是一个可以利用您现有 Spark 知识的工具;因此,您选择了 AWS Glue 来处理 数据管道。

考虑到上述所有要点,您制作了一个初步架构,如下所示: 图 8**.2。总结来说,文件被导入到 <st c="7884">/raw</st> 存储桶的前缀中,并由 Glue 处理,存入相同存储桶的 <st c="7941">/results</st> 前缀。 技术用户使用 Athena 通过类似 SQL 的语法查询数据,而业务用户则通过 QuickSight 获取可视化的洞察。

图 8.2 – 适用于您的商业智能应用的 AWS 架构

图 8.2 – 适用于您的商业智能应用的 AWS 架构

现在您已经概述了高级架构,让我们深入了解您选择的 AWS 服务, 以构建此解决方案,并了解它们如何与之前设定的需求对接。

AWS 服务

如图8.2所示,该架构由四个主要服务组成。在本节中,你将探索每个构建块,并理解它们如何与要求对齐。

亚马逊简单存储服务(S3)

在你的商业智能应用架构中,你需要一个数据存储来持久化大量的对象或事件,你发现 S3 可以成为数据湖的理想基础解决方案。S3 的设计目标是提供高耐久性,耐久性高达 99.999999999%(11 个 9),确保即使在面对意外事件或基础设施故障时,数据依然完整且可访问,同时提供高可用性,保证为分析和报告目的提供可靠的解决方案,这也是数据湖的预期需求。

此外,可扩展性和成本效益被强调为要求的一部分,而 S3 符合这两个原则,因为它可以存储和分析 PB 级的数据,且无需担心容量限制或基础设施配置,通过在需要时自动扩展,采用按需付费模式。

亚马逊 S3 是支持数据湖的最佳选择,你可以通过阅读以下博客了解更多原因:https://aws.amazon.com/blogs/big-data/tag/data-lake/

AWS Glue

AWS Glue 是一个无服务器的数据集成服务,使得数据的发现、准备和结合变得更加容易。在你的商业智能应用架构中,AWS Glue 有两个主要用途:提取、转换和加载(ETL)作业和 Glue 数据目录。

ETL 是数据集成中的关键过程,其中从各种源提取数据,转化为所需的格式,然后加载到数据存储中进行分析或报告;在这种情况下,它被加载到 S3 中。AWS Glue 提供了一个无服务器的 Apache Spark 环境来运行 ETL 作业,无需配置或管理服务器。

AWS Glue ETL 作业具有高度的可扩展性和成本效益,因为您只需为作业执行过程中使用的资源付费。此外,Glue 会自动配置和管理底层的 Apache Spark 集群,消除了手动集群管理的需要。

Glue 数据目录是一个集中的存储库,用于存储关于数据源的元数据,并作为贵公司所有数据的唯一可信来源。

在您的应用程序中,Glue 数据目录用于维护您的数据源的元数据定义,即基于 S3 构建的数据湖。

Glue 数据目录与其他 AWS 服务无缝集成,例如 Amazon Athena,它是您架构的一部分,使您能够基于存储在目录中的元数据访问和查询数据。

Amazon Athena

Amazon Athena是一个交互式查询服务,使您可以使用标准 SQL 轻松分析存储在 Amazon S3 中的数据。通过 Athena,您可以直接针对存储在 S3 中的数据运行临时查询或预定义的 SQL 脚本,而无需将数据加载或转换到单独的数据存储。

它的无服务器方式消除了配置和管理基础设施的需要,让您可以专注于数据分析,而不是基础设施管理。

如在AWS Glue部分所述,Athena 与 AWS Glue 数据目录无缝集成,通过引用 Glue 数据目录中的元数据,Athena 可以理解您在 S3 中的数据结构和位置,使您能够使用 SQL 查询数据,而无需手动定义模式。

对于在需求部分中介绍的技术概况,Athena 非常适合,因为它将使他们能够以临时的方式运行查询并回答复杂的问题。

Amazon QuickSight

Amazon QuickSight是一个基于云的商业智能服务,使组织能够快速轻松地创建和提供深刻的可视化和仪表板。在您的商业智能应用架构中,您可以利用 QuickSight 作为一个强大的数据可视化和报告工具,赋能您的业务用户通过交互式和富有视觉吸引力的仪表板进行数据探索和决策,无需技术技能。

QuickSight 无缝集成了多种数据源,包括 Athena,消除了复杂的数据迁移或转换过程的需求。 通过利用 QuickSight 与 Athena 和 Glue 数据目录的集成,你可以轻松地可视化并探索存储在 S3 数据湖中的数据,从而更容易地 获得洞察。

总的来说,QuickSight 解决了在 需求 章节中描述的非技术性用户的数据探索需求。

编码解决方案

本项目分为两部分;第一部分是数据工程部分,你将构建一个端到端的工作流来收集、转换和加载数据,第二部分是你将在 QuickSight 中构建你的第一个仪表板。

第一部分 – 克隆项目

首先,你需要 克隆与本书相关的 Git 仓库,正如在 技术要求 章节中提到的。 如果你已经跟随之前的章节进行操作,你应该已经在本地拥有该仓库,但如果不是这种情况,你可以直接从 Git 克隆它,或者如果你更喜欢,可以下载 ZIP 文件。

导航到 <st c="13899">chapter8/code</st> 文件夹,在里面你将找到 两个子文件夹:

  • <st c="13962">平台</st>:这包含了一个 CloudFormation 模板,用于部署你的应用程序的主要基础设施。

  • <st c="14071">辅助文件</st>:这包含了一组将在整个章节中使用的辅助文件。

第二部分 – 解决方案部署

第一步是 部署必要的基础设施来支持你的应用程序。 与前面的某些章节一样,这可以通过在 <st c="14382">/platform</st> 文件夹中找到的 CloudFormation 模板来完成。 表 8.1 列出了由你的模板创建的所有资源,这些资源映射到 图 8**.2中展示的架构。

模板 ch8-application-template.yaml
网络配置 1 VPC1 互联网网关1 公有子网
数据存储 Amazon S3
数据处理 1 Glue 数据库1 Glue 表1 Glue 作业
其他 1 个参数在 参数存储1 EC2 实例

表 8.1 – CloudFormation 模板详情

如同在前面章节中所做的那样,您将使用 CloudFormation 来配置支持 您的应用程序所需的基础设施:

  1. 从控制台,前往 CloudFormation 服务 https://console.aws.amazon.com/cloudformation/ 并在右上角选择您希望托管应用程序的 AWS 区域(俄勒冈州,在我们的案例中),如 图 8**.3所示。

图 8.3 – 访问 CloudFormation 控制台

图 8.3 – 访问 CloudFormation 控制台

  1. 点击创建堆栈

  2. 先决条件 – 准备模板 部分,选择选择现有模板

  3. 指定模板 部分,选择上传模板文件

  4. 点击选择文件

  5. 选择模板(<st c="15622">ch8-application-template.yaml</st>)来自<st c="15664">chapter8/code/platform</st>文件夹。

  6. 点击下一步

您的创建堆栈 窗口应当如 图 8**.4所示。

图 8.4 – CloudFormation 堆栈创建屏幕

图 8.4 – CloudFormation 堆栈创建屏幕

接下来,您将被要求配置 CloudFormation 堆栈中的参数。 表 8.2中,您可以找到关于 每个参数的详细解释。

参数 描述
<st c="17085">GitRepoURL</st> 您想要使用的 Git 仓库。 默认情况下,您将拥有与本书相关联的仓库,但如果您将其 fork 到自己的 Git 账户中,您可以相应地进行更改。
<st c="17282">InstanceType</st> 您希望为 EC2 实例选择的实例类型。 您可以保持默认设置,也可以在四个 可选项中选择。
<st c="17426">LatestAmiId</st> 您想用于 EC2 实例的 Amazon 机器镜像。 您可以保持默认 不变。

表 8.2 – CloudFormation 模板参数

您可以继续到最后一页,在该页上您将被要求确认 IAM 角色的创建 才能继续。 此通知会出现,因为模板将尝试创建两个 IAM 角色:

  • 与 AWS Glue 作业关联的 IAM 角色,授予读取和写入文件到 S3 所需的权限

  • 附加到 EC2 实例的 IAM 角色,在该实例上执行脚本,以提供足够的权限将特定文件复制到您的 S3 桶

点击 提交 并等待堆栈状态更改为 CREATE_COMPLETE,如 图 8**.5所示。

图 8.5 – CloudFormation 堆栈创建状态

图 8.5 – CloudFormation 堆栈创建状态

这意味着 所有资源都已配置完毕,您可以 继续进行。

第三部分 – 点击流事件生成器

与任何商业智能应用程序一样,进一步处理所需的第一个要素是数据。 在您的案例中,您还没有可以处理的数据;因此,在第一部分,我们创建了一个事件生成器,您可以使用它按需生成点击流事件。 要执行事件生成器,请按照以下步骤操作:

  1. 前往 CloudShell 控制台 访问 https://console.aws.amazon.com/cloudshell

  2. 这将打开一个新的终端窗口,您可以在其中执行脚本。 如果您没有准备好任何环境,请点击 打开 [AWS-Region] 环境,如 图 8**.6所示:

图 8.6 – CloudShell 终端创建

图 8.6 – CloudShell 终端创建

到最后,您应该看到一个全新的终端窗口,如 图 8**.7所示:

图 8.7 – CloudShell 终端窗口

图 8.7 – CloudShell 终端窗口

这个新终端将用于运行命令,生成事件并将其发送到你最近创建的 S3 存储桶。

作为部署过程的一部分,我们生成了一个包含所有需要在终端中运行的命令的文件。要访问它,请按照以下步骤操作:

  1. 前往 S3 控制台,console.aws.amazon.com/s3

  2. 选择你最近创建的 S3 存储桶。它应该被命名为chapter-8-clickstream-XXXXXXXX

  3. 点击aux文件夹。

  4. 选择instructions.txt文件。

  5. 点击下载,如图 8.8所示。

图 8.8 – instructions.txt 文件访问

图 8.8 – instructions.txt 文件访问

  1. 打开文件。在文件中,你应该能看到三条命令:

     git clone GIT_URL_DEFINED_IN_THE_CLOUDFORMATION_PARAMETER
    cd GIT_NAME/chapter8/code/aux
    pip install -r requirements.txt
    

    这三条命令将在你的 CloudShell 环境中本地克隆 Git 仓库。

  2. 接下来,导航到/aux文件夹,那里存放着你的事件模拟器文件(generator.py),然后使用pip安装所有需要的库。

  3. instructions.txt文件中复制命令,并粘贴到 CloudShell 终端中。

  4. 运行以下命令:

    <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 存储桶中的持久性,请按照以下步骤操作:

  1. 前往 S3 控制台,console.aws.amazon.com/s3

  2. 选择你最近创建的 S3 桶。 它应该被命名为 <st c="22128">chapter-8-clickstream-XXXXXXXX</st>

  3. 点击 <st c="22173">raw</st> 文件夹。

    你的 <st c="22190">/raw</st> 文件夹应该像 图 8**.9 一样,包含与生成的总事件数相对应的 JSON 文件。

图 8.9 – 存储在 S3 中的事件数据

图 8.9 – 存储在 S3 中的事件数据

你可以多次运行该脚本,只需执行以下命令:

<st c="23401">$ python3 generator.py</st>

现在,你已经生成并存储了原始数据,是时候应用 转换操作了。

第四部分 – Glue ETL 作业

到目前为止,你已经拥有一组代表 你生成的点击流事件的文件,但这些事件通常带有一种结构,不适合分析用途。 因此,现在是时候运行你的 ETL 作业,并对你的点击流数据进行一些修改,以支持分析工作负载和 信息提取:

  1. 前往 Glue 控制台 ,网址为 https://console.aws.amazon.com/glue

  2. 点击左侧菜单中的 Visual ETL 选项。

  3. <st c="24009">chapter8-gluejob</st> 中点击 运行作业,如 图 8**.10所示。

图 8.10 – Glue ETL 作业运行过程

图 8.10 – Glue ETL 作业运行过程

在作业运行时,重要的是要记住正在执行的具体操作:

  1. 读取 S3 桶中 <st c="24395">/raw</st> 文件夹内的所有事件文件。

  2. 读取一个包含 地理信息的参考文件。

  3. 更改每个数据集的架构。

  4. 将两个数据集 合并为一个。

  5. 选择一部分列。

  6. 基于输出数据集,创建一个单一的 <st c="24593">.csv</st> 文件。

  7. 将输出 <st c="24651">.csv</st> 文件保存在你的 S3 桶中的 <st c="24686">/</st>``<st c="24687">results</st> 文件夹内。

  8. 将所有点击流事件从 <st c="24744">/raw</st> 文件夹移动到 <st c="24763">/</st>``<st c="24764">processed</st> 文件夹。

  9. 要详细查看代码,按照以下步骤操作:

    1. 点击作业 名称(<st c="24856">chapter8-gluejob</st>)。

    2. 选择 脚本 选项卡并查看 代码。

  10. 要检查作业状态,前往 运行 选项卡,并等待直到 运行状态 变为 成功,如图 图 8**.11所示:

图 8.11 – 成功运行消息

图 8.11 – 成功运行消息

到目前为止,你的所有数据转换工作已完成,接下来是 探索数据的时刻。

第五章 – 使用 Athena 进行数据探索

到目前为止,你 已经生成了点击流数据并运行了 ETL 流水线进行转换。 现在,是时候探索你的数据并从中提取信息了。 如前述 要求 部分所提到,与你的数据交互有两种类型的用户,我们将从技术用户的解决方案开始,并尝试对你的 转换后的数据运行 SQL 查询:

  1. 访问 Athena 控制台 请前往 https://console.aws.amazon.com/athena

  2. 如果这是你第一次访问 Athena 控制台,你需要进行初始配置。 因此,点击 探索查询编辑器,如图 图 8**.12所示:

图 8.12 – Athena 控制台

图 8.12 – Athena 控制台

  1. 前往 设置 选项卡。

  2. 点击 管理

  3. 选择浏览 S3

  4. 找到并点击你为此项目创建的 S3 桶(名称应以 <st c="26346">chapter-8-clickstream-xxxxxxxx</st> 为前缀)。

  5. 选择 <st c="26391">/</st>``<st c="26392">aux</st> 文件夹。

  6. 点击 选择 选择,如 图中 8**.13所示。

图 8.13 – Athena 配置

图 8.13 – Athena 配置

重要提示

您选择的存储桶与您用于存储数据的存储桶相同。 理想情况下,您应该为此设置一个单独的存储桶,并在处理 实际项目时考虑这一点。

配置 Athena 环境后,请按照 以下步骤操作:

  1. 切换到 编辑器 选项卡。

  2. 确保您已选择了 以下设置:

    • <st c="27058">AwsDataCatalog</st>

    • <st c="27084">clickstream_db</st>

  3. 点击与 clickstream_table相邻的三个点。

  4. 选择 预览表,如 图中 8**.14所示。

图 8.14 – Athena 预览表示例

图 8.14 – Athena 预览表示例

这将打开一个新选项卡,其中包含如下自动生成的查询:

 SELECT * FROM "clickstream_db"."clickstream_table" limit 10;

这是一个您可以使用纯 SQL 探索结果数据的示例,尽管自动生成的 查询非常简单,但您可以扩展它以回答更复杂的问题;例如,您从哪个大陆获得的点击量更多? 尝试运行以下查询以获取 答案!

 SELECT continent, COUNT(*) AS total_records
FROM "clickstream_db"."clickstream_table"
GROUP BY continent
ORDER BY total_records DESC;

现在,是时候探索非技术用户如何在不具备 SQL 技术知识或经验的情况下与您的数据交互并提取信息了。 为此,您现在将在 QuickSight 中开发一个仪表板,为探索 您的数据创建一个视觉替代方案。

第六部分 – 使用 QuickSight 进行数据可视化

让我们开始 设置您的 QuickSight。 如果您已经在账户中为其他项目使用 QuickSight,可以跳过初始配置,并选择您已在本章中使用过的区域继续进行 数据集创建:

  1. 在您的 AWS 控制台搜索栏中, 输入 <st c="28804">QuickSight</st>

  2. 你将被重定向到QuickSight门户,并看到一个类似于图 8.15的表单:

图 8.15 – QuickSight 注册表单

图 8.15 – QuickSight 注册表单

  1. 点击注册 QuickSight

  2. 接下来,你需要填写用于通知的电子邮件。你可以使用自己的电子邮件或其他任何你选择的电子邮件。

  3. 前往 QuickSight 区域选择。从下拉菜单中选择你在本章项目中使用的相同区域,如图 8.16所示:

图 8.16 – QuickSight 区域选择

图 8.16 – QuickSight 区域选择

  1. 向下滚动,在chapter8-clickstream-xxx中。

  2. 向下滚动,在可选附加组件部分,确保你取消勾选添加分页报告复选框,如图 8.17所示:

图 8.17 – QuickSight 分页报告附加组件

图 8.17 – QuickSight 分页报告附加组件

重要说明

确保不将分页报告添加到你的订阅中,这对于避免使用本书中未涵盖的功能而产生不必要的费用至关重要。

  1. 点击完成

如果一切设置正确,在 QuickSight 门户的左侧菜单中,你应该看到一个包含各种选项的菜单,如图 8.18所示:

图 8.18 – QuickSight 菜单

图 8.18 – QuickSight 菜单

每当你开始在 QuickSight 中创建任何内容时,第一步是创建一个数据集。所以,让我们从定义你的第一个数据集开始:

  1. 点击数据集

  2. 在右上角,点击新数据集

  3. 选择Athena

  4. 对于数据源名称,给它一个有意义的名称,例如clickstream

  5. 对于 Athena 工作组,确保 [Primary] 已选择。

  6. 点击 验证连接 确保一切正常工作。

  7. 点击 创建 数据源

  8. 在下一个 窗口中,选择 <st c="31425">clickstream_table</st> 从表格列表中, 如 图 8**.19所示:

图 8.19 – QuickSight 数据集配置

图 8.19 – QuickSight 数据集配置

  1. 点击 选择

  2. 点击 可视化

  3. 当系统提示报告类型时,选择 交互式表单,如 图 8**.20所示:

图 8.20 – QuickSight 报告类型创建表单

图 8.20 – QuickSight 报告类型创建表单

现在,是时候开始创建可视化了。 由于这是一个学习练习,你将创建一个简单的仪表板,但 你可以 并且应该将其扩展为一个更复杂的并且 更具信息量的仪表板。

我们从根据点击创建用户的地理分布开始:

  1. 可视化 标签中,点击 + 添加

  2. 选择填充地图,如 图 8**.21所示:

图 8.21 – QuickSight 可视化选择

图 8.21 – QuickSight 可视化选择

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

最后,你的可视化应该像 图 8**.22所示:

图 8.22 – 填充地图可视化创建

图 8.22 – 填充地图可视化创建

现在,让我们创建一个不同的可视化,展示基于点击数据的用户平均年龄。 为此,你将 利用 Autograph,这是 QuickSight 中的一项功能,能够根据你想要可视化的数据推荐图表类型:

  1. 点击地图可视化之外的区域。

  2. <st c="33315">user_age</st>开始。

    请注意,QuickSight 会创建一个只包含单个数字的可视化。 这是因为聚合类型默认设置为 求和 ,因此它正在对所有 用户的年龄进行求和。

  3. 要更改它,请点击 <st c="33548">user_age</st> 字段旁边的三个点,然后在聚合菜单中将其更改为 平均值,如 图 8**.23中所示:

图 8.23 – QuickSight 数据计算配置

图 8.23 – QuickSight 数据计算配置

您的可视化应自动更改为显示 新的计算结果。

您将构建的最后一个可视化是一个 漏斗图,用于展示记录数量如何根据事件类型变化。 为此,您应按照 以下步骤操作:

  1. 点击 + 添加 并选择 漏斗图

  2. 从数据菜单中, 选择 <st c="34272">event_type</st>

    您的仪表板应如下所示 图 8**.24。请随意探索其他可视化类型,重新排列您已有的可视化,并创建您自己的仪表板版本。

图 8.24 – QuickSight 仪表板示例

图 8.24 – QuickSight 仪表板示例

现在,是时候发布您的仪表板,以便您可以与 其他用户共享:

  1. 在右上角,点击 点击 发布

  2. 为您的仪表板命名。

  3. 点击 发布仪表板

恭喜,您的仪表板已经完成并准备好共享了! 您将测试的最后一项是端到端 工作流 ,以确保您的数据在 仪表板中更新。

要做到这一点,首先按照 第三部分 – 点击流事件生成器 第四部分 – Glue ETL 作业中的描述生成额外的事件并运行 ETL 作业。 当您的作业以成功状态完成后,在 QuickSight 控制台中,执行以下操作:

  1. 点击左上角的 QuickSight 图标。

  2. 从左侧菜单中选择数据集

  3. 选择你刚刚创建的数据集。

  4. 转到刷新标签。

  5. 点击立即刷新,如图 8.25所示:

图 8.25 – QuickSight 数据集刷新

图 8.25 – QuickSight 数据集刷新

完成刷新过程后,请执行以下操作:

  1. 点击左上角的 QuickSight 图标返回初始菜单。

  2. 从左侧菜单中选择仪表板

  3. 选择你刚刚创建的仪表板。

如果你与之前的版本进行对比,你的仪表板应该在视觉效果上显示不同的数值,这正是你刚刚执行的数据更新的结果。

在所有工作流测试完成后,现在是清理资源的时刻,以避免不必要的成本。

第七节 – 清理

第一步是删除你的 QuickSight 订阅,同时你仍然可以享受免费套餐。

重要提示

删除你的 QuickSight 订阅将删除你在 QuickSight 账户中的所有资产。如果你已经在其他项目中使用 QuickSight,你可能想跳过这一步,因为它仅适用于本章中新创建的订阅。

要继续进行 QuickSight 订阅终止,请执行以下步骤:

  1. 在 QuickSight 账户的右上角,点击用户图标。

  2. 选择管理 QuickSight

  3. 在左侧,选择账户设置

  4. 账户终止下,点击管理

  5. 通过点击切换按钮禁用账户保护。

  6. 在文本框中输入confirm

  7. 点击删除账户

现在,您只需清空 S3 存储桶并删除 CloudFormation 模板。 让我们从清空 存储桶开始:

  1. 转到您的 S3 控制台。 AWS 账户。

  2. 选择您的前端 S3 存储桶(桶的名称应以 <st c="37057">chapter-8-clickstream-</st> 开头,后跟 随机字符串)。

  3. 点击 清空 这将删除存储桶中的所有内容。

图 8.26 – 清空 S3 存储桶的过程

图 8.26 – 清空 S3 存储桶的过程

现在存储桶已清空,您可以继续执行 CloudFormation 堆栈删除:

  1. 转到您的 CloudFormation 控制台。 AWS 账户。

  2. 选择堆栈 您创建的。

  3. 点击 删除

到目前为止,本章中创建的所有资源都已被删除,始终确保 清理未使用的资源,以避免产生不必要的费用。 在下一节中,您将探索改进 应用程序的可能性。

未来工作

恭喜您成功构建了业务智能应用程序,包括数据摄取、处理,以及通过 SQL 查询和视觉方式探索。 作为本书的最后一个项目,重要的是要强调一个信息,即在未来的项目中应始终铭记:技术不断发展,新功能、服务和最佳实践定期出现,因此保持持续改进的心态非常重要,本项目也不例外。 本项目可以成为业务智能应用程序的起点,但有一些具体的操作可以使其更加健壮 和适合生产环境。

自动化 ETL 管道

未来增强的关键领域之一 围绕自动化 ETL 管道展开,目前按需运行。 一个强大的业务智能应用程序应在编排级别上集成自动化,以确保及时和可靠的数据处理。 在 AWS 中,AWS Step Functions 或者 Glue 工作流可以帮助您调度和自动化您的 ETL 过程。

此外,实施通知系统可以为你的 ETL 流水线提供有价值的健康状态和运行状态的洞察。 Glue 已经与 Amazon CloudWatch 原生集成,提供关于流水线状态的新实时事件,结合通知服务,例如 Amazon 简单通知服务 (SNS),可以 帮助你在问题发生时及时进行干预。 确保问题得到及时处理。

数据生命周期管理

有效的数据 管理和 成本优化是任何商业智能应用程序中至关重要的考虑因素,尤其是在处理大量数据时,如点击流数据。 S3 提供了不同的存储层,可以涵盖所有的数据 访问模式。

例如,你可以将频繁访问的点击流数据存储在 S3 标准存储类中,以实现低延迟访问,而将较旧或不常访问的数据归档到 S3 Glacier 或 S3 Glacier Deep Archive 存储类中,这样可以显著节省成本。 这种方法不仅优化了存储成本,还确保你的数据根据其生命周期阶段存储在最合适的层级,从而提高了整体的数据管理效率。 此外,通过自动化生命周期管理过程,你可以减少人工干预,确保一致地执行数据保留政策,增强合规性并降低数据泄露或 意外删除的风险。

总结

在本章中,你探索了构建端到端商业智能应用程序的过程,利用了各种 AWS 服务。 通过结合 Amazon Athena 进行临时查询、Amazon S3 进行数据存储、以及 Amazon QuickSight 进行数据可视化和仪表板设计,你创建了一个既能为技术用户也能为非技术用户提供有价值洞察的解决方案。 从数据中提取洞察。

随着你继续未来的项目,你现在具备了构建支持数据和信息转化架构的知识,从而在 各个层面推动数据驱动的决策。

在下一章中,你将有机会重新审视前几章的架构,并探索替代方法和 AWS 服务,同时理解任何架构选择背后的权衡。 你所做的每一个决策。

第十章:9

探索未来工作

恭喜! 您已经使用多个 AWS 服务构建了七个独特的应用程序。 但是,学习是一个 永无止境的旅程。

在本章基于理论的章节中,您将进一步了解更多关于 AWS 服务的内容。 架构是关于权衡的;了解什么时机使用哪些服务将在未来变得更加有利。 为了说明这一点,我们将重新审视前面章节的架构并 对其进行重新设计。

价格是您在本书的需求收集和服务选择部分中看到的一个重点。 在本章中,您将学习如何使用 AWS 定价计算器来估算成本,以便在构建 架构之前进行预估。

最后,您将探索 AWS 提供的多个不同资源,以帮助您架构和构建 更好的应用程序。

技术要求

这是一个基于理论的章节,因此没有技术要求。 如果您决定根据本章的学习内容重新设计任何前面章节的架构,您将需要自己的 AWS 账户。

AWS 服务概览

AWS 目前提供 超过 200 种服务,涵盖多个类别,包括计算、存储、数据库、网络、分析、机器学习、 物联网 (IoT)、移动、开发者 工具、管理工具、安全性和企业应用程序。 AWS 服务的确切数量会随着新服务的推出而变化。 在过去的八章中,您已经学习了一些这些服务,并使用它们构建了多个应用程序。 使用它们。

解决方案架构的美妙之处在于,没有单一的答案或架构。 这完全是关于权衡。 您在前面章节中学到的应用程序可以通过不同的方式和服务来构建。 在本节中,我们将研究使用您尚未 见过的 AWS 服务来实现过去章节中应用程序的替代架构。

容器

容器 轻量级的虚拟化计算环境,允许您将应用程序及其依赖项打包并以隔离和可移植的方式运行。 容器设计上非常轻量和高效,因为它们共享主机操作系统内核,不像传统的 虚拟机 (VMs),后者为每个实例需要单独的操作系统。 容器是一种计算选项,类似于 虚拟机。

重要提示

您已经在 第六章中使用过容器;CodePipeline 使用容器在 每个阶段运行指令。

由于容器是轻量级的,最佳实践是将不同的功能隔离到不同的容器中,如 图 9**.1所示,其中一个虚拟机变成了四个容器。 一个单一的服务可以跨多个容器进行拆分。 请注意, 点赞服务 分布在两个容器中,而在 虚拟机 环境中,只有一个容器。 容器为您提供了 更多的灵活性。

图 9.1 – 虚拟机与容器分解

图 9.1 – 虚拟机与容器分解

随着容器构建的应用程序变得越来越复杂,跨多个容器和主机的协调变得至关重要;因此,容器编排对于高效的管理和扩展非常重要。 容器编排平台提供了一个集中控制平面和 API,以简化容器化应用程序的部署、扩展和管理。 容器化应用程序。

在 AWS 中,最常见的容器编排平台是 以下几种:

  • Amazon Elastic Container Service (ECS):一项完全托管的容器编排服务,帮助您在 EC2 实例或 Fargate 实例的集群中部署、管理和扩展容器化应用程序。 它支持 Docker 容器,并允许您以大规模运行和管理容器。 它支持 Docker 容器,允许您大规模运行和管理容器。

  • Amazon 弹性 Kubernetes 服务(EKS):一种托管的 Kubernetes 服务, 简化了在 AWS 上使用 Kubernetes 部署、管理和扩展容器化应用程序的过程。 Kubernetes 是一个开源的容器编排平台,能够自动化容器化应用程序的部署、扩展和管理。 容器化应用程序。

你可以将 过去章节中的计算选项替换为容器。 第四章 中介绍的无服务器架构,使用 ECS 在 EC2 环境中编排的容器,效果如 图 9**.2。你将像 <st c="4415">put_like</st> <st c="4427">get_recipes</st> 这样的 Lambda 函数替换为承载相同功能的容器。 你的 API 网关使用私有集成连接到一个 内部 应用负载均衡器(ALB) ,该负载均衡器公开 ECS 任务。 你需要使用私有集成,因为负载均衡器和 ECS 容器位于 VPC 中,而 API 网关则不在其中。 你可以在 AWS 文档中阅读更多关于私有集成的内容: https://docs.aws.amazon.com/apigateway/latest/developerguide/getting-started-with-private-integration.html

图 9.2 – 使用容器重新设计的第四章架构

图 9.2 – 使用容器重新设计的第四章架构

如你所见 图 9**.2,容器仍然可以在虚拟机中运行, 在这种情况下是 EC2\。 也可以使用 Fargate 以无服务器方式运行容器。 Fargate 是一种无服务器计算引擎,专为容器设计,允许你在无需管理底层 EC2 实例的情况下运行容器。 它与 ECS 和 EKS 无缝配合,消除了 提供和 管理服务器 或集群的需求。

其他 API 类型

在本书中,你 只构建了 REST API。 然而,还有其他类型的 API 不是 RESTful 的。 一个非常流行的例子 是 GraphQL。

GraphQL 是一种查询语言和服务器端运行时环境,最初由 Facebook 于 2012 年开发。 它提供了一种高效、强大且灵活的方法来构建和使用 API,并且在云应用中越来越受欢迎。 它之所以如此受欢迎,是因为它解决了传统 REST API 中常见的两个问题:超取(获取比实际需要更多的数据)和欠取(需要多次请求以获取相关数据)。 这些问题在传统的 REST API 中比较常见。

需要牢记一些重要特点:

  • GraphQL 通常会为数据查询暴露一个单一端点,而不是为不同资源设置多个端点。 这简化了 API 接口,并使得 API 的演变变得更加容易 随时间推移。

  • 它使用一种强类型查询语言,允许客户端仅请求所需的数据。 这与传统的 REST API 不同,后者通常返回超过客户端需求的数据 量。

  • 使用 GraphQL,客户端对接收到的数据有更多控制,从而实现更好的性能和灵活性。 它具有 客户端驱动的架构。

  • GraphQL API 是围绕一个模式构建的,定义了类型、查询、变更以及不同数据实体之间的关系。 该模式充当客户端和服务器之间的契约,确保数据一致性,并使得 强大的工具能够发挥作用。

在 AWS 中,AppSync 是一个托管服务,使得构建可扩展的 GraphQL API 变得更加容易。 AppSync 通过处理底层基础设施、扩展和安全方面的工作,简化了构建 GraphQL API 的过程,让开发人员能够专注于构建应用逻辑;这与 API 网关为 REST API 所做的工作类似。

第五章**'s 架构使用 AWS AppSync 重新设计的方式相似,如 图 9**.3所示。你将 API 网关替换为 AppSync,并使用 Lambda 解析器。

图 9.3 – 使用 AWS AppSync 重新设计的第五章架构

图 9.3 – 使用 AWS AppSync 重新设计的第五章架构

您的客户与该应用程序的交互方式有所不同。 您仍然可以使用 curl 或 Postman,但需要 将查询发送到负载中。 AWS 的文档对此有详细说明: 文档链接: https://docs.aws.amazon.com/appsync/latest/devguide/retrieve-data-with-graphql-query.html

生成式 AI

您已经在本书中看到了 不同的 AI 驱动的应用程序: 第五章中的图像分析, 第五章,第六章中的内容翻译, 第六章,以及第七章中的问答。 第七章。但还有一种 AI 正在席卷全球: 生成式 AI。

生成式 AI 指的是一类能够基于训练数据生成新数据(如文本、图像、音频或其他多媒体内容)的 AI 模型和技术。 与传统的主要关注分析或分类现有数据的 AI 模型不同,生成式 AI 模型学习训练数据的潜在模式和特征,并利用这些知识创造新的、 原创内容。

基础模型 (FM) 是一种强大的生成式 AI 模型,可用于各种任务。 不同的公司已经构建了自己的模型,如 OpenAI GPT、Anthropic Claude 和 Meta Llama。

您无需从零开始构建这些模型,但您应该知道如何充分利用它们。

在 AWS 中,您可以通过使用 Amazon Bedrock 以无服务器的方式利用 FMs。 Amazon Bedrock 是一项完全托管的服务,提供来自领先 AI 公司(如 AI21 Labs、Anthropic、Cohere、Meta、Mistral AI、Stability AI 和 Amazon)的高性能 FMs,您可以通过单一 API 获取,并提供构建生成式 AI 应用程序所需的广泛功能。

您所需要做的只是调用一个 API,就像使用其他任何类型的 AWS 服务一样。 第五章的架构 可以修改为使用 Bedrock 和 Claude 3 Sonnet,而不是 Rekognition,如 图 9**.4所示。

图 9.4 – 使用 Amazon Bedrock 重新设计的第五章架构

图 9.4 – 第五章的架构使用 Amazon Bedrock 重新设计

采用这种方法,你可以发送图像并用自然语言向模型提问。 例如,你可能会问:“这个人是在微笑吗?” 或者“这张照片看起来专业吗?” 你将这些信息与图像一起发送,并提示模型进行评估。 以下是本书作者与 Claude 3 Sonnet 之间的互动示例。 第一行以 <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.

生成式 AI 正被越来越多地应用于多种场景,如问答聊天机器人、文本摘要 和生成营销 内容。 在构建下一个应用程序时,请记住这一点。

其他通信模式

最常见的 通信模式是同步请求/响应。 例如,当你访问一个网页(请求)时,你的浏览器会获取并渲染结果(响应)。 这个过程是同步的,意味着在发出请求后你需要等待响应。 但是在现代分布式架构中,有时你会遇到需要不同通信模式的情况,例如在长时间处理任务中,当等待响应时阻塞客户端会干扰客户体验,或者当你需要将相同的内容传递给许多 不同的接收者。

一些常见的模式包括异步处理、分发和广播,以及事件驱动。 让我们从异步处理开始。 异步处理

异步处理

假设你需要 构建一个 应用程序,像在 第五章中那样,它接收一张照片并进行处理。 然而,处理的复杂度并不像在 第五章中那样轻便。 相反,它需要四小时才能完成,并且是由 EC2 机器完成的。 在四小时内可能会发生许多事情:处理可能失败,客户端可能超时,等等。 在这种情况下,解耦架构带来了 多个优势:

  • 客户端可以发送请求,而无需等待订阅者 处理它们。

  • 订阅者可以按 自己的节奏消费消息。

  • 如果订阅者端出现故障,另一个订阅者可以继续处理相同的请求。 它不会简单地 丢失。

实现异步处理的一种方式是使用队列。 AWS 提供了亚马逊 简单队列服务 (SQS),这是一个 完全托管的分布式消息 队列服务。

来自 第五章 的架构可以更新为支持异步处理,如 图 9**.5所示。消息存储在 SQS 中,EC2 集群订阅了 SQS 进行消息处理。 每条消息只会 被处理一次。

图 9.5 – 使用异步处理和 SQS 与 EC2 重新设计的第五章架构

图 9.5 – 使用异步处理和 SQS 与 EC2 重新设计的第五章架构

请注意 架构并未考虑客户端如何接收任务 完成的通知。

Fan-out 和广播

当你需要将单条消息发送到多个端点时,使用 Fan-out。 广播应用相同的概念,但将消息发送到所有端点,而不仅仅是选择的那些。 假设你有一本电话簿:fan-out 就像是逐一发送消息给每个人,而广播就像是创建一个群聊并将消息发送给群里的所有人。 这种方法在通知系统、数据复制或同步任务中很常见,且在 事件驱动架构中也经常使用。

在 AWS 中,有一个 Amazon 简单通知服务 (SNS)。 它是一个完全托管的发布/订阅消息 服务。 与 SQS 不同,它允许将一条消息发送到多个消费者。 它采用基于推送的机制,而不是像 SQS 那样基于拉取的机制。

考虑到之前的异步处理场景,这次你需要处理同一提交的图像两次,并且你有两个不同的计算集群来处理它。 使用 SQS,消息只会被处理一次。 图 9**.6 展示了如何使用 SNS 和 SQS 在扇出配置中实现这一目标。 当 SNS 被触发时,它会复制接收到的消息并将其发送到两个 SQS 队列。 然后,两个计算集群中的每一个会轮询各自的 SQS 队列并处理 消息。

图 9.6 – 使用扇出模式将相同消息分发到两个不同计算集群的架构

图 9.6 – 使用扇出模式将相同消息分发到两个不同计算集群的架构

最后,让我们 看看 事件驱动模式。

事件驱动

事件驱动 指的是一种编程 范式或架构模式,在这种模式下,程序的流程由事件决定。 在事件驱动系统中,程序的执行路径是由特定事件的发生触发的,而不是按照预定义的顺序执行指令。 事件可以由各种来源生成,例如用户交互(如点击或按键)、系统通知(如文件变化或网络事件)、硬件中断(如定时器或传感器数据)或来自其他组件 或系统的消息。

AWS 中的所有服务都会生成事件。 你可以使用 AWS EventBridge(前身为 Amazon CloudWatch Events)基于这些事件采取相应的行动。 它是一个无服务器的事件 总线服务。

事件驱动架构的一个常见示例如下:一个客户端将文件上传到你的 S3 桶,触发一个事件。 基于这个事件,你触发一个处理流水线来处理 上传的文件。

所有这些主题都很广泛,但都有充分的文档。 熟悉这些内容。 如果你想深入了解,推荐阅读 AWS 白皮书 在 AWS 上实现微服务 的通信机制 https://docs.aws.amazon.com/whitepapers/latest/microservices-on-aws/communication-mechanisms.html

AWS 定价计算器

在构建 架构之前,了解它是否符合你的成本要求是很重要的。 同时,比较不同的 服务选项也很重要。

有多种方式可以实现这一目标,例如,使用 AWS 服务的定价页面。 然而,AWS 定价计算器是推荐的方式。 它允许你通过逐个添加每个服务来创建 AWS 使用成本的估算。

访问 https://calculator.aws/ 并创建一个估算。 逐个添加每个服务并配置它。 配置参数因服务而异。 结果将是每月和 每年的成本估算。

对第二章中的解决方案进行定价

重新审视 第二章 并回顾在 图 2**.1中描绘的架构。 它使用了两个服务:CloudFront 和 S3\。 CloudWatch 基本监控指标是免费的。 在 AWS 定价计算器中重新创建此架构。

将 S3 添加到你的估算中。 指定你计划使用的区域;定价可能会因区域而异。 要估算 S3 成本,你需要知道每月将使用多少 GB 的存储空间,所需的请求数量和类型,以及 数据传输量 (DTO) 的 GB/月。

要存储来自 第二章 的三个网站文件 – <st c="17772">index.html</st> <st c="17784">index.css</st>,和 <st c="17799">avatar.png</st>,你需要 100 KB。 100 KB 等于 0.0001 GB。 如果你修改了文件,请检查 文件的大小。

CloudFront 主要 会向你的 S3 发出 GET 请求。 由于 第二章的项目是一个展示个人简历的网站,你预计每月不会超过 500 次浏览。 因此,你预计会有 500 次 GET 请求 到 S3。

关于 DTO,选择 CloudFront 作为目标。 这使得 DTO 免费。

接下来,添加第二个服务,CloudFront。 在用户访问你的网站的区域,输入每月预期的请求次数和 DTO 的数量。 请求次数的计算方法与 S3 请求相同。 由于这是一个简单的展示个人简历的网站,你估计每月会有 500 次请求。 对于 DTO,计算 500 次请求乘以你文件的大小。 网站文件总大小大约为 100 KB,折算下来大约是 0.05 GB。

尽管这两个服务都有免费层,但计算器不会自动考虑这一点。 对于大多数 AWS 服务,你需要确定免费层提供的内容,并在输入到计算器之前从你的值中减去这些内容。 例如,S3 的免费层包括 20,000 次 GET 请求。 如果你预计项目需要 40,000 次 GET 请求,你应该只输入 20,000 次 GET 请求到 计算器中。

对于 第二章,最终的计算器输出是 0 美元,无论你是否减去免费层,如 图 9**.7所示。这是因为项目的规模 非常小。

图 9.7 – 第二章项目的 AWS 定价计算器

图 9.7 – 第二章项目的 AWS 定价计算器

本章的非功能需求之一是低成本。 你无疑达成了这个目标。 使用计算器来了解当静态网站拥有数千或数百万用户时,成本如何上升。

定价第六章中的解决方案

请回顾 第六章。使用 AWS 定价计算器计算此解决方案的定价。 从架构的静态网站托管部分开始,包括 S3 存储桶和 CloudFront 分发。

添加 S3\。 来自 第六章的网站文件<st c="20349">index.html</st> <st c="20364">index.css</st>,每个文件大小都小于 10 KB。 由于这些文件存储在两个不同的 S3 存储桶中,因此总存储需求为 20 KB,或 0.00002 GB。 这是一个事件网站,预计每月约 100,000 次访问。 就 S3 而言,这意味着 100,000 次请求。

对于 CloudFront,它也有 100,000 次请求,总计 2 GB DTO。 然而,CloudFront 还使用 Lambda@Edge。 添加 Lambda。 此服务允许包含或排除免费层。 添加相同的 100,000 次请求,使用最小内存,128 MB,并假设执行时间为 10 毫秒。

现在,您已经完成了静态网站架构。 您的计算器应该输出大约每月 0.40 美元。 然而,如果您深入了解每项服务的费用,您会发现大部分费用来自 CloudFront。 计算器没有包括此服务的免费层,就像它没有包括 Lambda 一样。 CloudFront 的免费层包括 以下内容:

  • 每月 1 TB DTO 到互联网 每月

  • 每月 10,000,000 次 HTTP 或 HTTPS 请求 每月

因此,这个架构在我们解决方案的规模下几乎是免费的。 您的费用将低于每月 0.10 美元。 每月。

启动另一个计算器,或在相同计算器中添加来自 第六章的 CI/CD 组件: CodeBuild、CodePipeline 和Amazon Translate。

添加 CodeCommit。 它将询问活跃用户的数量。 在您的情况下,只有一个活跃 用户:您。

添加 CodeBuild。 第六章中,我们描述了使用 2 GB 按需 Lambda 进行计算。 假设您每周至少进行一次更改;每次更改的运行时间为 10 秒。

添加 CodePipeline。 您为 此项目拥有一个单独的管道。

最后,添加 Amazon Translate。 选择 <st c="22045">index.html</st> 有超过 2400 个字符。 如果你每月将其翻译四次为一种语言,那么每月大约翻译 10,000 个字符。 每月。

图 9**.8 显示了该项目的计算器。 S3 和 CloudFront 的费用将由服务的免费套餐免除。 Amazon Translate 没有实时文档翻译的免费套餐,而 AWS Lambda 计算器已经包括了免费套餐。 结果是每月 0.22 美元,或每年 2.64 美元。 每年。

图 9.8 – 第六章项目的 AWS 定价计算器

图 9.8 – 第六章项目的 AWS 定价计算器

将这些估算更改为与你构建的项目相符。 例如,如果你正在将网站翻译成多种语言,你需要调整 Amazon Translate 的费用。 如果 你每周更改的次数超过一次,则需要调整 CodeBuild 的执行次数。 如果你使用的是 AWS 以外的任何组件,例如 GitHub,如在 第六章所示, 则需要将这些费用添加到最终计算器中。

重要提示

你可以将估算结果导出为 JSON、PDF 或 CSV 格式。 你还可以分享计算器的链接。 这对于与同事 和客户共享架构非常有帮助。

当你进行定价估算时,你需要估算项目的容量和某些特征,例如预期的请求数量。 大多数时候,你不需要估算个位数或两位数的单位。 使用整数进行计算更为简单;例如,不要使用 87 KB,而使用 100 KB。 不要使用每秒 1 次请求(即每天 86,000 次请求),而使用每天 100,000 次请求。 这种方法通常被称为“简易估算”,并且在 构建架构时广泛应用。

实践成就 完美;通过为本书中的所有项目创建计算器来进行练习。 本书中的所有项目。

AWS re:Post

如果你能在遇到开发或架构疑问时,向其他专家提问关于错误的问题,那该多好呢? 你可以。

AWS re:Post 是一个由 AWS 创建的官方知识中心文章、视频及其他资源的知识库,旨在帮助客户更好地理解和使用 AWS 服务。 但是,re:Post 也允许你发布自己的问题。

访问 https://repost.aws 并导航至你选择的主题。 你将看到成百上千的问题,许多问题已由 AWS 专业人员或其他用户回答。 这是一个获取帮助、与他人合作以及让你的知识和工作在更广泛的行业中可见的绝佳资源。

然而,如前所述,re:Post 不仅仅是一个技术论坛。 AWS re:Post 包括官方的 AWS 知识中心, https://repost.aws/knowledge-center,这是一个涵盖 AWS 客户最常见问题和请求的知识库。 简而言之,AWS 会识别出经常被问到的问题,并将其转化为文章。 你在构建应用程序时遇到的许多错误,如果不是全部,都会在这里有针对性的解决方案。 解决方案在这里。

一些有用的示例如下:

最后,不仅仅是 AWS 的员工,其他人也可以与他人分享具有指导性的建议。 他们可以通过社区文章来分享这些建议, https://repost.aws/articles。作为练习,写一篇你在阅读本书时学到的内容,并将其作为社区文章分享 到 re:Post 上。

AWS 文档、解决方案库和指导性建议

了解一切的知识可能不如知道在哪里可以找到所需信息重要。 如果你需要某些信息,这一点尤其重要。

在本书中,你已经访问过 AWS 文档、AWS 架构中心等多个页面。 了解可用的多种选项非常重要。 在本节中,你将深入了解三种具体选项:AWS 文档、AWS 解决方案库和 AWS 指导性建议。

AWS 文档

AWS 上的每项服务 都有详尽的官方文档。 除此之外,还有如 medium.com、社区文章、本书本身 等非官方文档。

在本书中,你已经访问过多个文档页面。 然而,值得特别强调的是几个 文档页面:

熟悉这些资源,以便在需要时能够找到它们。

AWS 解决方案库

AWS 架构中心 是你在每章定义项目需求后最初的搜索引擎。 这是一个一站式的目的地,允许你浏览、搜索,甚至请求参考架构、架构模式、最佳实践和指导性建议,所有这些都可以在 一个地方找到。

但是,如果你正在寻找经过他人预构建、测试和验证的内容,并且附带如 CloudFormation 这样的 IaC 模板,AWS 解决方案库(https://aws.amazon.com/solutions/)是理想之地。 该库还包括 AWS 合作伙伴解决方案。

让我们为项目添加一个新需求,来自于 第六章。公司要求在部署活动网站之前进行广泛的负载测试,以确保它能够承受 高负载。

如果您不是负载测试方面的专家,请搜索并导航到 AWS 上的分布式负载测试 在解决方案库中:https://aws.amazon.com/solutions/implementations/distributed-load-testing-on-aws/?did=sl_card&trk=sl_card

这是一个典型的解决方案库文档。在其中,您将找到三个组件:

  • 一个架构图

  • 一个实施指南

  • 一键部署选项

如图 图 9**.9 所示,此架构图以逐步方式展示了流程。

图 9.9 – 分布式负载测试架构

图 9.9 – 分布式负载测试架构

实施指南,https://docs.aws.amazon.com/solutions/latest/distributed-load-testing-on-aws/solution-overview.html,深入介绍了该解决方案的工作原理,包括监控和故障排除信息。另请注意,实施指南中有专门的部分用于估算成本。

最后,它包括一个一键部署选项,在 AWS 控制台中启动,您可以使用它进行部署并立即测试您的事件网站,而无需从头开始设计另一个项目。

AWS 规范指导

AWS 规范指导 (APG)(https://aws.amazon.com/prescriptive-guidance/)也可以在 AWS 架构中心找到,但它侧重于经过时间验证的策略、指南和模式,以帮助加速您的云迁移、现代化和优化项目。

与解决方案库不同,并非所有内容都具有实用性,也没有架构图和代码。

有三种类型的资源:

  • 策略:云迁移和现代化的商业视角、方法论和框架,适用于 CxO 和高级经理。

  • 指南:为架构师、经理和 技术负责人提供的规划和实施策略的指导,重点介绍最佳实践和工具。

  • 模式:用于实现常见迁移、优化和现代化场景的步骤、架构、工具和代码,适用于构建者和其他 实践用户。

当你刚开始时,模式是最有用的。 它们详细描述了流行的 服务配置。

在构建本书中的项目时,你已经部署了几个 CloudFront 分发。 它们都像你期望的那样安全吗? 你知道如何验证吗? 你可以轻松地使用 APG 模式自动化这些 验证类型 检查 Amazon CloudFront 分发的访问日志、HTTPS 和 TLS 版本 https://docs.aws.amazon.com/prescriptive-guidance/latest/patterns/check-an-amazon-cloudfront-distribution-for-access-logging-https-and-tls-version.html?did=pg_card&trk=pg_card。它使用 Lambda 检查新的和已修改的 CloudFront 分发,确保其配置了 TLS 1.2、HTTPS 和 日志记录配置。

总结

在本章中,你了解了其他可以用于构建本书中不同示例项目的 AWS 服务。 这表明架构更多的是关于权衡取舍,而非构建 完美的解决方案。

你还了解了 AWS 定价计算器,以及它如何帮助你在构建项目之前估算成本。 你为来自 第二章 第六章的项目创建了定价估算。

最后,你探索了许多 AWS 的学习资源。 其中一些可能是你之前没有接触过的,比如 AWS re:Posts,而另一些则属于现在已经熟悉的 AWS 架构中心,这是一个提供指导 和资源的一站式平台。

AWS 服务、架构模式和技术种类繁多,无法在一本书中覆盖所有内容。 但如果你了解基础知识,那应该能提升你所做的一切的水平。 你所做的每件事都会有所提高。

恭喜你完成了这段充满实践项目和云计算知识的广泛旅程。 虽然这本书已经结束,但这只是你 AWS 云计算旅程的开始。

posted @ 2025-06-30 19:27  绝不原创的飞龙  阅读(12)  评论(0)    收藏  举报