亚马逊AWS官方博客

使用 Amazon Redshift 和 Amazon API Gateway 构建无服务器分析应用

无服务器应用程序是在业务部门和工程团队之间执行分析的现代化方式。业务团队可以通过 Web 应用程序简化报告并将报告分发给更广泛的受众,从而获得有意义的洞察。

以下列出了一些使用场景:

  • 控制面板 – 一个网页,其中包含表格和图表,每个组件均可向特定的业务部门提供洞察。
  • 报告和分析 – 一个应用程序,可用于触发使用动态输入的大型分析查询,然后查看或下载结果。
  • 管理系统 – 一个应用程序,提供公司内部资源和系统的全面视图。
  • ETL 工作流 – 一个网页,公司内部人员可以在使用动态输入的用户友好的环境中,触发特定的提取、转换、加载(ETL,Extract, Transform, and Load)工作负载。
  • 数据抽象 – 分离并重构基础数据结构和基础设施。
  • 易用性 – 一个应用程序,您需要在其中提供大量用户控制的分析访问权限,而无需让每个用户都登录技术平台。查询更新可以通过有条理的方式完成,并实现最小维护开销。

在这篇文章中,您将了解如何使用 Amazon Redshift Data API 和 Amazon API Gateway WebSocket 以及 REST API 构建无服务器分析应用程序。

Amazon Redshift 完全由 AWS 管理,您不再需要担心数据仓库管理任务,例如,硬件预置、软件修补、设置、配置、监控节点和驱动器以便从故障或备份中恢复。Data API 简化了对 Amazon Redshift 的访问,因为您无需配置驱动程序和管理数据库连接。相反,您只需调用 Data API 提供的安全 API 端点,即可对 Amazon Redshift 集群运行 SQL 命令。Data API 负责管理数据库连接和缓冲数据。Data API 是异步的,因此您可以稍后检索结果。

API Gateway 一种完全托管的服务,可让开发人员更轻松地发布、维护、监控任何规模的 API 并保护其安全。利用 API Gateway,您可以创建支持实时双向通信应用程序的 RESTful API 和 WebSocket API。API Gateway 支持容器化和无服务器工作负载以及 Web 应用程序,并且可充当 AWS 提供的许多计算资源的反向代理。

事件驱动型模型

事件驱动型应用程序越来越受客户的欢迎。分析报告 Web 应用程序可以通过事件驱动型模型实施。应用程序运行以响应事件,例如用户操作和不可预测的查询事件。通过将生产者流程和使用者流程分离,可以提高应用程序设计的灵活性并构建分离的流程。这种设计可以通过 Data API 和 API Gateway WebSocket 以及 REST API 实现。

REST API 调用和 WebSocket 都会在客户端与后端之间建立通信。由于 REST 的普及,您可能想知道 WebSocket 为什么会出现,以及它们如何有助于事件驱动型设计。

什么是 WebSocket,为什么我们需要它们?

在构建分析 Web 解决方案时,通常会使用单向通信。在传统环境中,客户端发起 REST API 调用以在后端运行查询,然后同步或异步地等待查询完成。“等待”这一点是为了应用轮询 这一概念而设计的。在这种上下文中,轮询在客户端不知道后端进程何时完成时执行。因此,客户端将始终向后端发出请求并进行检查。

与轮询相关的问题是什么? 主要挑战包括:

  • 增加了网络带宽中的流量 – 大量用户执行空检查将影响后端资源,并且无法很好地扩展。
  • 浪费用量 – 空请求不会交付任何业务价值。您需要支付不必要的资源费用。
  • 延迟响应 – 轮询是按时间间隔安排的。如果查询在这些间隔之间完成,那么用户只能在下次检查后看到结果。这种延迟会影响用户体验,在某些情况下,可能会导致 UI 死锁。

有关轮询的更多信息,请查看 From Poll to Push: Transform APIs using Amazon API Gateway REST APIs and WebSockets(从轮询到推送:使用 Amazon API Gateway REST API 和 WebSocket 转换 API)。

