数据库驱动的实时架构:构建无服务器和可编辑的聊天应用程序 - 第一部分

159 阅读11分钟

简介

Database-driven realtime architectures: building a serverless and editable chat app - Part 1

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

采用数据库驱动的实时信息传递的应用程序的两个关键优先事项是长期存储和来自数据库的变更数据捕获(CDC)更新。

在这两部分文章中,我们将详细了解一个完全无服务器的聊天应用,在这个应用中你可以编辑之前发布的消息。该聊天应用使用Ably Postgres连接器来实现这一点,其细节你会在文章中看到。如果你正在寻找建立数据库驱动的应用程序的方法,并在规模上无缝工作,你会发现这个架构和示例应用程序很有用。

我们以前写过关于数据库与实时消息传递解耦的文章。

主要问题是缺乏模块化:每个工具应该做自己的工作。 数据库是数据的基础。它们应该只做一件事,而且要做好一件事,那就是成为真理和数据的唯一基础来源。它们不应该为实时问题所累--这不是它们的设计优势。他们应该做存储,而另一个专门的部门应该做实时通信。所有其他的问题都源于此。

虽然实时数据库的想法听起来很好,并且开辟了一个巨大的可能的用例,我们可以用这种架构来构建,但是数据库和实时消息的紧密耦合可能会受到上面链接的文章中描述的各种问题的影响。

此外,并不是所有的事件触发器都构成相应的有效载荷,因此不需要进入存储。也许有些事件只是暂时性的,让客户端意识到一个事件的发生,甚至不一定是关于该事件的描述性细节。例如,在一个聊天应用程序中,我对存储消息、时间戳等感兴趣,但不一定是输入指示器事件。

最近的一篇文章中,我介绍了由我们的社区专家之一建立的Ably-Postgres连接器。它使用Postgres DB的监听/通知功能来监听任何DB表中的变化,并在变化发生时在特定的Ably通道上发布更新。这让我们可以利用数据库驱动的架构,而不必担心实时消息传递的可扩展性或两者之间的尴尬关系。

查看可编辑的聊天应用程序 :https://serverless-scalable-chat.netlify.app/

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

让我向您介绍一个看起来很复杂的架构,当您看完这篇文章后,会觉得更有意义。

Database-driven realtime architectures: building a serverless and editable chat app - Part 1

无服务器和可编辑的聊天应用程序的数据库驱动架构

从终端用户的角度来看,他们将在前端应用程序上发布消息,并希望在上面接收消息。编辑任何消息也是如此:所有参与者都需要一种方式来编辑他们自己的消息,同时也需要接收关于其他人编辑的任何消息的更新。

当使用像Ably这样的pub/sub消息服务时,一个常见的架构设置是在客户端也订阅的频道上发布更新。虽然这对普通的聊天信息或任何其他事件触发器来说效果很好,但要编辑以前发布的信息或触发关于以前信息的变化的更新就比较复杂了,因为Ably信息本质上是不可变的。

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

在当前的聊天应用程序中,我们将利用数据库将所有发布的消息直接存储在一个表中。我们也会有一个监听器,可以

i)观察我们数据库的聊天数据表中的insertupdatedelete 的变化,并且

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

如果我们让我们的前端客户端订阅这个监听器发布数据库更新的通道,我们不仅会收到作为数据库中insert 操作结果的新消息,而且还会收到由数据库上的update 操作导致的对以前消息的更新。每条Ably消息都有一个由Ably分配的唯一的msgId ,所以我们可以利用这个来唯一地识别表中的每条消息。数据库将是应用程序中唯一的真理来源,如果我们想在聊天中加载以前的消息,比如在Aply-Airtable启动套件的例子中,数据库也很有用。

在继续之前,再看一下上面的架构图,把所有的步骤放在一起,并把它们联系起来。

技术栈

我们对可编辑的聊天应用程序有四个主要目标。

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

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

Database-driven realtime architectures: building a serverless and editable chat app - Part 1

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

用于前端网络开发的NuxtJS

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

