如何发布一个客户端
2024-04-18
客户端的维护是困难的。
以前做服务端开发,依托现有的已经十分完备的基础设施,例如持续集成,持续部署,以及多副本,分布式,灰度发布,服务端发版和上线节奏非常快,紧急的时候一天可以上线多次。
因为服务端本身都是内部维护,不需要用户参与,开发者和运维人员对于服务的掌控力非常强。
客户端则不然。
客户端发布后,用户安装并更新,如果出现问题,基本没有办法远程修复。只能依赖重新发布版本,并引导用户更新。
这就带来两个问题。一方面问题修复周期长,缺乏即时的反馈链条,另一方面用户体验差。
由于过高的回滚成本,因此为了兼顾功能和可用性,客户端需要更为谨慎的发布策略。
在正文开始之前,先简单明确“客户端”的概念。
这里说的客户端,不仅限于 PC 上的软件,也包括手机上的 APP,需要用户下载到本地并安装。以网站作为服务载体的程序不算。
1. 起因
写这篇文章的动机,源于前两天为一个客户端发布新版本。
这里以 Edge 为例。
根据 下载官网🔗 下载官网描述,除了稳定版(stable),还提有三种预览版,分别是:
- 金丝雀版(canary)
- 开发版(dev)
- 测试版(beta)
这三个版本的稳定性强度递增。
其中,金丝雀版每天更新,开发版每周更新,测试版每个月更新,稳定版也是每个月更新一个大版本,只是相比而言,测试版就是提前释放出来的稳定预览版(preview)。
作为普通用户,自然不用关心这么多。
但作为开发者,这个问题就有意思了,为什么一个客户端,需要那么多不同版本?
我很想知道这种设计背后的原因。
2. 问题和思路
现象的背后,一定对应着某个问题,而现象只是解决方案的呈现。
经历一番调研,看到几篇不错的文章:
对于客户端的发布者而言,面临的问题主要有两个:如何尽快将载有最新特性的版本递交给用户,同时保持存量和增量版本的稳定性。
这两者通常是互斥的。
尽快发布新特性,意味着更快的发布频率,往往导致因测试不彻底带来的稳定性降低;而如果稳妥起见,测试完备后再发布,可能几个月都过去了,在追求极致效率的今天显然不合适。
所以,需要找到一种,尽快发布新版本,同时尽可能保证稳定的发布方式。
目前业界采用的方式大同小异,多采用“火车发布模型🔗”。
这是一个非常形象的比喻。
把新客户端的交付,当作是一群旅客从起点到终点的过程。
中间会有几个小站,火车到达每个站点的时间由时刻表规划好。
小站的意义在于,有些客人,中途就要下车抽根烟,小站提供了机会。
同时,如果有些客人想从某个站点临时上车,就要提前看好时刻表,不然就得等下一班。
等列车到达终点,旅客下车。同时下一列班车出发。
沿途停靠的站点,就可以区分为金丝雀、开发和测试多个版本,终点站是稳定版。
核心思想,简单概括下,就是两个:敏捷和灰度。
敏捷保证效率。有新的特性,自测没有太大问题,尽快上车,积攒一批后,小站点下车,释放一个版本。同时下车前会有一次集中的、高强度的回归测试。
灰度保证稳定性。版本有多个,可以区分不同用户需求,普通用户追求功能可靠,依赖稳定版即可;有些极客,想尽快尝新,可以用金丝雀版本;对于开发者,如果想要提前测试需求,可以使用开发版。通过多个不同的灰度阶段,在流程上保证新的特性会尽快出现在用户手中,同时问题也会提前暴露。如是,在终点下车的稳定版,可靠性能得到有效保证
3. 具体方案
结合上述描述,下面举一个简单的例子,看一下具体火车是怎么跑的。
对于绝大多数企业和开发者而言,代码版本控制通常借助 Git。
这里只需使用到 Git 的两个特性,就可以实现需求,一个是分支,一个是标签。
Loading graph...
火车所在的分支是 release,开发者的分支是 develop。
按照时刻表,火车发车,此时从 main 分支的某个 commit 切一个分支出来。
有新的功能开发完成,先合入到 main 分支。
main 分支每天会打个 tag,释放一版金丝雀。由于金丝雀版本每天都发布,因此最新的功能 都在上面,致命问题也有:非常不稳定。
release 会定期将 main 分支的改动同步,但中间存在时间差,比如说两周。只有两周前签入 main 的改动会出现在 release 分支上,好处是,改动在两周前就已经出现在金丝雀版本了,如果有问题,这么长时间足以发现。
间隔一周,release 分支释放一个测试版,稳定性比金丝雀好一些,开发者可以提前在上面测试。
一个月后,所有的功能基本稳定,稳定版发布。
因此在开发的时候,只要看好时刻表,在火车到站前上车,就能跟着车一起抵达终点。
如果没赶上,而又需要临时上车,比如某个重大 bug 的 fix,就得联系站长,找一辆车,提前送到下一站。在 Git 里的操作就是一个 Cherry-pick。
至此,整个流程就可以跑起来了。
4. 总结
软件工程其实很有趣。
通过机制的确定性,对抗人和组织的不确定性。
一个看似复杂,矛盾的问题,是可以被妥善解决的。
果然 trade-off(权衡)在计算机领域无处不在。
延申一点思考,客户端的更新,其实和人的成长类似,犯错是不可避免的。
尽早地暴露问题,尽早地尝试,犯错后修正,反复迭代,慢慢地趋于稳定。
不做,就不会出错,但这不应该是我们该考虑的。
(完)
参考
- 本文作者:Plantree
- 本文链接:https://plantree.me/blog/2024/how-to-deploy-client/
- 版权声明:所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明出处!
最后更新于: 2024-11-20T09:44:17+08:00