与 REST 相比,WebSocket 是另一种在前端和后端之间建立通信的方法。利用 WebSocket,您可以在客户端和服务器之间创建全双工通信通道。在这种双向场景中,客户端会向服务器发出请求,并在此过程完成时收到通知。在收到响应之前,连接将保持打开状态,并且网络开销最小。

由于可以使用 WebSocket 传输响应数据,因此,您可能想知道为什么会有 REST。WebSocket 是一项轻量级协议,专为系统之间的实时消息传递而设计。该协议并非为处理大型分析查询数据而设计的,在 API Gateway 中,每个帧的负载只能容纳最多 32 KB。因此,REST API 用于执行大型数据检索。

使用 Data API 和 API Gateway,可以构建分离的事件驱动型 Web 应用程序来满足数据分析需求。您可以使用 API Gateway 创建 WebSocket API,并在客户端和后端服务之间建立连接。然后发起请求以使用 Data API 执行分析查询。由于 Data API 的异步特性,查询完成时会生成一个事件,通过 WebSocket 通道告知客户端。客户端可以决定是通过 REST API 调用来检索查询结果,还是执行其他后续操作。事件驱动型架构支持双向可互操作的消息和数据,同时确保与系统组件无关。

解决方案概览

在这篇文章中,我们说明了如何通过在后端使用 Data API 进行查询,使用 API Gateway 中的 WebSocket 功能在用户和后端之间建立双向通信通道,以及使用 REST API 功能检索结果,以此来创建无服务器事件驱动型 Web 应用程序。您可以使用 Data API,而不是设计具有长时间运行的 API 调用的应用程序。利用 Data API,您可以异步运行 SQL 查询,避免了保持长时间的持久数据库连接。

Web 应用程序可使用 Amazon Cognito 进行保护,后者在用户使用 Web 应用程序之前先对其进行身份验证,还用于授权从应用程序发出的 REST API 调用。

此解决方案中的其他相关 AWS 服务包括 AWS LambdaAmazon EventBridge。Lambda 是一种无服务器的事件驱动型计算资源,让您无需预置或管理服务器即可运行代码。EventBridge 是一种无服务器的事件总线,可用于构建事件驱动型应用程序。

此解决方案在浏览器和后端之间创建轻量级 WebSocket 连接。当用户使用 WebSocket 向后端提交请求时,将向 Data API 提交查询。查询完成后,Data API 会向 EventBridge 发送事件通知。EventBridge 会告知系统数据可用并通知客户端。之后,执行 REST API 调用来检索查询结果以供客户端查看。

我们已在 AWS 示例 GitHub 存储库上发布此解决方案,本文的其余部分中将引用它。

以下架构图重点介绍了端到端解决方案,您可以使用 AWS CloudFormation 模板自动预置该解决方案,这些模板作为具有一些参数变量的 Shell 脚本的一部分运行。

应用程序执行以下步骤(请记下流程中相应的已编号步骤):

  1. Web 应用程序在 AWS Amplify 上预置;用户需要先提供他们的电子邮件和密码进行注册,之后才能访问该站点。
  2. 用户使用发送到其电子邮件的 PIN 来验证凭证。此步骤必须先执行,之后用户才能登录应用程序并继续访问应用程序的其他功能。
  3. 用户在注册并经过验证后,可以登录应用程序,使用输入参数通过其 Web 或移动客户端请求数据。这将在 API Gateway 中启动 WebSocket 连接。(流程 1、2)
  4. 连接请求由一个 Lambda 函数(即 OnConnect)处理,此函数使用 Data API 在 Amazon Redshift 中启动异步数据库查询。使用来自客户端的动态输入,从 Amazon Simple Storage Service(Amazon S3)中的 SQL 脚本执行 SQL 查询。(流程 3、4、6、7)
  5. 此外,OnConnect Lambda 函数将连接、语句标识符和主题名称存储在 Amazon DynamoDB 数据库中。主题名称是一个额外的参数,如果用户需要在同一个网页上实施多个报告,则可使用此参数。这可让前端将响应映射到正确的报告。(流程 3、4、5)
  6. Data API 将运行查询,如步骤 2 中所述。操作完成后,将向 EventBridge 发送事件通知。(流程 8)
  7. EventBridge 会激活一个事件规则,将该事件重定向到另一个 Lambda 函数(即 SendMessage)。(流程 9)
  8. SendMessage 函数通过 API Gateway 通知客户端 SQL 查询已完成。(流程 10、11、12)
  9. 收到通知后,客户端将执行 REST API 调用(GET)以获取结果。(流程 13、14、15、16)
  10. 这将触发 GetResult 函数,检索 SQL 查询结果并返回给客户端。
  11. 用户现在可以在网页上查看结果。
  12. 当客户端断开与浏览器的连接时,API Gateway 将使用 onDisconnect 函数,自动从 DynamoDB 表中删除连接信息。(流程 17、18、19)

