写点什么

Agoda 的非常规客户端优先迁移:从 GraphQL 单体架构到微服务架构

作者:Eran Stiller

  • 2024-12-19
    北京
  • 本文字数:3184 字

    阅读完需:约 10 分钟

Agoda 的非常规客户端优先迁移:从 GraphQL 单体架构到微服务架构

Agoda 最近描述了它们从单体 GraphQL API 转向微服务架构的非常规方法。与侧重于优先拆解服务器端组件的传统方法不同,Agoda 采用了客户端优先的策略,使用一个内部智能编排器库来使其客户端应用程序准备好并行处理单体和微服务。


在服务器迁移之前,Agoda 优先考虑让客户端准备好处理单体和微服务,从而降低风险和所需的协调工作。Agoda 的助理开发经理 Numan Hanif 告诉 InfoQ:“这种方法最大限度地减少了中断,使我们的团队能够更好地控制整个堆栈,并使架构更好地与敏捷和现代开发原则保持一致。”


打破单体架构,拆分 GraphQL 单体架构 (来源)


内部智能编排器(Smart Orchestrator)是 Agoda 客户端优先迁移策略的关键组成部分,旨在在迁移期间将客户端应用程序与后端连接起来。它充当动态路由层,根据配置将请求定向到单体 GraphQL API 或新部署的 微服务。Agoda 的工程师更喜欢使用这种方法,而不是使用 Apollo Federation,后者与奈飞(Netflix)处理这种情况的方式相似。


发布与单体架构相同的接口允许客户端应用程序无需任何修改即可运行,从而减少了迁移过程中进行大量更改的需要。这种设置确保了客户端应用程序可以处理混合后端环境,为并行微服务开发奠定了基础。


智能编排器(Smart Orchestrator)根据配置路由客户端查询(来源)


除了路由之外,智能编排器(Smart Orchestrator)还自动管理模式更新和映射,支持迁移的增量特性。最初,所有模式都指向单体,但随着域的拆分,编排器更新了映射,将查询路由到正确的微服务上。


Agoda 以增量方式执行向微服务的迁移。每个新创建的微服务都经过了严格的单体测试,以验证数据的正确性,确保在转换客户端流量之前,两个系统的响应相匹配。此外,Agoda 还实施了一个准确性测试系统,在增量部署期间不断比较单体和微服务的输出,以进一步验证迁移。


Agoda 采用了一种自动化的数据驱动方法,在其 100 个应用程序 Git 存储库中分析和准备 GraphQL 查询,以确保在迁移过程中客户端准备就绪。使用生产数据,Agoda 根据域之间相互依赖的程度将查询分为简单、中等和复杂类型。


“拆解”跨域查询是 Agoda 迁移的关键一步。简单的查询不需要更改,而 Agoda 工程师将中等查询拆分为每个域单独的独立请求,并在客户端上合并结果。涉及紧密耦合嵌套域的复杂查询,当一个查询依赖于另一个查询的结果时,通常需要顺序执行,因此需要更广泛的重组。


“拆解”复杂查询(来源)


在拆分单体架构的同时,Agoda 专注于将现有代码原封不动地迁移到新的微服务中,从而导致了旧的技术问题转移到了新的微服务中。例如,Hanif 告诉 InfoQ,“Agoda 遇到了诸如缺少客户端速率限制等问题,这经常影响我们的运营。”他说,事后看来,“为了更好地实现这种平衡,我们应在迁移过程中实施重构实践,确保迁移后的架构更清洁、更高效。”


InfoQ 在采访 Hanif 的过程中,谈到了 Agoda 的微服务迁移、使用的方法以及吸取到的教训。

InfoQ:你能详细介绍一下你们决定从单体架构迁移到微服务架构的原因吗?哪些特定的增长指标或痛点是启动这一迁移的转折点?


Numan Hanif:供应商管理系统由一个由 7 人组成的专业工程团队管理,监督 70 多个通过 GraphQL、gRPC 和 REST 等多个接口交互的客户端服务。这个单体系统在处理重要流程方面至关重要,包括通过该单体系统进行预订确认。


在这个单体系统中,我们的平均变更交付周期(Agoda 使用的开发人员体验指标)环比增长了 12%,平均每月创建了 40 个合并请求(MR)。我们广泛的测试环境包括 9200 个单元和集成测试,这些测试大约需要一个小时才能运行完,并在计划运行中实现约 73% 的稳定性。


