Featured image of post 使用 AWS Amplify、Lambda、API Gateway 和 DynamoDB 部署静态 Web 应用

使用 AWS Amplify、Lambda、API Gateway 和 DynamoDB 部署静态 Web 应用

本文详细介绍了如何使用 AWS 无服务器服务构建完整的 Web 应用,包括前端部署、后端逻辑实现、API 集成和数据库操作,涵盖 Lambda 函数编写、API Gateway 配置、DynamoDB 设置和 Amplify 部署等关键技术环节。

如何使用 AWS Amplify、Lambda、API Gateway 和 DynamoDB 部署静态 Web 应用

构建现代 Web 应用通常涉及复杂的设置和服务器管理,但其实不必如此。Amazon Web Services (AWS) 提供了一套强大的"无服务器"服务,让您能够构建和部署应用而无需担心底层基础设施。这意味着 AWS 会为您处理所有繁重的服务器、扩展和维护工作。

在本教程中,我们将引导您使用几个关键的 AWS 无服务器服务构建一个简单但功能完整的 Web 应用。您将学习如何将前端(用户看到的界面)与强大的后端(处理数据的部分)连接起来,后端可以自动高效地扩展。

目录

我们将构建什么:无服务器求和计算器

我们将创建一个简单的求和计算器 Web 应用。该应用将允许用户输入两个数字,将它们发送到我们的 AWS 后端进行计算,存储结果,然后将和显示给用户。

我们的计算器工作流程如下:

  1. 首先,获取用户输入:您将在简单的网页中输入两个数字。
  2. 然后后端通过 AWS Lambda 实现魔法:这些数字将被发送到运行在 AWS Lambda 上的特殊代码片段,该代码会将它们相加。
  3. 接着,使用 DynamoDB 存储数据:计算详情(两个数字、它们的和以及计算时间)将保存在名为 DynamoDB 的超快速数据库中。
  4. 最后,显示结果:和将被发送回您的网页并显示给您。

这个项目是理解无服务器架构核心概念以及不同 AWS 服务如何协同工作创建动态 Web 应用的绝佳方式。

我们将使用的核心 AWS 服务

在深入之前,让我们熟悉我们将要使用的主要 AWS 服务。将它们视为专业工具,每个工具都有自己的工作,共同构建我们的应用。

AWS Lambda:想象您有一个小机器人,只有在被赋予特定任务时才会激活。这就是 Lambda!它是一个"无服务器计算"服务,意味着您不需要管理任何服务器。您只需上传代码(在本例中是我们的计算器逻辑),Lambda 只在需要时运行它。

为什么我们使用它:它处理我们的后端数学(相加数字)。当用户请求求和时,Lambda"唤醒",进行计算,然后返回睡眠状态。这很高效且成本效益高,因为您只需为代码实际运行的时间付费。

Amazon API Gateway:将其视为您后端的门卫或接待员。当您的网页想要与您的 Lambda 函数通信时,它不会直接对话。相反,它向 API Gateway 发送请求。

为什么我们使用它:API Gateway 安全地接收来自我们网页的请求(如"请将这两个数字相加"),然后告诉正确的 Lambda 函数唤醒并处理它。它充当我们后端的安全入口点,确保只有授权的请求才能通过。

Amazon DynamoDB:这是我们超快速、灵活的数据库。与像文件柜一样的传统数据库不同,DynamoDB 是一个 NoSQL(不仅是 SQL)数据库,非常适合快速高效地处理大量数据而无需固定结构。

为什么我们使用它:我们将使用 DynamoDB 存储计算历史(输入的数字及其和)。它设计用于处理大量流量而不会减慢速度,非常适合需要快速存储和检索数据的 Web 应用。

AWS Amplify:Amplify 就像您的 Web 和移动应用的个人施工队。它简化了构建、部署和托管前端应用的过程,并与其他 AWS 服务无缝集成。

为什么我们使用它:我们将使用 Amplify 托管我们简单的 HTML、CSS 和 JavaScript 网页。它提供了一种简单的方法将我们的网站发布到互联网上,为我们处理所有复杂的部署步骤。