先决条件

在部署事件驱动型 Web 应用程序之前,请确保您满足以下条件:

  • AWS 环境中的 Amazon Redshift 集群 – 这是后端数据仓库解决方案,用于运行分析查询。有关创建 Amazon Redshift 集群的说明,请参阅 Amazon Redshift 入门
  • 您有权访问的 S3 存储桶 – S3 存储桶将是用于存储 SQL 脚本的对象存储解决方案。要创建 S3 存储桶,请参阅创建您的第一个 S3 存储桶

部署 CloudFormation 模板

在以下 GitHub 存储库中可找到与设计相关的代码。您可以在我们的 AWS 账户中的 AWS Cloud9 环境中克隆存储库。AWS Cloud9 环境安装了 AWS 命令行界面(AWS CLI),此界面用于运行 CloudFormation 模板来设置 AWS 基础设施。确保已安装 jQuery 库;在脚本运行期间,我们使用该库解析 JSON 输出。

完整架构使用三个 CloudFormation 模板进行设置:

  • cognito-setup.yaml – 创建连接到 Web 应用程序客户端的 Amazon Cognito 用户群体,用于进行身份验证和保护 REST API
  • backend-setup.yaml – 创建所需的全部 Lambda 函数以及 WebSocket 和 Rest API,然后在 API Gateway 上对其进行配置
  • webapp-setup.yaml – 使用 Amplify 创建 Web 应用程序托管,与 WebSocket 和 Rest API 进行连接和通信。

这些 CloudFormation 模板使用 script.sh Shell 脚本运行,该脚本根据需要处理所有依赖项。

系统提供了通用模板,供您自定义 DDL SQL 脚本和查询 SQL 脚本。我们创建了示例脚本以供您参考。

  1. 下载示例 DDL 脚本并将它上传到现有 S3 存储桶。
  2. 将 IAM 角色的值更改为 Amazon Redshift 集群的具有 AmazonS3ReadOnlyAccess 权限的 IAM 角色。

对于本文,我们从公共 S3 存储桶中复制了 New York Taxi Data 2015 数据集。

  1. 下载示例查询脚本并将它上传到现有 S3 存储桶。
  2. 将修改后的示例 DDL 脚本和示例查询脚本上传到您拥有的现有 S3 存储桶中,并记下 S3 URI 路径。

如果您想运行自己的自定义版本,请修改 DDL 和查询脚本以适应您的场景。

  1. 在运行 script.sh 文件之前对该文件进行 编辑,并设置以下参数的值:
    • RedshiftClusterEndpoint (aws_redshift_cluster_ep) – 您在 AWS 管理控制台上可用的 Amazon Redshift 集群端点
    • DBUsername (aws_dbuser_name) – 您的 Amazon Redshift 数据库用户名
    • DDBTableName (aws_ddbtable_name) – 将创建的 DynamoDB 表的名称
    • WebsocketEndpointSSMParameterName (aws_wsep_param_name) – 在 AWS Systems Manager Parameter Store 中存储 WebSocket 端点时使用的参数名。
    • RestApiEndpointSSMParameterName (aws_rapiep_param_name) – 在 Parameter Store 中存储 REST API 端点时使用的参数名。
    • DDLScriptS3Path (aws_ddl_script_path) – 上传的 DDL 脚本的 S3 URI。
    • QueryScriptS3Path (aws_query_script_path) – 上传的查询脚本的 S3 URI。
    • AWSRegion (aws_region) – 在其中设置 AWS 基础设施的区域。
    • CognitoPoolName (aws_user_pool_name) – 要提供给 Amazon Cognito 用户群体的名称
    • ClientAppName (aws_client_app_name) – 为 Web 应用程序配置的客户端应用程序的名称,用于处理用户的用户身份验证

