RDC如何打造支撑百万用户的分布式代码托管平台

一、背景介绍

毋庸置疑,代码是DevOps流程的起点,是所有研发流程的基础;代码托管为代码“保驾护航”,确保代码的安全性、可用性,同时提供围绕代码的一些基础服务,如MR、Issues等等。

阿里巴巴集团GitLab是基于GitLab社区版8.3版本开发,目前支撑全集团数万规模的研发团队,累计创建数十万项目,日请求量千万级别,存储TB级别,早已超过了GitLab社区版承诺的单机上限能力,且增长速度迅猛。

面对这种情况,顺理成章的做法就是——扩容。然而非常不幸,GitLab的设计没有遵守Heroku推崇的“The Twelve-Factor App”的第四条:“把后端服务当作附加资源”(即对应用程序而言,不管是数据库、消息队列还是缓存等,都应该是附加资源,通过一个url或是其他存储在配置中的服务定位来获取数据;部署应可以按需加载或卸载资源),具体体现是:

  • Git仓库数据存储于服务器本地的文件系统之上
  • GitLab所依赖的三个重要组件:libgit2、git、grit也都是直接操作在文件系统上GitLab

所以GitLab社区版是基于“单机”模式设计,当存储容量和单机负载出现瓶颈时,难以扩容!

二、面对挑战

2015年初,阿里巴巴集团GitLab的单机负载开始呈现居高不下的情况,当时的应对方案是同步所有仓库信息到多台机器,将请求合理分配到几台机器上面从而降低单机的负载。然而这个方法治标不治本:

  • 系统运行过程中的数据同步消耗资源和时间,不可能无限制扩充机器
  • 这种方案暂时缓解了单机负载的问题,但对于单机存储上限的问题束手无策

2015年中,团队正式启动了第一次改造尝试,当时的思路是去掉对本地文件系统的依赖,使用网络共享存储,具体思考和方案可以参见RailsConf 2016 - 我们如何为三万人的公司横向伸缩 GitLab

然而由于本地缓存等问题的限制,网络共享存储的方案在性能上出现较明显性能问题,且大都为基于C/C++的底层改动,改造成本出现不收敛情况。而当时集团GitLab服务器在高峰期CPU屡屡突破95%甚至更高的警戒值,而高负载也导致了错误请求占比居高不下,无论是对上游应用的稳定性还是对用户体验都提出了严峻挑战。

2016年8月起新一轮改造开始。

三、改造方案

既然共享存储的方案暂时行不通(后续如果网络存储的读写性能有质的提升,未尝不是好的方式),首先明确了唯有分布式或者切片才能解决问题的基本思路。
我们注意到,GitLab一个仓库的特征性名称是"namespace_path/repo_path",而且几乎每个请求的URL中都包含着个部分(或者包含ID信息)。那么我们可以通过这个名称作分片的依据,将不同名称的仓库路由到不同的机器上面,同时将对于该仓库的相关请求也路由到对应机器上,这样服务就可以做到水平扩展。

下面通过一幅图介绍一下目前集团GitLab在单个机房内的架构。

3.1 各个组件的功能主要是:

  1. Sharding-Proxy-Api用于记录仓库与目标机器之间的对应关系,可以看作切片的大脑
  2. Proxy负责对请求做统一处理,通过Sharding-Proxy-Api获取信息,从而将请求路由到正确的目标机器
  3. Git Cluster由多组节点构成,每组节点内有三台机器,分别为master,mirror和backup。其中master主要负责处理写(POST/PUT/DELETE)请求,mirror主要负责读(GET)请求,backup作为该节点内的热备机器

说明

  • master在处理完写请求后,会同步更新此次变更到mirror和backup机器,以确保读请求的正确性和热备机器的数据准确
  • 之所以没有采用双master的模式,是不想造成在脏数据情况下,由于双向同步而造成的相互覆盖

3.2 保证方案可用

  • 如何确保切片信息准确
    Sharding-Proxy-Api基于martini架构开发,实时接收来自GitLab的通知以动态更新仓库信息,确保在namespace或project增删改,以及namespace_path变更、仓库transfer等情况下数据的准确性。
    备注:这样的场景下,等于每次请求多了一次甚至多次与Sharding-Proxy-Api的交互,最初我们曾担心会影响性能。事实上,由于逻辑较为简单以及golang在高并发下的出色表现,目前Sharding-Proxy-Api的rt大约在5ms以内。
  • 如何做到切片合理性
    海量数据的情况下,完全可以根据namespace_path的首字母等作为切片依据进行哈希,然而由于某些名称的特殊性,导致存在热点库的情况(即某些namespace存储量巨大或者相应请求量巨大),为此我们为存储量和请求量分配相应的权重,根据加权后的结果进行了分片。目前来看,三个节点在负载和存储资源占用等方面都比较均衡。
  • 如何处理需要跨切片的请求
    GitLab除了对单namespace及project的操作外,还有很多跨namespace及project的操作,比如transfer project,fork project以及跨project的merge request等,而我们无法保证这些操作所需的namespace或project信息都存储在同一台机器上。
    为此,我们修改了这些场景下的GitLab代码,当请求落到一台机器同时需要另一台机器上的某个namespace或project信息时,采用ssh或者http请求的方式来获取这些信息。

    最终的目标是采用rpc调用的方式来满足这些场景,目前已经在逐步开展。