先决条件:您需要什么

要跟随本教程,您应该具备:

  • AWS 账户:这是访问所有 AWS 服务所必需的。如果您没有,可以在 AWS 网站上注册免费套餐账户。
  • Python 基础知识:我们的后端逻辑将用 Python 编写。
  • 理解 REST API:了解什么是 API(应用程序编程接口)以及 RESTful API 如何工作将有所帮助,但我们会解释关键部分。
  • 熟悉 HTML/CSS/JavaScript:我们的前端将使用这些标准的 Web 技术构建。
  • NoSQL 基础知识:虽然不是严格必需,但理解数据库中的键值对概念可能有益。

让我们开始吧!

入门指南:如何构建我们的无服务器 Web 应用

我们将逐步构建我们的应用,从数据库开始,然后是我们的后端代码,用 API 连接它们,最后部署我们的前端。

步骤 1:使用 Amazon DynamoDB 设置数据库

我们的计算器需要一个地方来存储计算结果。为此,我们将使用 Amazon DynamoDB。您可以按照以下步骤进行设置:

  1. 导航到 DynamoDB 控制台: 首先,登录您的 AWS 管理控制台。在顶部的搜索栏中,输入"DynamoDB"并从结果中选择"DynamoDB"。这将带您进入 DynamoDB 仪表板。

  2. 创建新表: 在 DynamoDB 仪表板上,找到并单击"Create table"按钮。

  3. 配置您的表: 您需要为表添加以下信息:

    • 表名:输入 myTable。这将是我们数据库表的名称。
    • 分区键:输入 ID

    但您可能想知道——什么是分区键?在 DynamoDB 中,“分区键”(有时称为哈希键)就像是表中每个唯一项的主要标识符。将其视为每个记录的唯一 ID 号。它帮助 DynamoDB 快速查找和分发您的数据。对于我们的计算器,我们存储的每个计算将获得一个唯一的 ID。

    对于本教程,将所有其他设置保留为默认值。这些默认值通常足以满足基本用例。

  4. 最终确定表创建: 单击页面底部的"Create table"按钮。DynamoDB 现在将创建您的表,这通常需要几秒钟。

  5. 重要:记下表 ARN(Amazon 资源名称): 一旦您的表创建完成,单击列表中的名称(myTable)进入其详细信息页面。在"Summary"选项卡下,您将找到显示"ARN"的部分。这是您的 DynamoDB 表在 AWS 中的唯一标识符。

    复制整个 ARN 并将其保存在安全的地方(如记事本)。我们稍后在设置 Lambda 函数权限时将需要它。

步骤 2:使用 AWS Lambda 创建后端逻辑

现在我们有了数据库,让我们创建我们操作的大脑:将执行加法并保存结果的 Lambda 函数。

  1. 导航到 Lambda 控制台: 在 AWS 管理控制台搜索栏中,输入"Lambda"并从结果中选择"Lambda"。这将带您进入 Lambda 仪表板。 然后通过单击仪表板上的"Create function"按钮创建一个新函数。

  2. 配置函数: 现在,是时候配置您的函数了:

    • 从头开始创作:确保选择此选项。
    • 函数名:给您的函数起一个有意义的名称,例如 SumCalculatorFunctionAddFunc
    • 运行时:这指定了您的代码编写的编程语言。对于本教程,选择"Python 3.9"(或可用的最新 Python 3.x 运行时)。 注意:始终选择与您要编写的代码匹配的运行时!
    • 架构:保留为 x86_64(默认)。
    • 权限:暂时可以保留默认执行角色。我们稍后将修改其权限。
  3. 创建函数: 接下来,通过单击底部的"Create function"按钮创建函数。

  4. 编写 Lambda 函数代码: 现在是编写您的 Lambda 函数代码的时候了。一旦您的函数创建完成,您将被带到其配置页面。向下滚动到"Code source"部分。这是您将编写或粘贴 Python 代码的地方。

    您将看到一个默认的 lambda_function.py 文件。将其内容替换为以下 Python 代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
