透明、灰度、兼容&半强制

最近重构了一个公司业务的一个模块,涉及的东西有点多,从需求评审到技术评审,再到各端沟通,花了很大功夫才确定架构和技术方案,最后开发提测灰度上线,清洗数据等等,整个重构经历了很长时间。现在一切尘埃落定,我也静下心来把工作中的思考和探索记录下来。业务不能说的太详细,用一些泛泛的概念,比如新业务逻辑,新业务数据,旧业务逻辑,旧业务数据,业务主体等等。

透明

我很喜欢透明这个词,在软件领域的意思就是关注应该关注的东西,不应该关注的东西应该是透明的、看不到的。
原业务是后端提供一个 HTML,前端各渠道各自编写相同逻辑处理 HTML 里面的信息,进而展示给用户。这样的设计真的是非常痛苦,首先各端工作量增加,其次耦合性太高,最重要的是需要使用 iframe 或引入 jquery 来执行逻辑。重构之后由后端处理完 HTML 的信息,传给各端一个纯展示用的 HTML,对于各端来说这个 HTML 里的内容是透明的,他们不必关注,只需要展示就可以了。
另一个是 HTML 里面有很多需要填写的关键信息夹杂在内容之中,在不同的 HTML 中有可能有相同的关键信息,原业务对相同的关键信息用相同 ID 的 input 标签作为区分,后端再根据 ID 来存取所填的值。这样导致每创建一个新的 HTML 都要开发人员编写并保存一个完整页面,并且确保其中关键信息的填空的 ID 和约定一致。重构之后 HTML 的文本内容和关键信息分离,文本内容相当于纯文案,关键信息则是 key-value 列表,由后端装填到一个 HTML 模板中即可,这样一来,这些业务无关的内容对于后端和前端来说都是透明的,文本内容和关键信息的修改不需要投入开发人员。

灰度

重构一个正在运行的服务,新旧逻辑和数据不互通,不能保证同一时间迁移数据的,而且变更内容过多,影响范围较大,一定要有一个灰度方案,保证出现问题能够把影响面降到最小,新的服务能够逐步稳定地替代旧服务。
首先是灰度范围的选择,从业务的哪一层面来划分灰度范围,选取的颗粒度不能太大也不能太小,根据业务来寻找一个层面进行划分。
然后要考虑如何方便地调整灰度范围直至全量,以及如何保证后续新的业务主体自动进入灰度范围,我在数据库的字典表用一条数据记录灰度范围,也就是一些类型 ID 用逗号拼接成的字符串,代码逻辑会根据业务主体判断其类别是否在灰度范围,当灰度范围调整时,更新这条数据,当这条数据为空字符串时,代码判断为全量切换,即所有业务主体走新的业务逻辑,保证后续新增的类型自动进入灰度范围。
最后是灰度策略的制定,灰度范围外的业务如何处理,在灰度范围内但没有新业务基础数据的怎么处理,其他上下游业务如何保证不受灰度策略的影响。我在这次重构中,灰度范围外的业务主体仍然按照旧的业务逻辑处理,加到了灰度范围中但没有新业务基础数据的,仍然按照旧业务逻辑处理。新的业务保证上下游数据的正常交互,就像一条河流在中间分成了两条河道,对应新旧协议,然后又汇聚回原河流。

兼容

在涉及很多端,不能保证各端同一时间上线,尤其是 APP 端不能强制更新的情况下,旧的接口和逻辑要能够保持正常运行,旧的接口可以调用新的服务,而新的接口也要能够调用旧的服务。也就是说在使用灰度方案时,要保证新旧接口都可以正常工作,并根据灰度范围来正确调用新旧服务。
举个例子,这次重构中,旧业务逻辑是前端根据占位符填充的某些内容,新接口无论新旧业务数据,统一直接在后端填充好了,为了让旧接口兼容并正常展示新业务数据,我在旧接口返回新业务数据时 hack 了相应的占位符,仍然走前端填充的方式。

半强制

在设计了灰度和兼容两个关键点之后,带来另一个业务上必须考虑的问题,就是用户太懒。因为我们有灰度和兼容方案,所以使用者感觉旧的业务还可以使用,便不愿意迁移到新的业务,而且对于他们来说,新旧业务并没有什么不同。
所以我们的半强制策略就是,进入灰度范围的业务主体将不能修改和展示旧业务数据,只有编辑新业务数据的入口,旧业务数据可以走旧业务逻辑完成整个流程,一旦编辑好新业务的基础数据,该业务主体将走新业务逻辑。

作者: snowhere

Keep coding ... Stay cool ...

发表评论