阿里、蚂蚁、晟腾、中科加禾精彩分享 AI 基础设施洞见,现购票可享受 9 折优惠 |AICon 了解详情
写点什么

真正的持续集成:分布式代码仓库和依赖

  • 2017-05-08
  • 本文字数:2204 字

    阅读完需:约 7 分钟

微服务架构为软件开发带来了极大的灵活性,并加快了交付速度,但同时也带来了依赖管理问题。传统的解决方案虽然能够解决依赖管理问题,但都太极端,顾此失彼。于是,Netflix 尝试着寻找自己的解决方案,期待着在整个组织层面做到真正的持续集成。本文内容来自 Netflix 技术博客,已获得翻译授权,查看英文原文 Towards true continuous integration:distributed repositories and dependencies

在过去的 8 年间,Netflix 基于 AWS 构建了一套健壮的微服务架构,我们因此学会了如何在 AWS 上构建可靠的高性能服务。我们的微服务架构解耦了工程团队,让他们可以自由地构建、测试和部署他们的服务。这种灵活性最大化了团队的交付速度。在 Netflix,交付速度和可靠性是设计解决方案时首要的考虑点。

基于我们的架构,微服务为它们的消费者提供了一个客户端软件包,用于处理所有的 IPC(进程间通信)逻辑。这同时为服务的提供者和消费者带来了很多好处。除了客户端,微服务的很大部分是基于我们的运行时平台而构建的,这个平台由内部的软件包和第三方开源的软件包组成。

尽管服务开发团队有很大的发布灵活性,但他们的交付速度却受到了依赖软件包的影响。一项新增的产品特性可能要求很多微服务都用上最新版本的共享软件包或客户端,而更新依赖版本可能会带来风险。

简而言之,依赖管理是一项艰巨的任务。

更新项目的依赖可能带来潜在的问题。

  • 具有阻断性的 API 变更。这是最典型的场景,一个编译错误导致整个构建失败。由依赖锁定( Dependency Locking )和动态版本选择器组成的语义版本控制( Semantic Versioning )可以帮助大部分团队避免发生这种错误。不过,锁定在一个主版本上会让整个公司的代码升级变得很困难,导致配置漂移(Configuration Drift),并且需要长期地维护旧软件包。
  • 具有传递性的依赖更新。因为 JVM 的类路径是扁平结构,所以在一个应用程序里,一个类只能存在一个版本。像 Gradle Maven 这类工具可以处理版本冲突,避免同一个软件包的多个版本被引入到项目当中。这也意味着,你的应用程序里有一些代码依赖了具有传递性特征的软件包,但你的代码并没有针对它们进行过测试。
  • 具有阻断性的功能变更。理想情况下,这个问题可以通过执行适当的测试来缓解。软件包的所有者可以通过运行使用者的测试案例来了解他们对软件包功能的预期。

我们发现,为了解决大规模的依赖管理问题,很多公司使用了两种方案:共享最小化(Share Little)和单体仓库( MonoRepo )。

  • 共享最小化(或者干脆不使用共享软件包)最近在微服务领域很流行,它的核心论调是说,微服务之间不应该共享代码,服务之间只能通过 HTTP API 进行耦合。更有甚者,有人说直接使用拷贝加黏贴的方式来代替共享软件包。这是一种非常极端的解耦手段。
  • 单体仓库的核心论调是说,组织的所有代码应该全部保存在一个单独的仓库里。任何一个代码变更在提交到 HEAD 之前,都需要针对整个代码仓库进行编译和测试。内部软件包没有所谓的版本,只有 HEAD 代码。所有的提交在到达 HEAD 之前需要跨过一些门槛。第三方软件包需要通过“审批”才能被使用,而且仅限于一两个版本。

这两种方式都能解决大规模的依赖管理问题,不过它们也带来了一些挑战。共享最小化促进了解耦,也加快了工程速度,但牺牲了代码的重用性和一致性。单体仓库保证了代码一致性,并降低了风险,但牺牲了灵活性。不管采用哪一种方式,我们都需要对 Netflix 的开发基础设施和运行时架构做出重大的调整。况且,这两种方案会破坏我们所推崇的自由和责任文化

我们给自己提出了一个很大的挑战目标:

我们能否为 Netflix 的工程师们提供一种解决方案,它不但具有单体仓库的优势,还能保持分布式仓库的灵活性?

我们以单体仓库为蓝本,另辟蹊径,希望找出能够达到相同目的的可替代方案。单体仓库所要解决的核心问题是什么?我们能否在传统的二元集成世界里开发出一种新的方案?

