

# 教程：使用 WebSocket API、Lambda 和 DynamoDB 创建 WebSocket 聊天应用程序
<a name="websocket-api-chat-app"></a>

在本教程中，您将使用 WebSocket API 创建无服务器聊天应用程序。借助 WebSocket API，您可以支持客户端之间的双向通信。客户端可以接收消息，而无需轮询更新。

完成本教程需要大约 30 分钟。首先，您将使用 CloudFormation 模板来创建用于处理 API 请求的 Lambda 函数，以及存储客户端 ID 的 DynamoDB 表。然后，您将使用 API Gateway 控制台创建与您的 Lambda 函数集成的 WebSocket API。最后，您将测试 API 以验证消息是否已发送和接收。

![\[您在本教程中创建的 API 的架构概述。\]](http://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/images/ws-chat-app.png)


要完成本教程，您需要一个AWS账户以及一位具有控制台访问权限的 AWS Identity and Access Management 用户。有关更多信息，请参阅 [设置为使用 API Gateway](setting-up.md)。

还需要 `wscat` 以连接到 API。有关更多信息，请参阅 [使用 `wscat` 连接到 WebSocket API 并向其发送消息](apigateway-how-to-call-websocket-api-wscat.md)。

**Topics**
+ [步骤 1：创建 Lambda 函数和 DynamoDB 表](#websocket-api-chat-app-create-dependencies)
+ [步骤 2：创建 WebSocket API](#websocket-api-chat-app-create-api)
+ [步骤 3：测试您的 API](#websocket-api-chat-app-invoke-api)
+ [步骤 4：清除](#websocket-api-chat-app-cleanup)
+ [接下来的步骤：通过 实现自动化CloudFormation](#websocket-api-chat-app-next-steps)

## 步骤 1：创建 Lambda 函数和 DynamoDB 表
<a name="websocket-api-chat-app-create-dependencies"></a>

下载并解压缩[适用于 CloudFormation 的应用程序创建模板](samples/ws-chat-app-starter.zip)。您将使用此模板创建 Amazon DynamoDB 表以存储应用程序的客户端 ID。每个连接的客户端都有一个唯一 ID，我们要将其用作表的分区键。此模板还创建 Lambda 函数，这些函数用于更新 DynamoDB 中的客户端连接并处理向已连接的客户端发送消息的事宜。

**创建 CloudFormation 堆栈**

1. 打开 CloudFormation 控制台，地址：[https://console.aws.amazon.com/cloudformation](https://console.aws.amazon.com/cloudformation/)。

1. 选择**创建堆栈**，然后选择**使用新资源(标准)**。

1. 对于**指定模板**，选择**上传模板文件**。

1. 选择您下载的模板。

1. 选择**下一步**。

1. 对于**堆栈名称**，输入 **websocket-api-chat-app-tutorial**，然后选择**下一步**。

1. 对于**配置堆栈选项**，请选择**下一步**。

1. 对于**功能**，请确认 CloudFormation 可以在您的账户中创建 IAM 资源。

1. 选择**下一步**，然后选择**提交**。

CloudFormation 预置在模板中指定的资源。完成资源预置可能需要几分钟时间。当 CloudFormation 堆栈的状态为 **CREATE\$1COMPLETE** 时，您就可以继续下一步了。

## 步骤 2：创建 WebSocket API
<a name="websocket-api-chat-app-create-api"></a>

您将创建 WebSocket API 来处理客户端连接并将请求路由到您在步骤 1 中创建的 Lambda 函数。



**创建 WebSocket API**

1. 通过以下网址登录到 Amazon API Gateway 控制台：[https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway)。

1. 选择**创建 API**。对于 **WebSocket API**，选择**构建**。

1. 对于 **API 名称**，请输入 **websocket-chat-app-tutorial**。

1. 为 **IP 地址类型**选择 **IPv4**。

1. 对于**路由选择表达式**，输入 **request.body.action**。路由选择表达式确定当客户端发送消息时 API Gateway 调用的路由。

1. 选择**下一步**。

1. 对于 **Predefined routes**（预定义路由），选择 **Add \$1connect**（添加 \$1connect）、**Add \$1disconnect**（添加 \$1disconnect）和 **Add \$1default**（添加 \$1default）。**\$1connect** 和 **\$1disconnect** 路由是 API Gateway 在客户端连接到 API 或断开与 API 的连接时自动调用的特殊路由。当没有其他路由与请求匹配时，API Gateway 调用 `$default` 路由。

1. 对于 **Custom routes**（自定义路由），选择 **Add custom route**（添加自定义路由）。对于 **Route key**（路由键），请输入 **sendmessage**。此自定义路由处理发送到已连接的客户端的消息。

1. 选择**下一步**。

1. 在 **Attach integrations**（附加集成）下，对于每个路由和 **Integration type**（集成类型），选择 Lambda。

   对于 **Lambda**，请选择您在步骤 1 中使用 CloudFormation 创建的相应 Lambda 函数。每个函数的名称与一个路由匹配。例如，对于 **\$1connect** 路由，选择名为 **websocket-chat-app-tutorial-ConnectHandler** 的函数。

1. 查看 API Gateway 为您创建的阶段。原定设置情况下，API Gateway 会创建阶段名称 `production`，然后自动将您的 API 部署到该阶段。选择**下一步**。

1. 选择 **Create and deploy**（创建和部署）。

## 步骤 3：测试您的 API
<a name="websocket-api-chat-app-invoke-api"></a>

接下来，测试您的 API 以确保它正常工作。使用 `wscat` 命令连接到 API。

**获取调用 API 的调用 URL**

1. 通过以下网址登录到 Amazon API Gateway 控制台：[https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway)。

1. 选择 API。

1. 选择**阶段**，然后选择**生产**。

1. 记下 API 的 **WebSocket URL**。该 URL 应类似于 `wss://abcdef123.execute-api.us-east-2.amazonaws.com/production`。

**连接到您的 API**

1. 使用以下命令连接到您的 API。当您连接到 API 时，API Gateway 会调用 `$connect` 路由。调用此路由时，它会调用用于将连接 ID 存储在 DynamoDB 中的 Lambda 函数。

   ```
   wscat -c wss://abcdef123.execute-api.us-west-2.amazonaws.com/production
   ```

   ```
   Connected (press CTRL+C to quit)
   ```

1. 打开一个新终端并使用以下参数再次运行 **wscat** 命令。

   ```
   wscat -c wss://abcdef123.execute-api.us-west-2.amazonaws.com/production
   ```

   ```
   Connected (press CTRL+C to quit)
   ```

   这为您提供了两个可以交换消息的已连接客户端。

**发送邮件**
+  API Gateway 根据 API 的路由选择表达式确定要调用的路由。您的 API 的路由选择表达式是 `$request.body.action`。因此，当您发送以下消息时，API Gateway 会调用 `sendmessage` 路由：

  ```
  {"action": "sendmessage", "message": "hello, everyone!"}
  ```

  与调用的路由关联的 Lambda 函数会从 DynamoDB 收集客户端 ID。然后，该函数调用 API Gateway 管理 API 并将消息发送给这些客户端。所有连接的客户端都会收到以下消息：

  ```
  < hello, everyone!
  ```

**调用 API 的 \$1default 路由**
+ 当客户端发送与您定义的路由不匹配的消息时，API Gateway 会调用您的 API 的默认路由。与 `$default` 路由关联的 Lambda 函数使用 API Gateway 管理 API 发送有关其连接的客户端信息。

  ```
  test
  ```

  ```
  Use the sendmessage route to send a message. Your info: {"ConnectedAt":"2022-01-25T18:50:04.673Z","Identity":{"SourceIp":"192.0.2.1","UserAgent":null},"LastActiveAt":"2022-01-25T18:50:07.642Z","connectionID":"Mg_ugfpqPHcCIVA="}
  ```

**从 API 断开连接**
+ 按 **CTRL\$1C** 以从 API 断开连接。当客户端与 API 断开连接时，API Gateway 会调用 API 的 `$disconnect` 路由。适用于 API 的 `$disconnect` 路由的 Lambda 集成会从 DynamoDB 中删除连接 ID。

## 步骤 4：清除
<a name="websocket-api-chat-app-cleanup"></a>

为避免不必要的成本，请删除作为本教程的一部分而创建的资源。以下步骤将删除您的 CloudFormation 堆栈和 WebSocket API。

**删除 WebSocket API**

1. 通过以下网址登录到 Amazon API Gateway 控制台：[https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway)。

1. 在 **API** 页面上，选择您的 `websocket-chat-app-tutorial` API。选择**操作**，选择**删除**，然后确认您的选择。

**删除 CloudFormation 堆栈**

1. 打开 CloudFormation 控制台，地址：[https://console.aws.amazon.com/cloudformation](https://console.aws.amazon.com/cloudformation/)。

1. 选择您的 CloudFormation 堆栈。

1. 选择**删除**，然后确认您的选择。

## 接下来的步骤：通过 实现自动化CloudFormation
<a name="websocket-api-chat-app-next-steps"></a>

您可以自动创建和清理本教程中涉及的所有 AWS 资源。有关创建此 API 和所有相关资源的 ‭CloudFormation 模板，请参阅 [ws-chat-app.yaml](samples/ws-chat-app.zip)。