在我们的聊天应用中,它在将状态管理完全从视觉组件中分离出来方面非常有用,所以所有技术栈的开发者都能理解聊天应用和外部服务(在这种情况下主要是Ably)之间的通信和数据交换。

你可以用任何其他的前端Web框架、vanilla JS或甚至使用本地移动编程语言来取代Nuxt,这取决于你的应用程序的需求和愿望。

Ably启用pub/sub模式

Ably是一个作为服务的实时消息传递基础设施。它允许你只用几行代码就可以在你的应用程序中启用基于发布/订阅的消息传递。Ably提供高度可靠的低延迟消息传递,并能在任何平台或设备上全球工作。它完全抽象化了在地球上多个地区扩展实时通信的复杂问题,因此开发人员可以专注于他们的应用逻辑。

Database-driven realtime architectures: building a serverless and editable chat app - Part 1 hbspt.cta.load(6939709, '85f436af-7315-44c9-aa12-d764f40b294d', {"useNewLoader":"true","region":"na1"});

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

我们使用PostgresDB来存储聊天应用程序的消息。一般来说,任何改变表数据的数据库事务都不应该直接从前端完成,以避免潜在的安全风险。因此,我们将利用AWS Lambda函数,代表用户对数据库进行更改。鉴于我们的目标是使这个应用程序完全无服务器,Lambda函数正好符合这个主题。

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

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

Postgres并不附带主机,我们需要利用另一个服务来托管数据库。同样,考虑到要保持一切无服务器,我为Postgres使用了AWS RDS。使用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提供了一个无服务器平台来部署网络应用。它还允许设置基于git的工作流程,以自动构建和部署静态网站的新版本,因为存储库有变化。Nuxt应用程序是使用Netlify部署的。

Netlify的功能是启用一个令牌认证端点,用Ably进行认证

Netlify的无服务器平台也提供了无服务器的功能,这些功能可以被调用来执行一项功能。Ably服务要求客户以两种方式之一进行认证:基本认证或令牌认证。基本认证在前端脚本中直接暴露了API Key,因此不应该在生产中使用。你几乎应该总是选择令牌认证。为了启用这一点,我们需要设置一个认证端点,它可以验证前端客户端的凭证,并发出Aply Token请求。然后,前端客户端可以使用这个Ably Token Request来验证Ably并使用其服务。

鉴于我们使用Netlify来托管聊天应用程序,我们自然要利用Netlify的功能来托管我们的认证端点。尽管AWS Lambda已经是技术栈的一部分,但在我们的用户可以访问AWS Lambda之前,它需要我们为他们设置一个IAM。而Netlify则让它变得非常简单。

Ably Postgres连接器--一个关键的依赖因素

在继续讨论聊天应用程序的细节之前,让我们先了解使这种架构成为可能的Ably Postgres连接器的工作。

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

该连接器接受一个配置文件,在该文件中你可以输入数据库的连接细节,以及你想监听的数据变化的表。它还接受一个Ably API密钥,以便在指定的表发生变化后,能够实例化并向你的Ably应用发布消息。

使用配置文件,连接器在你的数据库中创建一个特殊的表,称为 "ablycontroltable"。这个表是用来维护Ably通道映射,以应对你数据库中的表的不同变化。

接下来,连接器创建一个程序,使用pg_notify 函数来监听指定表的变化。这个通知函数然后在相关的Ably通道上发布变化数据捕获(CDC)的有效载荷,如配置中指定的那样。

Database-driven realtime architectures: building a serverless and editable chat app - Part 1

Ably Postgres连接器是一个关键的依赖,它使可编辑的聊天应用程序成为可能。


通过这些,我希望你能更好地理解无服务器可编辑聊天应用程序的高层架构。

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

以下是我们在下一部分中会看到的一些东西。

  • 导航Nuxt应用程序(即使你不是Nuxt开发者)
  • VueX状态管理
  • Postgres数据库设置
  • 在Ably Integrations仪表板上设置Lambda函数
  • Ably Postgres连接器的设置
  • 部署所有的组件

敬请关注下一篇文章,请关注本空间。同时,请查看可编辑的聊天应用程序的演示,或深入到GitHub repo中

如果您有任何问题,请随时与我联系。

资源