我们的解决方案,虽然还在试验阶段,不过可以从中归纳出三个关键的特性。

  • 向发布者反馈。直接或间接地向共享代码所有者快速地反馈使用者所遇到的问题。同时,允许团队因下游依赖的中断而暂停发布。目前,我们不会把这类问题的责任归咎到使用者身上。通过向软件包所有者反馈他们的问题给 Netflix 带来的影响,希望他们能够负起应有的责任。
  • 来源管理。当有新版本发布时,为使用者提供一种安全的方式,用于自动增加软件包的版本。既然我们已经针对所有的下游依赖测试过每一个软件包,那为什么不直接让使用者知道新版本,从而加快新版本的采用速度呢!
  • 分布式重构。为共享代码的所有者提供一种方式,让他们可以全局地对 API 的使用者进行快速的重构。我们已经开始向使用了某些特定 Java API 的 Git 代码仓库发起了全面的拉取请求。我们已经做了一些试验,并希望在这方面有更多的投入。

我们的旅程才刚刚开始。我们的发布者反馈服务目前正处于 alpha 测试阶段,我们计划后续会大规模采用这个服务,紧接着会进行来源管理。我们的分布式重构试验让我们了解到进行快速的全局重构是多么的重要。我们也看到了通过我们所构建的工具来降低依赖图复杂度的可能性。我们相信,通过扩展和培养这种能力,我们的 Netflix 团队将会在组织层面做到真正的持续集成,并减少(甚至免去)依赖管理的痛苦。


感谢郭蕾对本文的审校。

给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ @丁晓昀),微信(微信号: InfoQChina )关注我们。

2017-05-08 19:002302

评论

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

Zadig + Gitee:完美实现微服务架构持续交付

Zadig

DevOps 云原生 CI/CD 软件交付

九、高可用之弹性伸缩

穿过生命散发芬芳

5月月更 高可用设计

整理了100个必备的Python函数,建议收藏

伤心的辣条

Python 程序人生 软件测试 软件自动化测试 测试 单元测试

linux之history命令

入门小站

Linux

适合喜欢快速wiki和md的 vuepress

kcnf

看了它!你也能轻松部署vue3组件库

Jianmu

前端 持续集成 Vue 3 组件库 建木CI

Java 项目编译的时候提示 javax.xml.bind.annotation does not exist 错误

HoneyMoose

PHP基础语法1

乌龟哥哥

5月月更

快速删除 node_modules

HoneyMoose

浅谈前端和后端的区别

工程师日月

5月月更

八卦信息怎样传到吃瓜群众?这是一条正儿八经的技术科普

融云 RongCloud

HTML的iframe使用

恒山其若陋兮

5月月更

使用APICloud AVM框架封装通讯录组件

YonBuilder低代码开发平台

APP开发 APICloud avm.js 通讯录

针对自动取款机优化需求的用例设计,应该挺全面了吧

伤心的辣条

Python 程序人生 软件测试 软件自动化测试 软件测试工程师

计算机二级备考

工程师日月

5月月更

CMMI3级(低成熟度)与5级(高成熟度)到底有什么不同?

高山

CMMI CMMI高成熟度

深入了解 Flutter 的状态管理机制(上)

岛上码农

flutter ios开发 安卓开发 跨平台应用 5月月更

时不我待,TSDB崛起正当时

CnosDB

IoT 时序数据库 开源社区 CnosDB infra

在线提取Sitemap中的URL工具

入门小站

工具

这 BUG,绝了

AlwaysBeta

程序员

【愚公系列】2022年05月 二十三种设计模式(九)-装饰者模式(Decorator Pattern)

愚公搬代码

5月月更

Hoo研究院|区块链简报:以太坊创始人V神呼吁马斯克支持“非侵入式”抗新冠技术

区块链前沿News

区块链 Hoo

Go语言入门很简单:如何在 Go 语言中使用 MySQL

宇宙之一粟

Go 语言 MySQL 数据库 5月月更

什么是数据资产?

奔向架构师

数据资产 5月月更

《法医奇遇记系列》——爱情是WebSocket的坟墓

法医

前端 websocket

Hadoop Java api操作hdfs(二)

Emperor_LawD

hadoop 5月月更

天翼云十年一诺,以普惠算力拥抱万里山河

脑极体

测试人面试 常被问到的计算机网络题,高薪回答模板来了!

伤心的辣条

Python 程序人生 测试 自动化测试 测试 单元测试

在线TSV转SQL工具

入门小站

工具

如何挑选文档协作工具

小炮

文档协作

中原银行流量削峰平台

中原银行

高并发 流量 中原银行 削峰

真正的持续集成:分布式代码仓库和依赖_DevOps & 平台工程_Netflix_InfoQ精选文章