发布于 2026-01-06 8 阅读
0

基于数据库的实时架构:构建无服务器可编辑聊天应用 - 第一部分

基于数据库的实时架构:构建无服务器可编辑聊天应用 - 第一部分

介绍

数据库驱动的实时架构正变得越来越普遍,Firebase 和 Supabase 等软件的主要支持者和广泛使用就证明了这一点。

对于遵循数据库驱动的实时消息传递的应用程序而言,两个关键优先事项是长期存储和从数据库捕获变更数据 (CDC) 更新。

在本系列文章(共两部分)中,我们将详细介绍一款完全无服务器的聊天应用,用户可以在其中编辑之前发布的消息。该聊天应用使用 Ably Postgres 连接器来实​​现这一功能,您将在文章中看到相关细节。如果您正在寻找构建能够无缝扩展的数据库驱动型应用程序的方法,那么本文的架构和示例应用将对您有所帮助。

我们之前曾撰文探讨过如何将数据库与实时消息传递解耦

主要问题在于缺乏模块化:每个工具都应该各司其职。数据库是数据的基础。它们应该只做好一件事,那就是成为唯一的数据源和权威来源。它们绝不应该承担实时处理的任务——这并非它们的强项。它们应该专注于存储,而实时通信则应该由另一个专门的组件负责。所有其他问题都源于此。

虽然实时数据库的概念听起来很棒,并且为利用这种架构构建各种可能的用例开辟了道路,但是数据库和实时消息传递的紧密耦合可能会遇到上面链接的文章中描述的各种问题。

此外,并非所有事件触发都会产生重要数据,因此无需存储。有些事件可能只是短暂的,目的是让客户端感知到某个事件的发生,甚至不一定包含事件的描述性细节。例如,在聊天应用中,我可能只想存储消息、时间戳等信息,而不一定需要存储输入指示事件。

最近的一篇文章中,我介绍了由我们社区一位专家开发的Ably-Postgres 连接器。它利用 Postgres 数据库的监听/通知功能来监听任何数据库表的变更,并在变更发生时将更新发布到指定的 Ably 频道。这使我们能够充分利用数据库驱动的架构,而无需担心实时消息传递的可扩展性或两者之间复杂的交互关系。

来看看这款可编辑的聊天应用: https://serverless-scalable-chat.netlify.app/

可编辑的聊天应用程序架构

让我向您展示一个看似复杂的架构,但当您读完本文后,就会更容易理解它的含义。

可编辑聊天应用架构

从最终用户的角度来看,他们会在前端应用上发布消息,也希望能够接收来自该应用的消息。编辑消息也是如此:所有参与者都需要能够编辑自己的消息,并且能够接收其他用户编辑的消息的更新通知。

在使用 Ably 这类发布/订阅消息服务时,一种常见的架构设置是将更新发布到客户端也订阅的频道上。虽然这种方法对于常规聊天消息或其他事件触发都非常有效,但由于 Ably 消息本质上是不可变的,因此编辑先前发布的消息或触发关于先前消息更改的更新就比较复杂。

然而,我们可以通过一种略微非传统的方法来实现此功能。我们不必订阅用户发布消息的单个聊天频道,而是将传入和传出的聊天频道分开。这样做允许我们在数据通过订阅回调返回之前对其进行各种操作。这种架构的一个常见用例是消息过滤,例如应用脏话过滤器

对于当前的聊天应用,我们将使用数据库将所有已发布的消息直接存储在一个表中。我们还会设置一个监听器,用于监听消息发布情况。

i) 观察我们数据库聊天数据表中的insertupdate和 的变化,以及delete

ii) 在 Ably 频道上发布一条消息,其中包含操作名称以及变更数据捕获 (CDC)。

如果我们让前端客户端订阅监听器发布数据库更新的频道,我们不仅会收到insert数据库操作产生的新消息,还会收到之前update数据库操作产生的更新消息。每条 Ably 消息都带有msgIdAbly 分配的唯一标识符,因此我们可以利用该标识符在表中唯一标识每条消息。数据库将成为应用程序中的唯一数据源,并且在我们需要加载聊天中的历史消息时(例如Ably-Airtable 入门套件示例中那样)也非常有用。

在继续之前,请再看一下上面的架构图,以便更好地理解所有步骤并将其联系起来。

技术栈

我们开发这款可编辑聊天应用的主要目标有四点:

  • 可扩展性
  • 无服务器架构
  • 消息可编辑性
  • 消息存储

鉴于以上情况,让我解释一下这款聊天应用中各种技术选择背后的一些原因,以及一些替代方案。

可编辑聊天应用程序的技术栈

NuxtJS 用于前端 Web 开发

Nuxt旨在为常见的 Web 开发问题(如路由、状态管理、代码分割等)提供最佳实践解决方案。它允许我们在静态站点中使用各种 NPM 实用程序库,该站点可以直接从 CDN 部署和使用,而无需服务器,即遵循Jamstack 架构

就我们的聊天应用程序而言,这样做的好处在于可以将状态管理与视觉组件完全分离,这样所有技术栈的开发人员都可以了解聊天应用程序与外部服务(在本例中主要是 Ably)之间的通信和数据交换。

您可以根据应用程序的需求和愿望,将 Nuxt 替换为任何其他前端 Web 框架、原生 JS,甚至使用原生移动编程语言。

能够启用发布/订阅模式

