打破微服务孤岛:使用 Dozer 构建实时一致的 API

作者:

Matteo —— Co-Founder @ Dozer;

Vivek —— Co-Founder @ Dozer

英文原文:https://getdozer.io/blog/microservices-unified-apis

作为开发人员,你肯定不会对从多个微服务中创建一致 API 的挑战感到陌生。但是有了 Dozer,你可以告别繁琐复杂的过程,迎来闪电般快速的结果。Dozer 使整个过程的每一步自动化,从构建数据 pipelines 到实时数据聚合、索引和极速查询。只需简单的配置,你就可以生成 gRPC 和 REST API,并与你的面向客户的产品进行集成。让我们一起体验下使用 Dozer 创建的实时 API 的速度和便捷性。

简介

微服务架构是一种软件设计方法,它着重于将大型的、单体的应用程序拆分为更小、更独立的服务,可以独立开发、部署和维护。然而,这种方法可能会引来新的挑战,例如要处理分布式系统的复杂性,确保数据的一致性和可靠性,以及处理故障。

解决这些挑战的一种方法是使用 Saga 模式,它提供了一种在微服务架构中管理分布式事务的方式。Saga 模式是一种设计模式,它协调多个服务来完成事务,即使出现故障也可以完成。

虽然 Saga 模式是管理分布式事务的强大工具,但当需要将来自多个服务的数据集成在一起创建一致的 API 时,它可能会引来额外的挑战。

所有的配置文件和数据库示例都可以在我们的 GitHub samples repo 中找到。

场景

首先,我们以一个航空公司的订票网站为例。整个应用程序分为两个主要的微服务:

• 一个预订微服务:处理所有的预订、机票和登机证件

• 一个航班主数据微服务:维护所有航班的主数据,包括航线、飞机等。

每个服务都维护自己的数据库:

BOOKINGS, TICKETS, TICKET_FLIGHTS表是预订微服务数据库的一部分

AIRPORTS, FLIGHTS是航班主数据微服务数据库的一部分。

下面是我们数据库的实体关系图:

为了改善用户体验,我们想要创建几个新的 APIs:

•Booking retrieval APIs: 提供特定旅客的预定详情

•Routes listing APIs: 提供所有可用路线清单

由于这些 APIs 面向客户,所以要求延迟可忽略,且能够支持高吞吐量。出于明显的原因,这不能通过每次查询 Postgres 数据库表来实现。我们可以考虑创建 materialized views,但这些视图必须在每次记录更新时刷新,这也是不可行的选项。

传统上,这些用例是通过引入一个中间缓存层(如 Redis)来解决的,但即使是这种情况,保持缓存始终更新并决定正确的逐出策略也不是轻松的事情。除此之外,我们还需要构建一个高效和可扩展的 API 层,最好使用像 gRPC 这样的协议。

总之,没有简单的解决方案,实现需要付出一些不易的努力。

Dozer能提供什么帮助

上述需求正是 Dozer 的完美应用场景。Dozer 是一款低代码开源平台,可以自动构建超快的 gRPC 和 REST 只读 APIs,始终保持数据更新,可与前端代码(如 React )集成。为了始终保持缓存层的更新,Dozer 依赖于 Postgres CDC,并实现了一个 SQL 流引擎,可用于在传输过程中预处理数据。

让我们深入了解每个 API 以及如何使用 Dozer 构建它们。以下是我们想要实现的 API 列表:

配置连接和数据源

首先,我们需要创建一个新的 dozer-config.yaml 文件。该文件有 4 个主要模块: connections, sources, sql and endpoints。让我们定义两个连接到我们的微服务数据库:

一旦连接被定义,我们需要明确指出我们将从哪些源表中获取数据:

上面只是一些示例的数据源定义。您可以点击这里参考完整的配置文件,以获取完整的列表。

配置和构建 endpoints

一旦定义了数据源,我们终于到了构建 API 过程中有意思的地方。Dozer 配置文件有一个 endpoints 模块,我们可以在其中定义 endpoints 列表。在我们的例子中,我们将有 3 个定义:

这就是定义新 API endpoints 所需的全部内容。现在你可能想知道 sources 和 endpoints 是如何相互连接的。让我们深入了解 endpoint 配置:每个 endpoint 的所有参数中,都有一个 table_name 属性,该属性定义了要缓存的实际数据源。它可以匹配源的 table_name 属性(如果我们想要在缓存中复制完整的源表),或者是一个 SQL 临时表的名称(下面会进行说明)。

使用SQL预处理数据

在我们的场景中,我们希望在将数据插入缓存之前对其进行预处理。为此,Dozer提供了一个 sql 模块,其中可以表达转换。所有的 SQL SELECT 语句都必须包含一个 INTO ,这将与一个 endpoint 的 table-name 属性相匹配。在我们的示例中,我们的 sql 模块如下所示:

SELECT 语句后面跟着一个 INTO ,其中的值与我们要构建的缓存名称相匹配。

这就是用 Dozer 创建低延迟的 REST 和 gRPC APIs 所需的全部内容。所有 APIs 都附带了预嵌入的授权层,以允许直接与前端应用程序集成。我们将在另一篇即将发布的文章中详细介绍此主题。

缓存同步

由于 Dozer 直接与 Postgres CDC 进行交互,因此无需特殊操作即可保持缓存的实时性。每当 Postgres 发生 UPDATE、 INSERT 或 DELETE 操作时,Dozer 会基于 SQL 查询会基于SQL查询自动预处理这些操作,并在几毫秒内自动将结果传播到缓存中。

Dozer 完全由 RUST 构建,以实现较低的查询延迟。

查询数据

使用 gRPC 或 REST 查询 Dozer 非常简单。gRPC endpoint 还支持反射,特别适用于 enforce schemas 和 discover services。例如,我们可以使用 grpcurl 命令行工具从 passenger_id检索所有预订的详细信息:

List Services

Query an Endpoint with filters

由于整个对象已经被预先计算并存储在低延迟的混合(内存+磁盘)缓存中,因此响应很即时。

底层实现

上面已经解释了如何轻松地开始使用 Dozer,接下来让我们深入了解 Dozer 的架构和幕后发生的事情。

为了实时处理数据,Dozer 将所有的dozer-config.yaml 查询转换成DAG(Directed Acyclic Graph)的形式。DAG 定义了查询的流式执行,其中每个节点都是一个 source、一个 processor 或一个 sink。比如,下面是给 BOOKING DETAILS 查询生成的 DAG:

可以注意到,我们有两个connectors( bookings_conn 和 flights_conn),每个都有多个 output ports,对应一个数据库表。所有的连接都进入一个product node,负责执行 join 操作,然后是一个projection node,它将执行 field selection。

一旦启动,Dozer就会连接到源数据库,有选择地获取数据库表并开始监听 CDC 事件。然后将这些事件注入 DAG。

每个节点本质上都是一个 processor,能够处理3种类型的操作: INSERT、 DELETE和 UPDATEs。每当接收到 CDC 消息时,每个 processor 都会更新其内部状态,并停止、传播或生成 新消息,并通知下游节点。这些事件流最终传播到缓存中,以便其状态始终与源保持同步。


如果你有兴趣更深入地了解 Dozer,可访问 GitHub

别忘了在 GitHub 点个 ⭐️ +分享哦!感谢支持~

也欢迎加入我们的 Discord 频道~

如想使用此示例,请访问 GitHub samples repo

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,504评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,434评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,089评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,378评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,472评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,506评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,519评论 3 413
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,292评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,738评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,022评论 2 329
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,194评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,873评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,536评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,162评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,413评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,075评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,080评论 2 352

推荐阅读更多精彩内容