3.3 提升性能

  • ssh协议的替换

    目前阿里巴巴集团GitLab提供ssh协议和http协议两种方式,供用户对代码库进行fetch和push操作。其中,原生的ssh协议是基于操作系统的sshd服务实现,在GitLab高并发ssh请求的场景下,出现了诸如这样的bug:

    由此产生的问题是:

    • ssh协议登陆服务器变慢
    • 用户通过ssh协议fetch和push代码时速度变慢

    为此,我们采用golang重写了基于ssh协议的代码数据传输功能,分别部署在proxy机器以及各组节点的GitLab服务器上。由此带来的好处有:

    • 机器负载明显降低
    • 消除上述bug
    • 在ssh服务发生问题的情况下,仍旧可以通过ssh登陆(使用原生)服务器,以及重启sshd服务不会对服务器本身造成影响

    下图是proxy机器采用新sshd服务后的cpu使用情况:

  • 个别请求的优化和重写

    对于一些请求量较大的请求,例如鉴权、通过ssh key获取用户信息等接口,我们目前是通过文本转md5,加索引等方式进行性能优化,后期我们希望通过golang或java进行重写。

3.4 确保数据安全

  • 一主多备

    如上面提到的,目前阿里集团GitLab的每组分片节点包含有三台机器,也就是相对应的仓库数据一备三,即使某一台甚至两台机器发生磁盘不可恢复的故障,我们仍旧有办法找回数据。

  • 跨机房备份

    刚刚过去的三月份,我们完成了阿里巴巴集团GitLab的跨机房切换演习,模拟机房故障时的应对策略。演习过程顺利,在故障发生1min内接到报警,人工干预(DNS切换)后5min内完成机房间流量切换。

    多机房容灾的架构如下图所示:

    保证准实时的仓库数据同步是机房切换的基础,我们的思路按照实际需求,由容灾机房机器主动发起数据同步流程,基本步骤是:

    • 利用GitLab的system hook,在所有变更仓库信息的情景下发出消息(包含事件类型及时间包含数据等)
    • 同机房内部署有hook接收服务,在接收到hook请求后对数据进行格式化处理,并向阿里云MNS(Message Notify Service)的相关主题发送消息
    • 容灾机房内,部署有消息消费服务,会订阅相关的MNS主题以实时获取online机房发送到主题内的消息,获取消息后调用部署在容灾机房GitLab节点机上的rpc服务,主动发起并实现数据同步的逻辑

    hook接收、消息消费以及GitLab节点机上的rpc服务,均由golang实现。其中rpc服务基于grpc-go,采用protobuf来序列化数据。

    通过一段时间的运行和演习,已经确定了方案切实可行,在数据校验相关监控的配合下,容灾机房可以准实时同步到online机房的数据,且确保99.9%至99.99%的数据一致性。

3.5 如何提升系统的可用性

  • 日志巡检
    面对集团GitLab每天产生的大量日志,我们使用阿里自研的监控工具进行日志监控,对系统产生的5xx请求进行采集和报警,然后定期去排查其中比较集中的错误。经过一段时间的排查和处理,5xx错误日志大致可以分为:

    • 分布式改造带来的跨分片操作的bug
    • GitLab本身的bug
    • 高并发情况下带来的系统偶发性故障
    • 数据库相关的错误等

    由于用户量大,场景多,阿里巴巴集团GitLab的使用场景基本覆盖GitLab的所有功能,因此也可以暴露出一些GitLab自有的bug。如Fix bug when system hook for create deploy key(从此,咱也是给GitLab供献过代码的人了)。

  • 服务器监控

    无论系统多少健壮,完备的监控是确保系统平稳运行的基础,既可以防患于未然,也可以在问题出现时及早发现,并尽可能减小对用户的影响。目前阿里巴巴集团GitLab的监控主要有:

    • 机器cpu,内存、负载等基本指标的监控
    • ssh、ping等网络检测信息(用于判断是否宕机,后将详述)
    • 服务器各个端口的健康检查(80,90xx,70xx等等)
    • 异步消息队列长度的监控
    • 数据库连接的检查
    • 错误请求的监控
    • Sharding-Proxy-Api与GitLab的数据一致性校验

    很自豪的一点是,我们经常可以根据报警信息,先于用户发现问题。

  • 单机故障的自动切换

    虽然监控足够完备,但谁也不能保证服务器永远不宕机,因此我们在同一组节点中保有一台backup机器以应对服务器故障。会有专门的client定期通过API轮询监控平台提供的机器监控信息,当确认机器宕机时(ssh和ping同时不通,且持续时间超过2min)自动触发机器角色的互换,包括master与backup互换,mirror与backup互换等。通过演习,我们已经具备了单机故障时5min内全自动实现机器切换的能力。

  • 机房故障时的切换

    即前述的跨机房切换。