Ably是一款实时消息传递基础设施即服务 (IaaS)。只需几行代码,即可在您的应用程序中启用基于发布/订阅的消息传递功能。Ably 提供高度可靠、低延迟的消息传递,并可在全球任何平台或设备上运行。它完全抽象化了跨全球多个地区扩展实时通信的复杂问题,使开发人员能够专注于应用程序逻辑。

用于在数据库中插入和更新行的 AWS Lambda 函数

我们使用 PostgresDB 来存储聊天应用的消息。通常情况下,任何会更改表数据的数据库事务都不应该直接从前端执行,以避免潜在的安全风险。因此,我们将使用AWS Lambda函数代表用户对数据库进行更改。鉴于我们的目标是使该应用完全无服务器,Lambda 函数与此理念完美契合。

使用托管在 AWS RDS 上的 PostgresDB 来存储数据

Postgres是一个开源的 SQL 数据库。它的性能和可靠性使其成为复杂生产应用的理想选择。选择 Postgres 还有另一个特殊原因,您将在下一点中看到。

Postgres 本身不提供托管服务,我们需要使用其他服务来托管数据库。同样,为了保持无服务器架构,我选择了AWS RDS来托管 Postgres。使用 AWS 的另一个优势是,数据可以在其他 AWS 服务之间访问,例如前面提到的 Lambda 函数。

Ably Postgres 连接器,用于监视数据库表的更改并在每次更改时发布消息。

这款聊天应用的关键需求之一是能够监听数据库表的变化并将这些变化发布到 Ably。Ably Postgres 连接器是一个社区构建的项目,它实现了这一功能。我们之所以选择 Postgres,是因为其内置的监听/通知功能使该连接器能够正常工作。稍后我们将详细介绍它。

使用 AWS Fargate、AWS ECS 和 AWS ECR 部署 Ably Postgres 连接器的 Docker 化镜像

AWS Fargate是一个无服务器计算引擎,用于托管容器。Ably Postgres 连接器有一个 Docker 化的镜像,需要托管在某个地方。我们将使用 AWS Fargate 来实现这一点,因为它能够轻松安全地在 AWS 等单一服务上管理后端部署和托管。

AWS Fargate 与AWS ECS协同工作,支持容器化应用程序的部署和管理。我们使用AWS ECR上传 Docker 镜像,以便将其存储在镜像仓库中,供 ECS 按需使用。

Netlify 将托管 Jamstack 静态网站

Netlify提供了一个无服务器平台来部署 Web 应用程序。它还允许设置基于 Git 的工作流,以便在代码仓库发生更改时自动构建和部署静态网站的新版本。Nuxt 应用程序就是使用 Netlify 部署的。

Netlify 函数启用令牌认证端点,以便与 Ably 进行身份验证。

Netlify 的无服务器平台还提供无服务器函数,可用于执行特定功能。Ably 服务要求客户​​端通过两种方式之一进行身份验证:基本身份验证或令牌身份验证。基本身份验证会将 API 密钥直接暴露在前端脚本中,因此不应在生产环境中使用。您几乎应该始终选择令牌身份验证。为此,我们需要设置一个身份验证端点,用于验证前端客户端的凭据并发出 Ably 令牌请求。然后,前端客户端可以使用此 Ably 令牌请求向 Ably 进行身份验证并使用其服务。

鉴于我们使用 Netlify 来托管聊天应用,自然而然地,我们也应该使用Netlify 函数来托管身份验证端点。虽然 AWS Lambda 已经是我们技术栈的一部分,但它需要我们先为用户设置身份和访问管理 (IAM) 权限,用户才能访问 AWS Lambda。而 Netlify 则让这一切变得非常简单。

Ably Postgres 连接器——一个关键依赖项

在深入了解聊天应用程序的细节之前,让我们先来了解一下使这种架构成为可能的 Ably Postgres 连接器的工作原理。

我最近写了一篇文章,详细解释了 Ably Postgres 连接器

该连接器接受一个配置文件,您可以在其中输入数据库的连接详细信息,以及要监听数据更改的表。它还接受一个Ably API 密钥,以便在指定表发生任何更改时,能够实例化 Ably 应用并向其发布消息。

连接器会根据配置文件在您的数据库中创建一个名为“ablycontroltable”的特殊表。该表用于维护 Ably 通道映射,以应对数据库中表的不同更改。

接下来,连接器会创建一个过程,使用该函数监听指定表的更改pg_notify。然后,此通知函数会将更改数据捕获 (CDC) 有效负载发布到配置中指定的 Ably 相关通道上。

Ably Postgres 连接器


希望通过以上内容,您对无服务器可编辑聊天应用程序的高级架构有了更深入的了解。

在本系列文章的下一部分中,我们将更仔细地研究聊天应用程序的各个组件,并深入研究一些代码,以更好地了解每个步骤是如何实现的。

以下是我们将在下一部分中看到的一些内容:

  • 即使您不是 Nuxt 开发人员,也能轻松使用 Nuxt 应用。
  • VueX 状态管理
  • Postgres数据库设置
  • 在 Ably Integrations 控制面板上设置 Lambda 函数
  • Ably Postgres 连接器设置
  • 部署所有组件

敬请关注,下一篇文章即将发布。同时,您可以查看可编辑聊天应用的演示,或访问 GitHub 代码库

如有任何疑问,请随时与我联系。

资源

文章来源:https://dev.to/ively/database-driven-realtime-architectures-building-a-serverless-and-editable-chat-app-part-1-1ceh