考虑以下三种做法:
- 在代码中埋入 Feature Flag,通过配置中心下发开或者关,或者对一部分流量打开
- 在本地的笔记本上启动一个独立的精简集群做测试开发
- 在本地的笔记本上只启动一个进程,集群的其余的进程使用生产环境的
我把这三种做法都归纳为 Multi Variant,多个变种。它们都是在不改变进程的情况下,通过配置等方式更灵活地进行装配组合。 这样发布和上线就可以解开为两个操作了。上线就是上线,改变进程里的可执行代码。 上线可以不把 Feature Flag 打开,而是保持原有的行为。除非 Feature Flag 本身实现得有bug,上线过程的风险就小了很多。 然后再慢慢地打开 Feature Flag 的流量开关。
Feature Flag 未必一定是用 if/else 实现的,它可以是基于插件机制来实现的。 根据不同的 Feature Flag 的配置信息,选择执行同一个插件的不同版本。 其实质是运行时的插件动态装配。把发布从进程粒度,降低到插件的粒度。
Feature Flag 虽然好用,但是仍然要先完成上线。从 Feedback 周期来说仍然不够理想。 如何在上线之前就测试好呢?本地搭建一个完整的环境困难重重,不仅仅可能笔记本性能不够,而且还有一大堆的数据配置依赖。 理想情况当然是可以把业务拆成更小的部分,只做一部分的集成就能完成测试。 比如说一个app里包括了打车和外卖,那需要打车和外卖都打包进去吗?显然可以只跑打车的代码嘛。 但是部分集成不是免费的,每添加一种部分集成的跑法,就给代码增加了一个运行模式,是需要额外维护的东西。 当团队比较多的时候,只有维护生产环境是大家共同的目标,你自己搞出来的一个部分集成的环境,未必能够得到其他人的认同和资源支持。
所以 Test in Production 才会逐渐火起来,因为只有 Production 才是唯一公认必须保持稳定的环境。 在自己的笔记本上只启动自己修改了代码的进程,才更符合高效分工的原则。 根据概率论,一个系统的稳定性是其构成模块稳定性的乘积。 如果要本地搭建一个完整的集群,必然是一个很不稳定的东西。 在有了多租户的前提下,Test in Production 仅仅需要解决部分替换进程这个问题。 通过在 Http Header 中附加路由信息(例如 Istio Request Routing), 是可以实现一个集群中其他进程都用生产环境,但是你修改的进程替换成你本地启动的。
我们总结一下
- 多进程:控制的是代码的变更
- 多租户:控制的是数据的变更
- 多变种:控制的是配置的变更
理想的快 Feedback 工作环境里,上线应该是每个小时都发车,随意可以搭车的。 多个团队的Git仓库其实是跑在一个进程里。 每个团队通过 Feature Flag 来做自己的灰度测试,出了问题可以一键回滚。 一次可以只变更一个租户,确保不出大面积故障。开发者不需要费心维护自己私有的开发环境,而是直接 Test in Production。 需要全链路压测的时候,创建一个新租户,放心大胆地随便随便测。