默认的可接受值已在下载的代码中提供。

  1. 使用以下命令运行脚本:
./script.sh

在部署期间,AWS CloudFormation 会创建并触发 Lambda 函数 SetupRedshiftLambdaFunction,该函数用于设置 Amazon Redshift 数据库表并将数据填充到该表中。下图展示了此流程。

使用演示应用程序

在 Shell 脚本完成后,您可以开始与演示 Web 应用程序进行交互:

  1. 在 Amplify 控制台上,在导航窗格中的 All apps(所有应用程序)下,选择 DemoApp
  2. 选择 Run build(运行构建)。

DemoApp Web 应用程序将经历预置、构建、部署阶段。

  1. 完成后,使用提供的 URL 访问 Web 应用程序。

以下屏幕截图显示了 Web 应用程序页面。其中具有很少的功能:您可以登录、注册或验证用户。

  1. 选择 Sign Up(注册)。

  1. 对于 Email ID(电子邮件 ID),输入电子邮件。
  2. 对于 Password(密码),输入长度至少为八个字符、至少包含一个大写字母和一个小写字母、至少一个数字以及至少一个特殊字符的密码。
  3. 选择 Let’s Enroll(注册)。

这将打开 Verify your Login to Demo App(验证演示应用程序的登录)页面。

  1. 输入您的电子邮件和发送到指定电子邮件地址的验证码。
  2. 选择 Verify(验证)。


系统会将您重定向到登录页面。

  1. 使用您的凭证进行登录。

系统会将您重定向到 demoPage.html 网站。

  1. 选择 Open Connection(打开连接)。

现在,您已在浏览器和后端 AWS 环境之间建立一个活动 WebSocket 连接。

  1. 对于 Trip Month(行程月份),指定一个月份(本示例中为十二月),然后选择 Submit(提交)。

现在,您已定义要查询数据的月份和年份。几秒钟后,您会看到从 WebSocket 传送的输出。

您可以继续使用活动 WebSocket 连接进行其他查询 – 只需选择不同的月份,并再次选择 Submit(提交)。

  1. 完成后,选择 Close Connection(关闭连接)以关闭 WebSocket 连接。

出于探索目的,当 WebSocket 连接处于活动状态时,您可以在 DynamoDB 控制台上导航到 DynamoDB 表,查看当前存储的项目。关闭 WebSocket 连接后,存储在 DynamoDB 中的项目将被删除。

清理

要清理您的资源,请完成以下步骤:

  1. 在 Amazon S3 控制台上,导航到包含示例 DDL 脚本和查询脚本的 S3 存储桶,然后从该存储桶中删除这些脚本。
  2. 在 Amazon Redshift 控制台上,导航到您的 Amazon Redshift 集群,然后删除从示例 DDL 脚本中复制的数据。
    1. 运行 truncate nyc_yellow_taxi;
    2. 运行 drop table nyc_yellow_taxi;
  3. 在 AWS CloudFormation 控制台上,导航到 CloudFormation 堆栈并选择 Delete(删除)。按以下顺序删除堆栈:
    1. WebappSetup
    2. BackendSetup
    3. CognitoSetup

此解决方案中创建的所有资源都将被删除。

监控