3.6 单元化部署

单元化架构是从并行计算领域发展而来。在分布式服务设计领域,一个单元(Cell)就是满足某个分区所有业务操作的自包含的安装。而一个分区(Shard),则是整体数据集的一个子集,如果你用尾号来划分用户,那同样尾号的那部分用户就可以认为是一个分区。单元化就是将一个服务设计改造让其符合单元特征的过程。

为了实现单元化的目标,我们在最初设计时就往这方面考虑。比如跨机房备份中,消息消费应用需要调用Sharding-Proxy-Api获取rpc服务的地址时,尽可能做到数据在单机房内闭环。这样在满足单元化要求的同时,也可以在机房故障时,尽量不影响已进入队列的消息在消费时出现数据断流。

现在阿里巴巴集团GitLab在架构上已经基本具备了单元化部署的能力,这样的情况下,无论是后续与阿里云合作对外提供服务,还是当收购海外公司需要单独搭建新服务时,都不会遇到问题。

四、未来的改进

4.1 偶发的cache大量释放

由于GitLab有大量的IO操作,使得系统占用cache的数值巨大,也正是因为cache,系统的性能得到保证。然而成也cache败也cache,为了确保系统不会发生OOM,我们设定了vm.min_free_kbytes,当cache占用过多且需要继续申请大片内存时,会触发cache的释放,势必会影响释放瞬间请求处理能力(通过日志分析得到,此瞬间的处理能力仅为cache存在时的1/2左右),直接后果是该瞬间的请求堵塞,甚至出现部分502。

为此我们咨询了系统部的同学,根据他们的建议修改了部分内核参数(目前仍没有根治),后续会尝试升级内核的方式,也希望遇到过类似问题或对这方面问题有研究的同学,把你的秘籍传给我们。

4.2 自动化运维

目前集团GitLab的发布主要靠手,在分布式架构下,机器势必越来越多,全自动化的发布、扩容机制,是我们需要完善的地方。

4.3 rpc方案的最终落地

如前所述,只有最终实现了全局的rpc替换,才能将web服务所消耗的资源与Git本身消耗的资源进行分离,阿里巴巴集团GitLab的分布式改造才能算最终结束。

五、结语

监控及日志数据对比显示,过去一年中阿里巴巴集团GitLab请求量增长4倍,项目数增长130%,用户数增长56%,在这样的增速下,系统调用的正确率却从99.5%提升到了99.99%以上,这些数字印证了我们方案的可行性和可用性。

接下来的时间里,小伙伴们会为继续代码服务的创新而努力。“高扩展、分布式、响应式、大文件、按需下载、流控、安全、数据化、单元化”,有些我们做到了,有些是接下来努力的方向。

很自豪,今天的我们终于可以有底气地承诺:现在阿里巴巴集团GitLab的架构,已经足够支撑百万规模的用户体量,在满足集团业务发展的前提下,会逐步会通过刚刚上线的研发协同RDC为更多云上开发者提供服务,共同打造云上的协同研发生态!

时间: 2024-12-10 05:58:13

RDC如何打造支撑百万用户的分布式代码托管平台的相关文章

打造支撑百万用户的分布式代码托管平台

在2017在线技术峰会--首届阿里巴巴研发效能嘉年华上,来自研发效能事业部的杨再新分享了<打造支撑百万用户的分布式代码托管平台>.他主要介绍了GIT和SVN思想差异.开源的代码托管平台的挑战.云代码托管平台的架构设计以及云代码托管后续发展.其中,他主要分享了云代码托管平台的设计思路,稳定性.安全性的构建.   以下内容根据直播视频整理而成. 直播视频:https://yq.aliyun.com/edu/lesson/548 PDF下载:https://yq.aliyun.com/attachm

如何打造支撑百万用户的分布式代码托管平台

本文整理自2017云栖大会-上海峰会中阿里云高级技术专家杨再新的分享讲义,讲义主要介绍了开源代码托管平台的挑战,以及云代码托管平台的架构设计与产品规划.