单体架构的设置还严重依赖于各种基础设施组件,并且难以管理不相关的域,从而导致了架构的复杂性。由于每季度积压 210 张操作票据和高昂的运维开销,以及知识孤岛和庞大的代码库,学习曲线很陡峭。


这些问题凸显了可扩展性解决方案的必要性,使得微服务成为增强该系统开发过程中的可管理性、可扩展性和敏捷性的理想选择。

InfoQ:你们是否遵循了任何特定的方法或框架来定义每个微服务的边界,比如领域驱动设计(DDD)或类似的实践?


Hanif:我们没有采用领域驱动设计(Domain-Driven Design,DDD)作为我们微服务边界的默认框架,而是根据我们的具体需求和 GraphQL API 的独特方面开发了一种定制方法。我们从自低而上的方法开始,分析数据库模式,并通过标记将表分类到特定的域中。这提供了一个与我们的数据管理模式相一致的基础结构,确保了识别服务边界的一致基础。


标记了表之后,我们将每个 GraphQL 端点与相应的表域对齐,以保持跨数据和服务边界的一致性。虽然 75% 的 GraphQL 端点域标记起来很简单,但剩下的 25% 却带来了挑战,因为它们涉及存储过程从多个域访问表的复杂模式。这种复杂性需要进一步的改进,以确保内聚的服务结构与我们的架构目标相一致。


我们的流程与 DDD 共享元素,例如将服务与业务功能对齐,但不同之处在于它是基于数据驱动、自底而上的方法。与自顶而下、领域专家主导的 DDD 方法不同,我们专注于现有的数据结构,并使用领域标记来解决 GraphQL 的独特挑战。这使我们能够创建连贯且功能一致的微服务,同时解决基础设施的操作复杂性。

InfoQ:是什么促使你们采用“客户端优先”的迁移方法?这一策略是否是基于以往的经验、理论优势或从以往项目中吸取的教训?Agoda 现有的架构或团队结构中是否存在任何特定的挑战,使这种方法特别适用?


Hanif:采用“客户端优先”的方法迁移到微服务的决定受到了理论和实践经验的影响。最初,我们考虑使用单体作为客户端通信的路由器,但这与我们实现真正的垂直(客户端数据库)所有权的目标相冲突。路由器最终将成为一个软单体,使长期架构变更变得复杂,并保持集中控制。这一见解强调了需要采取更分布式的策略。


过去采用服务器优先迁移方法的经验凸显了几个挑战,包括由于客户端迁移延迟而导致的迁移时间过长。这些瓶颈阻碍了我们完全停用单体架构的能力,并暂时推迟了微服务架构带来的好处。这些经验教训强调了首先让客户端做好准备的重要性,确保它们能够处理后端更改并促进无缝迁移的重要性。


客户端优先策略旨在通过允许后端开发与客户端准备活动同时进行来减少与外部团队的协调工作。这种方法最大限度地减少了中断,使我们的团队能够更好地控制整个堆栈,并使架构更好地与敏捷和现代开发原则保持一致。它还解决了诸如主动拼接查询、实现并行开发和减少依赖性之类的挑战,考虑到现有体系结构的复杂性,这一点尤其有益。

InfoQ:智能编排器(Smart Orchestrator)客户端库是内部构建的,还是你们根据需要调整了现有的工具?在创建和维护它的过程中,有哪些主要的挑战?对于处理 GraphQL 模式和路由的复杂性,你们是否发现了一些必要的特定特性?


Hanif:智能编排器(Smart Orchestrator)客户端库是内部开发的,用于解决现有解决方案无法满足的特定需求。这一决定允许使用定制工具,在不改变客户端接口的情况下,有效地管理跨微服务的模式更新和请求路由。自动模式映射更新等关键功能对于处理 GraphQL 的复杂性至关重要,可确保与现有客户端应用程序的无缝集成,同时可以避免嵌入式业务逻辑。


开发智能编排器(Smart Orchestrator)带来了挑战,每当迁移过程中出现问题时,都要用新的库版本更新多个存储库,这需要仔细的协调和测试。此外,在生产环境中启用 GraphQL 自检查询是至关重要的,但通常会由于安全和性能问题而受到限制。通过应对这些挑战,我们确保库始终是轻量级的,同时有效地支持跨域查询并适应我们的架构需求。