使用 Amazon CloudWatchAWS CloudTrail 可以监控事件驱动型 Web 应用程序事件、用户活动和 API 使用情况。此解决方案的大部分区域都已启用日志记录功能。要查看 API Gateway 日志,可以启用 CloudWatch Logs。Lambda 具有默认的日志记录和监控功能,可以使用 CloudWatch 访问这些功能。

安全

您可以使用 Amazon Cognito 保护对应用程序的访问,这是一种以开发人员为中心的、经济实用的客户身份验证、授权和用户管理解决方案。它提供了可轻松扩展的身份存储和联合身份验证选项。Amazon Cognito 支持使用社交身份提供程序以及基于 SAML 或 OIDC 的身份提供程序进行登录,并支持各种合规性标准。它基于开放身份标准(OAuth2.0、SAML 2.0 和 OpenID Connect)运行。您也可以将它与 API Gateway 集成,使用 Amazon Cognito 客户端应用程序或 Lambda 函数对 REST API 调用进行身份验证和授权。

注意事项

此应用程序的性质使其包括启动对 Amazon Redshift 的 SQL 查询的前端客户端。需要注意的重点是,客户端可能执行的潜在恶意活动,例如 SQL 注入。在目前的实施中,不可能出现这种情况。在此解决方案中,SQL 查询是预先存在于 AWS 环境中的 DQL 语句(它们不更改数据或结构)。不过,在开发此应用程序以满足业务需求时,应评估这些风险领域。

AWS 提供了各种安全服务来帮助保护云中的工作负载和应用程序,包括 AWS ShieldAWS Network FirewallAWS Web Application Firewall 等。有关更多信息和完整列表,请参阅 AWS 上的安全性、身份和合规性

成本优化

在此解决方案中,CloudFormation 模板预置的 AWS 服务均为无服务器服务。在成本优化方面,您只需为使用的资源付费。此模型还可让您无需手动干预即可进行扩展。查看以下页面,确定每项服务的相关定价:

小结

在这篇文章中,我们向您演示了如何使用 Amazon Redshift Data API、API Gateway WebSocket 以及 REST API 创建事件驱动型应用程序。此解决方案可帮助您在事件驱动型架构中构建数据分析 Web 应用程序,分离应用程序,优化长时间运行的数据库查询进程,并避免客户端和后端之间的不必要的轮询请求。

您还使用了无服务器技术、API Gateway、Lambda、DynamoDB 和 EventBridge。在整个过程中,您无需管理或预置任何服务器。

这种事件驱动型无服务器架构提供了更高的可扩展性,并且更加简单,简化了维护和发布新功能的过程。同时还简化了添加新组件或第三方产品的过程。

按照本文中的说明以及我们提供的通用 CloudFormation 模板,您可以根据自身业务量身定制事件驱动型应用程序。要提供反馈或投稿,欢迎您通过 AWS 示例 GitHub 存储库创建问题来联系我们。


关于作者

David Zhang 是全球金融服务领域的 AWS 数据架构师。他专门设计和实施无服务器分析基础设施、数据管理、ETL 和大数据系统,帮助客户在 AWS 上实现数据平台的现代化。David 还是活跃的 AWS 会议、技术内容和开源计划演讲者和撰稿人。业余时间,他喜欢打排球、网球以及举重。您可以随时在 LinkedIn 上与他联系。

Manash Deb 是 AWS Directory Service 团队的软件开发经理。他拥有超过 18 年的软件开发经验,热爱在 AWS 身份和数据分析领域设计并交付高度可扩展、安全、零维护的应用程序。他乐于指导和辅导他人,发挥催化剂和力量倍增器的作用,领导积极进取的工程团队,构建大规模的分布式系统。

Pavan Kumar Vadupu Lakshman Manikya 是一位 AWS 解决方案架构师,他帮助客户设计跨多个行业的可靠、可扩展的解决方案。Pavan 拥有企业架构和软件开发背景,帮助他的客户创建用于处理 API 安全、API 管理、微服务和地理空间信息系统使用场景的解决方案。他热爱学习新的技术以及使用这些解决方案来解决、自动化和简化客户问题。