亚马逊AWS官方博客

AWS 如何使用无服务器技术构建生产服务

我们的客户一直在寻找提高组织敏捷性和创新性的方法,并且他们经常与我们联系,希望详细了解我们如何代表客户进行快速迭代。我们不断探索通过使用新技术更快移动的方法,这是我们独特文化(Jeff Barr 在此处的主题演讲中加以论述)的组成部分。

无服务器计算这项技术可以帮助 Amazon 以比以往更快的速度进行创新,并通过消除预置、扩展和修补基础架构的需求节省内部团队的时间。而我们可以利用节省下来的时间改善我们的产品和服务。

今天,我们非常高兴地宣布,我们发布了一个新的开源项目,旨在帮助客户学习 Amazon 构建无服务器应用程序的方法。这个开源项目包含 AWS Serverless Application Repository(主要使用 Java 编写并使用无服务器技术构建的生产级 AWS 服务)的关键架构组件、代码结构、部署技术、测试方法以及操作实践。我们希望为客户提供一个机会,让他们可以通过一个开源且文档齐全的代码库进一步了解无服务器部署,该代码库中汇集了 Amazon 多年来的最佳实践。该项目由两年前发布 AWS Serverless Application Repository 的同一团队开发,可以通过 Apache 2.0 许可证在 GitHub 上使用。

Firecracker 示例所示,开源一直是 AWS 战略的重要组成部分。开源是与社区合作更有效的方式,我们将对开源的投资视为实现客户创新的一种方式。尽管我们在 GitHub 上提供了很多无服务器应用程序示例和许多参考架构,但这是我们首次尝试开放一组无服务器应用程序组件的源代码(受 AWS 生产服务实施的启发)。因为该项目的重点是学习,所以我们在 GitHub 上仅提供了一些服务操作。例如,为了展示我们如何开发请求和响应架构,我们发布了服务的 create-application 操作的代码,并排除了 put-policyget-template 等类似的操作。我们使用该服务从开发此项目的实际场景中获取动机。您可以研究代码、在本地更改代码、在您的 AWS 账户中部署受该服务启发而编写的服务版本,然后重复此过程,以便进一步了解我们如何使用无服务器技术开发、测试和操作我们的生产服务。

关于 AWS Serverless Application Repository 以及我们为何将其用作开发该项目的参考的简单说明:

团组、组织和开发人员个人可以借助 AWS Serverless Application Repository 存储和共享可重用无服务器应用程序,并且可以通过功能强大的新方式轻松汇编和部署无服务器架构。该服务实施常见的请求/响应模式,将事件驱动型系统用于异步处理,并使用组件架构来减少耦合和提高扩展维度。客户通常期望学习的是如何实现这些模式,以及如何使用最佳实践。

下图表示开源项目的高级体系结构,该结构酷似服务的生产体系结构。我们来详细了解下您可以在 GitHub 上学习的内容。

主架构图。

该开源项目包含四个核心组件:一个静态网站(前端)、一个后端、一个操作组件和一个异步分析组件。这种模块化体系结构有助于在发生故障时最大程度降低对客户的影响,并且对于快速且独立地迭代组件至关重要。每个组件都有其自己的指定文件夹,有助于整理其代码、依赖关系和基础架构即代码模板,这与生产服务的布局非常相似。每个文件夹中都提供了一套单元测试和集成测试,帮助确保在部署更改之前对其进行全面的测试。CI/CD 管道模板可用于单个组件,从而让您可以灵活地为要部署的特定组件设置管道。

注意:尽管该项目专为学习目的而设计,但我们在构建每个组件时均考虑到了生产质量。从服务中提取的组件也可以通过 AWS Serverless Application Repository 独立部署为应用程序。

本文将详细说明后端组件。项目 Wiki 中也提供了此项目的版本。

后端(请求/响应)

应用程序在处理用户请求、处理数据和响应时可能成功,也可能出错,这都是非常常见的。用户还必须通过与 API 通信的方式进行身份验证(通常是通过 Web 界面)。例如,服务的 create-application 操作公开为 Amazon API Gateway API。客户使用 AWS 开发工具包和 AWS 控制台与服务进行交互,其中身份验证和授权通过 AWS Identity and Access Management (IAM) 进行管理。系统会将向服务发起的请求路由到执行业务逻辑的 AWS Lambda,并通过 Amazon DynamoDB 管理状态。这个开源项目包含与生产服务几乎相同的请求/响应架构,除此之外我们还展示了如何使用 Amazon Cognito 进行身份验证和授权。下图展示了随本开源项目一同发布的后端组件的架构。

后端组件架构图。

后端组件实施以下操作:

  • CreateApplication:创建应用程序
  • UpdateApplication:更新应用程序元数据
  • GetApplication:获取应用程序的详细信息
  • ListApplications:列出您创建的应用程序
  • DeleteApplication:删除应用程序

我们使用 Open API (Swagger) 的规范来定义 API,并使用 Swagger Codegen 工具生成服务器端模型(用于输入/输出)和上述 API 的 JAX-RS 注解。

注意:JAX-RS (Java API for RESTful Web Services) 是 Java 编程语言 API 规范,支持根据表现层状态转换架构模式创建 Web 服务。JAX-RS 的参考实现 Jersey 实现了对在 JSR 311 中定义的注解的支持,让开发人员能够使用 Java 编程语言轻松构建 RESTful Web 服务。

我们来看几段代码,了解如何通过应用程序的相应 Java 方法路由和处理请求。了解我们如何使用现有 Java 框架来帮助开发人员专注于仅编写应用程序的业务逻辑,这将对您有所帮助。