import json
import boto3
import time
from botocore.exceptions import ClientError

# 创建 DynamoDB 客户端。此行创建到 DynamoDB 服务的连接。
# 'boto3' 是 AWS 的 Python SDK,允许我们的 Python 代码与 AWS 服务通信。
dynamodb = boto3.resource('dynamodb')
# 指定我们要交互的 DynamoDB 表。确保 'myTable' 与您创建的名称匹配。
table = dynamodb.Table('myTable')

# 这是 Lambda 被触发时将运行的主函数。
# 'event' 包含发送到我们 Lambda 函数的数据(例如,来自我们前端的数字)。
# 'context' 提供有关调用、函数和执行环境的运行时信息。
def lambda_handler(event, context):
    # 从 'event' 数据中提取数字。
    # .get() 用于安全地检索值,如果键不存在则返回 None。
    num1 = event.get('num1')
    num2 = event.get('num2')

    # 基本验证:检查是否提供了两个数字。
    if num1 is None or num2 is None:
        # 如果没有,返回带有 400(错误请求)状态码的错误消息。
        return {
            'statusCode': 400,
            'body': json.dumps({'message': 'Both num1 and num2 are required'})
        }

    # 计算两个数字的和。
    sum_result = num1 + num2

    # 为我们的 DynamoDB 项生成唯一 ID。
    # 我们使用时间戳(当前时间,毫秒)来确保唯一性。
    partition_key = str(int(time.time() * 1000))

    # 生成排序键(可选,但对于更复杂的数据模型是良好实践)。
    # 这里,我们也使用时间戳,但您可以使用其他有意义的数据。
    sort_key = str(int(time.time()))

    # 准备要存储在我们的 DynamoDB 表中的数据(项)。
    # 这里的每个键值对代表我们数据库记录中的一个属性。
    item = {
        'ID': partition_key,  # 这匹配我们在 DynamoDB 中的分区键
        'Timestamp': sort_key, # 用于跟踪计算发生时间的附加属性
        'num1': num1,
        'num2': num2,
        'sum': sum_result
    }

    # 尝试将项存储在 DynamoDB 表中。
    try:
        table.put_item(Item=item) # 'put_item' 是 DynamoDB 添加新项的操作。
    except ClientError as e:
        # 如果存储数据时出错(例如,权限问题),返回 500 错误。
        return {
            'statusCode': 500,
            'body': json.dumps({'message': f'Error storing data in DynamoDB: {e.response["Error"]["Message"]}'})
        }

    # 如果一切成功,返回成功消息和计算详情。
    # 'statusCode: 200' 表示成功。
    return {
        'statusCode': 200,
        'body': json.dumps({
            'message': 'Sum calculated and stored successfully',
            'result': {
                'ID': partition_key,
                'Timestamp': sort_key,
                'num1': num1,
                'num2': num2,
                'sum': sum_result
            }
        })
    }

