如何发布一个客户端

2024-04-18 pv

客户端的维护是困难的。

以前做服务端开发,依托现有的已经十分完备的基础设施,例如持续集成,持续部署,以及多副本,分布式,灰度发布,服务端发版和上线节奏非常快,紧急的时候一天可以上线多次。

因为服务端本身都是内部维护,不需要用户参与,开发者和运维人员对于服务的掌控力非常强。

客户端则不然。

客户端发布后,用户安装并更新,如果出现问题,基本没有办法远程修复。只能依赖重新发布版本,并引导用户更新。

这就带来两个问题。一方面问题修复周期长,缺乏即时的反馈链条,另一方面用户体验差。

由于过高的回滚成本,因此为了兼顾功能和可用性,客户端需要更为谨慎的发布策略

在正文开始之前,先简单明确“客户端”的概念。

这里说的客户端,不仅限于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(权衡)在计算机领域无处不在。

延申一点思考,客户端的更新,其实和人的成长类似,犯错是不可避免的。

尽早地暴露问题,尽早地尝试,犯错后修正,反复迭代,慢慢地趋于稳定。

不做,就不会出错,但这不应该是我们该考虑的。

(完)

参考

  1. 客户端单周发版下的多分支自动化管理与实践🔗
  2. 字节跳动亿级DAU客户端发布最佳实践🔗
  3. 火车发布模型🔗
在 GitHub 上编辑本页面

最后更新于: 2024/04/24 10:37:29