以下代码片段展示了在根据 API 规范创建的 ApplicationsApi Java 接口中为 create-application API 定义的 JAX-RS 注解。

根据 API 规范创建的 Java 接口。

ApplicationService 类包含 API 的所有业务逻辑。此类实现了 ApplicationsApi Java 接口定义的方法。以下代码片段展示了 create-application API 的实现:一个简单的 Java 方法,可接受 CreateApplicationInput POJO 作为输入来处理创建应用程序的请求。

创建应用程序 API 的实现。

最后,以下代码片段展示了如何将 Amazon API Gateway 请求(从 Lambda 处理程序)路由到 ApplicationService 类中的相应 Java 方法。

如前所述,该项目使用 Jersey 框架(JAX-RS 的实现)。ApplicationService 类已注册到 ResourceConfig(Jersey 应用程序),以便 Jersey 可以将 REST 调用转发给 ApplicationService 类中的相应方法。API 请求通过 JerseyLambdaContainerHandler 中间件组件发送到 Jersey,该组件本身支持用于处理请求和响应的 API Gateway 代理集成模型。该中间件组件是开源 AWS 无服务器 Java 容器框架的组成部分,此框架提供 Java 包装类,以便在 AWS Lambda 内运行 Jersey、Spring、Spark 和其他基于 Java 的框架应用程序。

API Lambda 处理程序。这是 API Lambda 的入口点。

测试和部署

集成测试是使用 Cucumber 定义的。Cucumber 是一个热门的 Java 测试框架,可以将用户的要求翻译成纯英文的测试场景,这样所有的利益相关者都可以在理解的基础上进行审核和达成一致,然后再进行实施。这些测试位于 src/test folder 中,可作为自动化 CI/CD 管道的一部分运行,也可以手动运行。运行集成测试会将测试堆栈部署到您的 AWS 账户、运行测试,并在测试完成后删除堆栈。

部署到 AWS 时,我们使用 AWS 无服务器应用程序模型 (SAM)。该模型提供简化的语法来表达函数、API、数据库和数据源映射。这些模板可以手动部署,也可以作为自动化管道的一部分进行部署。在整理模板时,我们采用了多年来在 AWS 学到的两个关键最佳实践 – 嵌套堆栈和参数引用:

1) 嵌套堆栈使模板可在不同的堆栈中重复使用。随着基础架构的扩展,您可以将通用模式转换为模板,并且可以将这些模板定义为其他模板中的资源。在本项目中,我们为每个组件添加了一个根级 SAM 模板,名为 template.yaml。在该模板中,database.template.yamlapi.template.yaml 等嵌套模板就被定义为资源。这些嵌套模板会相应地定义组件所需的特定资源,例如 API Gateway API 和 DynamoDB 表。

2) 对于参数引用,我们使用 AWS Systems Manager 参数仓库。该参数仓库允许将可配置参数存储在参数仓库中并在 SAM 模板中引用。参数仓库还允许直接在 Lambda 函数内部引用这些参数,而不是将它们作为环境变量传递,并且允许独立于服务部署来管理配置值。

演练

我们在上面说明了该项目的一些部署技术、测试实践和部署方法。接下来我们演练下如何在 AWS 账户中构建和部署应用程序。我们将构建静态网站(前端)和后端组件,这样我们可以看到正在运行的应用程序的端到端演示。此过程应该不到 10 分钟即可完成。

确保您已在计算机本地准备好必要的先决条件。克隆 GitHub 存储库,转到项目目录,然后运行以下命令来构建代码:

cd static-website
npm install
npm run ci
cd ..
mvn clean compile

注意:该应用程序支持 Node LTS 版本 10.16.3 和 OpenJDK 版本 8。您可以将 Amazon Corretto 用于 OpenJDK 的生产就绪型发行版。

成功创建项目后:

  • 通过 aws s3 mb s3://<s3 bucket name> 创建一个 S3 存储桶来存储应用程序的打包构件;
  • 通过 mvn clean package -DpackageBucket=<s3 bucket name> 打包应用程序;
  • 通过 aws cloudformation deploy --template-file target/sam/app/packaged-template.yaml --capabilities CAPABILITY_IAM CAPABILITY_AUTO_EXPAND --stack-name <name> 部署应用程序

您应该会看到类似于下图所示内容的输出:

CloudFormation 堆栈创建的确认图片。

成功创建堆栈后,导航到 AWS CloudFormation 控制台,找到您刚刚创建的堆栈,然后转至输出选项卡找到应用程序的网站 URL。单击该链接应该会显示如下类似页面。这说明应用程序已创建完毕并已正常运行!

网站屏幕截图。

您可以单击尝试演示来访问后端 API。作为初次使用的用户,应用程序会要求您先注册。之后您可以创建(发布)、获取、更新、列出和删除应用程序。

后续步骤

在本文中,我们介绍了如何利用无服务器来构建生产级服务,以及 AWS 开发人员如何使用无服务器技术代表客户更快地进行创新。还简要介绍了项目后端(请求/响应)组件的详细信息、我们的测试和部署实践,并演练了如何将前端和后端实例部署到您的 AWS 账户。接下来,您可以创建存储库的分支和对其进行修改。您还可以设置 CI/CD 管道来自动推送更改。我们已在 sam/cicd/template.yaml 下为每个组件提供了 CI/CD 模板。我们可以使用以下代码轻松部署这些模板:

aws cloudformation deploy --template-file target/sam/cicd/template.yaml --capabilities CAPABILITY_IAM CAPABILITY_AUTO_EXPAND --stack-name <your-stack-name>

您也可以详细了解分析组件管道操作警报和控制面板。希望本文对您有所帮助。如果本文对您有所帮助,请为我们的 GitHub 项目点赞。