再看Monorepo

·

1 min read

What is Monorepo

由于谷歌在 Monorepo 上的实践,Monorepo 受到了越来越多的关注。Monorepo 意味着把所有项目的所有代码统一维护在一个单一的代码版本库中,和多代码库方案相比,两者各有优劣,需要根据公司文化和产品特性进行取舍

记得两年前还在某W司的时候,当时我设计了一套基于prometheus的监控平台,这套平台是微服务架构,当时作为微服务门徒的我跟同事在服务划分上产生了分歧:是一个repo一个服务,还是将不相关的两个服务放在一个repo里面?当然,我支持前者,那位同事支持后者,彼时我并没有说服对方,还觉着很沮丧,不过服务是由那位同事编写,我也没有过多地坚持自己的意见。记得当天我将这件事当作牢骚发在微博上,有一个朋友就留言道:这没什么啊,谷歌也是这么干的啊……我惊了,谷歌会这样?不相信也不接受,直到最近因为工作原因,开始接触bazel,好像发现了一个新天地……

我们的现状

我现在的工作是做一个公司的内部服务平台,依然使用我“熟悉”的微服务架构,我对“微”这个字保持着洁癖,以至于一年之后的现在,我负责的微服务多达10几个,由于是内部平台,流量小,清一色部署在k8s上,0.5G+0.5C的配置,短小而精悍,这期间我还开发了一个极简的golang服务脚手架,又引入了golib共享库,加入了对dubbo、gRPC的支持(虽然现在看没有必要)等等,还有metric、log、trace,持续给系统加菜,效果上看,对功能的支撑是没问题的,开发速度也还不错,只有我又发现了几个不大不小的问题

  • client sdk: 平台的微服务间使用http协议进行通信,我引入了swagger,新建了一个client repo, 专门存放通过swag自动生成的client sdk,问题在于,协同开发时,A服务依赖B服务, 所以B服务接口定义好后,生成sdk,更新到client repo,A服务才能继续进行开发,就有人A服务repo、B服务repo、client repo三个代码仓库,有时会出现不一致的情况,小团队人少问题也不是特别明显;
  • golib共享库:会放一些常规代码:日志处理、中间件、共用的数据定义等等,这个库主要我在维护,主要目的是减少重复代码
  • 代码风格:这是一个让我非常头疼的问题,由于一些历史原因,团队的代码格式化做的非常糟糕,更不用提静态检查了,因为没有强制措施的缘故,我甚至当了半年多的“格式化”工程师,我自问并没有代码洁癖,格式化已经是最低要求了
  • 负载:这其实是一个额外的问题,在我之前,团队没人关注这一些,服务无脑申请资源,至少1C+2G,平均负载低的可怜,极大地浪费,在我的强烈敦促下,才减少到0.5G+0.5C,就这样,平均负载50%都不到(我一度怀疑是不是咱们团队写的代码太优秀了)

Monorepo解决的问题

其实真有点讽刺,今年以前,我还是微服务的无脑拥护者,不过抛开那些耳熟能详的高谈阔论,单一代码仓库又确实能解决我的问题,而我们的服务又是微服务的,在我们这样子的小团队,优势还是很明显的

  • 代码风格统一
  • 抽象得当的话,代码复用率会非常高
  • 小团队,代码合并问题不大

因为公司的CI选型是droneci ,且没有任何迹像要引入bazel,所以单一代码仓库对提供构建效率是毫无帮助的。

轮回

如果过往奉k8s、微服务、容器化为圭臬,现如今我也没有得出完全相反的结论,合适的场景,选择适合的技术体系,使团队收益最大化,才是紧要的事情,毕竟,唯一不变的,就是变化。

参考