四年前,我加入了风头正劲的 Square 公司。两年前,我又加入了涨势甚猛的 Airbnb 公司。在我加入的时候,这两个公司都有上百名的工程师,网站和主要产品的核心功能也已齐备。
两家创业公司从 0 到 1 的创业过程我并没有亲身经历,但是两次都恰好经历了公司从 1 到 N 的扩张过程和业务拆分的过程。
今天我就和你聊聊,公司从 1 到 N 发展过程中的系统拆分问题。
创业初期的代码现状
在 Square 刚刚起步的时侯,整个产品都是基于 Ruby on Rails 构建的,所有的产品和功能代码几乎都在一个代码库里。
等到我进入 Square 的时候,有一些服务已经从 Ruby 代码中分离出来了,形成了单独的 Java 或者 Ruby 服务,然而大部分功能还是在一大块 Ruby 代码里。
当时,几乎所有的工程师每天都在这一份基准代码(Code Base)里写程序。虽然有严格的代码审核过程和规范的开发流程,但是,不同功能的代码模块会产生交叉影响,不同工程师改动的模块会有重合或牵连,所以,系统还是会时不时出现问题。
那时候, Square 的做法是:在周五对本周所有的代码进行代码审查(Code Review),通过审查之后,把修改合并到主分支,然后再发布到生产环境。
这种做法虽然可以避免产生人为错误,但是非常不灵活,比如,每周只有周五有一次机会将改进的代码部署到线上。
可以想象一下,一百多名工程师,就算只有三分之一的人在这个代码池子里改代码,一周累积下来,已经有不少的改动了。
于是,当时 Square 有个系统管理员组(Sysops),专门负责每周五的部署。我也是工作近半年的时侯,因为表现不错才被荣幸地 “选拔” 进了这个 “特别行动小组”,承担部署的重任。
那么说,每次的部署是一幅什么样的场景呢?
部署开始的时候,一正一副两位工程师正襟危坐,多个显示器同时打开,进行各种指标监控。
工程师先将在测试环境中测试无误的代码部署到若干生产机器上,进行灰度发布,这就意味着有一部分用户的访问量会调用新代码。如果监控没有发现异常的话,再进行全量发布,这周修改的代码就会被部署到几百台机器上。
一旦出现异常,监控系统就开始各种红色告警,工程师们会立刻扔下手中的可乐或者咖啡,进入备战状态,停止系统,进行数据回滚、排查问题、修复,从头开始把流程再来一遍,直到代码安全地部署到线上并能够正常运行为止。
随后的两年,我们进行了细致的业务拆分,等到我离开 Square 的时候,大部分可以独立出来的服务都已经拆分出来,很多系统可以分别部署和上线,也就再没有了那种激动人心的周五上线日。
Airbnb 的情况也差不多,我刚加入的时候,代码状态甚至更原始一些。不同的是,Airbnb 没有一周只能部署一次代码的规矩,所有的工程师只要准备好了就可以做部署上线。
这样做的优点是可以快速迭代,每次部署的代码改动也很小,缺点是几乎任何时候都有人在部署代码。时时的部署也就意味着,红色告警随时可能在身边响起。