R 语言联盟将打造自家的代码托管平台 R-Hub

R 语言联盟( R Consortium )将打造一个新的代码托管平台 "R-Hub",用于 R 语言的开发和分发软件包,这项计划得到 Linux 基金会的资助. R 语言是十分受欢迎的统计学编程语言.而 R 语言联盟是 Linux 基金会的协作项目之一,宗旨是为 R 社区.R 基金会.团体以及个人使用.维护和分发 R 软件提供帮助,微软.谷歌.甲骨文等科技巨头都是其会员. R-Hub 平台将向 R 软件包提供开发.构建.测试和验证服务.R 语言的开发者在早 2015年7月就已发出建立

打造支撑海量用户高性能server的内存管理

以此系列文章纪念因 QQ 空间.QQ 农场等http://www.aliyun.com/zixun/aggregation/4580.html">互联网业务爆炸式增长,而日夜 不眠地为公共组件做架构调整.性能优化的激情岁月. 以 QQ 农场.好友买卖为代表的 SNS 网页游戏的突然兴起,全国男女老少一 起日夜不眠的在电脑面前奋战,鼠标.键盘还有各路外挂汇成的请求像洪水一般 涌来.当流量把机房核心交换机冲得七零八落,当我们把市场上的服务器全部买 光都不够时,我终于懂了,这就是 TMD 的所谓

唱吧流量秘笈:如何日进百万用户

唱吧获取第一个百万用户,只花了10天时间,曾经一天就进账一百万用户,它是怎么做到的?陈华简介2005年创办酷讯网,获得联创策源与SIG基金两轮共计1200万美元投资.2009年4月加盟阿里巴巴,从事搜索引擎技术应用的研究.2011年7月创办最淘网.2012年初创办唱吧,迅速蹿红提要:唱吧怎么做微博营销?利用明星用户.明星用户分享到微博之后,唱吧再去放大影响力,就是再去找一堆大账号去转发他的微博.也可以靠普通账号做推广.但不要去传播本身就没有传播能力的东西,一定是你的产品已经在微博上形成某个爆点,

阿里专家倪超:支撑海量用户的阿里中间件技术

大流量高并发互联网应用实践在线峰会官网:https://yq.aliyun.com/activity/112 峰会统一报名链接:http://yq.aliyun.com/webinar/join/49 议题名称:<支撑海量用户的阿里中间件技术> 议题简介:伴随着互联网和移动互联网的盛行,海量的用户一次又一次的洗礼了各个机构的IT系统,而在阿里,这种改变无疑更加频繁与剧烈--这些年下来,中间件技术完成了从1.0到3.0时代的蜕变,并已经完成了将技术变成商业化产品,与业界分享.本议题将围绕这一变革

百万用户上不了“博客大巴”

本报讯 (记者彭科峰 实习记者吕晓勋)从1月5日开始,拥有百万用户的知名博客网站--"博客大巴"(www.blogbus.com)无法登录,这引来众多 网友的不满.昨天,"博客大巴"域名提供商表示,近日接到上级主管部门的通知,要求停止解析该网站域名,恢复时间未定. "博客大巴"网站是国内一家知名的提供博 客服务的网站,拥有百万用户.据网友介绍,1月5日上午,"博客大巴"出现了"博客大巴"首页无法访问.用户后

Draw Something一个月内流失五百万用户

显然没有开发者希望看到自己的应用在短短30天内就流失了五百万日常用户,而这正是OMGPOP(现已被Zynga收购)所处的窘境.Draw Something在iOS和 Android平台发布后就立即成为最火爆的应用之一,在极短的时间内获得了惊人的下载量.据App Data的调查,目前Draw Something的用户正在下降.在其高峰时期曾经拥有一千五百万用户,但是就在短短30天内就流失了五百万,失去了其三分之一的用户数量.App Data的调查数据来自通过这款游戏登陆Facebook的用户数量,

用友旗下畅捷通软件百万用户诞生

2011年5月10日, 作为中国中小型企业信息化服务领域的龙头品牌,用友旗下畅捷通软件有限公司(以下简称"畅捷通")以百万用户的诞生庆典完成了自己的历史性跨越:并同时举办了精英伙伴俱乐部成立挂牌仪式,携手来自全国的渠道合作伙伴精英,共同吹响4000万中国中小企业信息化新进程的号角.工信部推进司及中小司.中国软件协会相关领导和来自全国的畅捷通渠道合作伙伴用户代表共同见证了畅捷通第100万家用户的诞生. 亚洲地区的中小型企业如恒河星数,在中国就有至少4000万家,在国家的积极扶持下,中小企