作者介绍


Eran Stiller 是澳大利亚墨尔本的首席软件架构师。作为一名经验丰富的软件架构师和首席技术官,Eran 设计、实施和审查了跨多个业务领域的各种软件解决方案。Eran 在软件开发领域拥有多年的经验,并有着丰富的公开演讲和社区贡献记录。


查看原文链接:

https://www.infoq.com/news/2024/11/agoda-graphql-microservices/

2024-12-19 08:0025701

评论

发布
暂无评论
发现更多内容

在线HTML转JSON工具

入门小站

工具

规模化软件开发的必由之路—大规模自动化测试

刘冉

自动化测试

记一次 JMeter 压测 HTTPS 性能问题

阿里巴巴云原生

阿里云 云原生 https Jmeter 压测

flask框架【入门学习笔记一】

恒山其若陋兮

5月月更

react-router原理分析

正经工程师

React React-Router

【C 语言】指针 Five 之 ["​⚔ 空指针 - NULL、💣 指针使用之前检查有效性、🗡 指针运算 💣 指针+- 整数、💣 指针 - 指针、指针关系运算、💣 标准规定、⚔ 指针和数组、⚔ 二级指针、⚔ 指针数组"]

謓泽

5月月更

Linux 入门及常见Shell命令

宇宙之一粟

Linux Shell 5月月更

架构学习(一)

爱晒太阳的大白

5月月更

Kubernetes 节点弹性扩展实践组件 Amazon Karpenter:部署 GPU 推理应用

亚马逊云科技 (Amazon Web Services)

Kubernetes 部署

如何透过 Serverless 与 API 的方式异步搜寻数据湖中的数据

亚马逊云科技 (Amazon Web Services)

Serverless 数据 API

C++最佳实践 | 1. 工具

俞凡

c++ 最佳实践

跨平台应用开发进阶(十一) :uni-app 实现IOS原生APP-云打包集成极光推送(JG-JPUSH)详细教程

No Silver Bullet

uni-app ios 5月月更 云打包 原生APP

跨平台应用开发进阶(十二) :uni-app 实现应用桌面图标角标提示及应用跳转

No Silver Bullet

uni-app 5月月更 桌面角标

从“数据”到“大数据”,激发数据潜力,深耕智能应用!

亚马逊云科技 (Amazon Web Services)

大数据 数据 智能开发

M_5: 设计微博系统中”微博评论“的高性能高可用计算架构。

Jadedev

架构训练营

架构实战营 - 第 6 期 模块六课后作业

天琪实刚亮

架构实战营

密码学系列之:使用openssl检测网站是否支持ocsp

程序那些事

Java 密码学 程序那些事 5月月更

提效客户体验管理:结合 K-Means 聚类和 RFM 模型的客户分群

龙国富

RFM 客户分群 K-Means

【刷题第16天】数组中出现次数超过一半的数字

白日梦

5月月更

数学建模学习资料

乌龟哥哥

5月月更

SAP OData V4 模型支持的一些数据绑定模式

汪子熙

JavaScript 前端开发 SAP ui5 5月月更

数据结构-复杂度计算经典案例

芒果酱

数据结构 算法 5月月更

LinkedList 源码分析-迭代器

zarmnosaj

5月月更

SpringMVC源码分析:POST请求中的文件处理

程序员欣宸

Java spring 5月月更

Linux环境编译静态库

Loken

音视频 5月月更

PostgreSQL出现死锁怎么办?

慕枫技术笔记

数据库 5月月更

[ CloudWeGo 社区动态 ] Kitex 电商项目案例

baiyutang

Go 微服务 5月月更

Amazon CodePipeline 与 GitHub 集成

亚马逊云科技 (Amazon Web Services)

GitHub Code

WordPress 编辑用户

海拥(haiyong.site)

WordPress 5月月更

1.1 历史长河中的顶层设计

凌晞

Artery —— 单页面应用接口描述语言简介

全象云低代码

前端 低代码 流程 页面 artery

Agoda 的非常规客户端优先迁移:从 GraphQL 单体架构到微服务架构_微服务_InfoQ精选文章