我在代码中添加了很多注释,但以下是简要说明:

  • import json, boto3, time, ClientError:这些行引入了必要的 Python 模块。
    • boto3 对于与像 DynamoDB 这样的 AWS 服务交互至关重要。
    • json 帮助我们处理 JSON 格式的数据,这在 Web API 中很常见。
    • time 用于生成唯一 ID。
    • ClientError 帮助我们捕获特定的 AWS 错误。
  • dynamodb = boto3.resource('dynamodb'):此行创建到 DynamoDB 服务的连接对象。
  • table = dynamodb.Table('myTable'):这指定了我们的 Lambda 函数将与之交互的 DynamoDB 表(我们刚刚创建的表)。
  • lambda_handler(event, context):这是 AWS Lambda 在您的函数被触发时自动调用的特殊函数。
    • event:包含有关触发的所有信息。在我们的例子中,它将包含从我们的 Web 前端发送的 num1num2
    • context:提供有关 Lambda 函数的运行时信息。
  • num1 = event.get('num1'), num2 = event.get('num2'):这些行安全地从传入的事件数据中提取数字 num1num2
  • if num1 is None or num2 is None::这是一个基本检查,以确保确实提供了两个数字。如果没有,则发回错误消息。
  • sum_result = num1 + num2:这是实际求和计算发生的地方。
  • partition_key = str(int(time.time() * 1000)):这为每个记录创建一个唯一 ID。我们使用当前时间戳(毫秒)来确保它始终唯一。
  • item = {...}:此字典定义了我们想要保存到 DynamoDB 中 myTable 的项的数据结构。
  • table.put_item(Item=item):这是核心行,告诉 DynamoDB 将我们的项保存到 myTable 表中。它被包装在 try-except 块中以捕获数据库操作期间的任何错误。
  • return { 'statusCode': 200, 'body': json.dumps({...}) }:这是我们的 Lambda 函数发送回调用者(将是 API Gateway,然后是我们的 Web 前端)的响应。状态码 200 表示成功。主体包含消息和 JSON 格式的计算结果。
  1. 部署代码: 现在是部署代码的时候了。粘贴代码后,单击代码编辑器上方的"Deploy"按钮。这将保存您的更改并使它们生效。

  2. 测试 Lambda 函数: 最后,一旦代码部署完成,您将想要测试您的 Lambda 函数(这是可选的但推荐)。单击"Deploy"按钮旁边的"Test"按钮。您将被提示配置测试事件。

    选择"New event",对于"Event template",选择"hello-world"(或者如果"hello-world"不可用,则保留为默认)。将"Event JSON"框中的示例 JSON 替换为以下测试数据:

1
{ "num1": 5, "num2": 10 }

给您的测试事件起一个名称(例如 testSum)。然后单击"Save",然后"Test"。您应该看到"Status: Succeeded"消息,并且在"Execution result"选项卡中,您将看到 statusCode: 200 和计算的和在主体中。这确认了您的 Lambda 函数正常工作!

更新 Lambda 函数权限(IAM 角色策略)

我们的 Lambda 函数当前具有默认权限,通常不包括访问 DynamoDB 的权限。我们需要明确授予它写入我们的 myTable 的权限。我们将通过 IAM(身份和访问管理)角色策略来实现。

  1. 导航到权限: 在您的 Lambda 函数的配置页面上,单击"Configuration"选项卡。然后,选择"Permissions"子选项卡。 您将看到一个"Execution role"部分,其中包含"Role name"。单击此"Role name"(它将是一个链接)。这将带您到 IAM 控制台,特别是与您的 Lambda 函数关联的角色的详细信息。

  2. 添加权限: 在 IAM 角色的页面上,您将看到标题为"Permissions policies"的部分。单击"Add permissions",然后选择"Create inline policy"。“内联策略"是直接嵌入到特定 IAM 身份(在本例中是我们的 Lambda 的执行角色)中的策略。

  3. 配置策略: 您将看到一个"Policy editor”。单击"Visual editor"选项卡(如果尚未选中)。

    • 服务:单击"Choose a service"并搜索并选择"DynamoDB"。
    • 操作:在"Actions"部分,展开"Write"。我们需要授予我们的 Lambda 函数权限以"put"项到 DynamoDB。 搜索 PutItem 并选中旁边的复选框。为什么是 PutItem? 我们的 Python 代码使用 table.put_item(Item=item) 来存储数据。此 PutItem 操作直接对应于该操作。
    • 资源:这很关键!我们需要指定我们的 Lambda 函数被允许写入哪个 DynamoDB 表。
      • 单击"Resources"部分下的"Specific"。
      • 单击"table"旁边的"Add ARN"。
      • 在弹出窗口中,粘贴您从步骤 1 复制的 DynamoDB 表 ARN。
      • 单击弹出窗口中的"Add ARN"以确认。
  4. 审查并创建策略: 单击"Next: Tags"(如果适用,跳过标签)。然后单击"Next: Review policy"。给您的策略起一个有意义的名称,例如 DynamoDBPutItemPolicy。 审查策略 JSON 以确保它授予对您特定的 myTable ARN 的 dynamodb:PutItem 权限。然后单击"Create policy"。

您的 Lambda 函数现在具有写入您的 DynamoDB

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计