资料内容:
1. 引言
Code 是美团自研的代码托管平台,其中包括了代码版本管理、分支管理及代码评审等
功能,协同众多研发流程工具平台,支撑内部所有工程师的日常研发工作。经过近 3 年
的建设,目前 Code 托管了数以万计的仓库,日常处理千万级的 Git 相关请求,稳定支
撑着美团研发流程规范的持续落地。本文主要介绍美团在建设代码托管平台过程中面临
的一些挑战和实践经验。
2. 美团代码托管平台建设之路
2.1 代码托管平台的发展史
回顾美团代码托管平台的发展史,整个历程可以划分为三个阶段:单机部署、多机部署
以及自研分布式代码托管平台。
第一阶段:单机部署
美团最初的代码托管平台,和绝大多数 Web 系统一样,单机部署即可运行,所有用户
的请求均通过 Web 应用进行响应。由于 Git 使用基于文件组织形式的存储模式,无论
是通过页面访问还是执行 Git 命令操作,最终都会表现为磁盘的文件读写,高 IO 磁盘
尤为重要。
第二阶段:多机部署
在访问规模不大的情况下,第一阶段这种单机架构可以满足日常的开发需求。但随着研
发团队业务需求的不断增长,测试自动化流程的逐步完善,扩展性瓶颈也愈发明显,主
要表现为以下 2 个方面:
● 存储:由于公司资源限制和地域分配不均等因素,代码托管平台部署机器已配置
最大容量的可用 SSD 磁盘,使用率仍高达 80%,可用空间严重不足。
● 负载:随着研发人员的不断增多,在访问高峰期,CPU 和 IO 负载高达 95% 以
上,页面出现严重的卡顿,仅能通过限流保障系统的持续服务。
因而,单机部署无法再承载高峰期的访问量,系统扩容刻不容缓。于是,我们开始设计
了一套能够通过多机负载同一仓库 IO 的读写分离架构方案,以解决较为严重的 IO 负
载问题。在读写分离架构中,最重要的是要保证用户视角的数据一致性(用户随时可以
读取提交的最新代码),这里采取了以下措施:
1. 写操作仅发生在主节点。
2. 采用懒汉同步模式,在读取数据时触发从节点同步数据,若失败,则路由到主
节点。
3. 采用独主兜底模式,遇遇到突发情况时可以迅速禁用从节点,保障数据安全。
的解析代理模块进行读写分发操作后再下发到主从节点(此处采用了 Round-Bobin 的
算法分发读请求),使得读吞吐量整体扩大了 2 倍。对于从节点,我们部署了 Agent,
在用户发起读请求时会触发同步仓库数据的 Fetch 操作,以保证数据的一致性。
第三阶段:自研分布式代码托管平台
在第二阶段,虽然通过多机负载 IO 的读写分离架构短暂性地解决了扩展性瓶颈问题,
但仓库数据仍在持续不断地指数增长。同时,除扩展性问题之外,可用性瓶颈也凸显出
来,主要表现在以下 2 个方面:
● 运维:无论是日常迭代更新版本还是热修复紧急 Bug,都需要停服才能部署系
统,停服期间用户无法使用代码托管平台。
● 备份:系统采用冷备份的方式多副本存储 Git 数据,无法保证核心数据的实时恢
复,异常情况下存在数据丢失风险。因此,搭建具备高可用性和水平扩展性的分
布式架构迫在眉睫。我们调研了业界主流代码托管平台的分布式方案,并结合公
司内部的业务特性,最终选择了基于应用层分片的分布式架构,该架构满足了以
下 2 个特性:
● 高可用:采用三副本多活模式,规避代码丢失风险,且系统版本更新无需停服,
单机断电、宕机均可正常提供服务。
● 水平扩展:可通过扩容分片集群的方式进行存储和负载扩展,实现广义下的“无
限”容量。
综上所述,Code 基于 GitLab 生态开源组件二次开发,并采用了应用层分片多活模式
的分布式架构方案,简介如下:
1. 底层存储服务基于 GitLab 生态开源组件二次开发,有良好的生态和丰富的功能
支持。
2. 各服务间均通过 gRPC 进行交互通信,主要考虑点是 Git 大多数为二进制数据
通信,gRPC 基于 HTTP 2.0,有良好的传输性能和流式支持。
3. 通过路由模块实现逻辑层与存储层有效隔离,逻辑层对物理分片无感知,存储
层如同一个整体提供服务。
4. 采用了多活复制模式的数据保障架构,提高读写吞吐量,满足日均千万级的请
求量需求。
5. 针对于应用层分片的劣势,在架构设计时也做了相应的针对性优化,具体如下:
○ 热点库:提供了自动化的分片迁移能力,在发现仓库出现热点时,可进行分片迁移
达到分片均衡。
○ 跨分片数据交互:通过业务层的 Git 事务包装,我们使用共享 Object 的模式并确
保相互关联的仓库均落在同一分片上,既避免了跨分片通信的问题,也减少了磁盘
空间占用和访问时延。