美文网首页
构建可回滚的应用及上线checklist实践

构建可回滚的应用及上线checklist实践

作者: 木小丰_ | 来源:发表于2021-11-22 10:20 被阅读0次

    一、背景

    在互联网分布式应用中,如果上线的新版本有bug又不能回滚止损,带来的后果将是灾难性的。因此做到上线可回滚以及上线前的checklist是保证服务稳定性的基本要求。

    在简单的场景里直接回滚到上一版个版本即可,但是如果涉及多个上下游和组件、考虑多版本兼容,就需要有好好设计下如何构建可回滚的代码,充分验证后还需要仔细检查上线checklist,最大程度保证线上服务的稳定性。

    二、构建向前兼容的代码

    回滚指的是程序或数据处理错误,将程序或数据恢复到上一次正确状态的行为。在回滚之后,程序依然能够正常处理,称为可回滚。

    不可回滚原因大多是旧程序不能处理新数据,同时新数据又不能丢弃,代码回滚导致旧业务逻辑出错。

    保证向前兼容的手段:

    1、数据库变更

    新加字段:设置默认值,默认值要保证新旧代码逻辑的语义一致性。比如用户表添加了用户状态,默认值要设置为默认有效。

    删除字段:新版本全量发布后,最后迭代2-3个版本后,再删除无用字段,同时要做好数据库备份。

    新加唯一约束:首先要确保原有的数据值没有重复的,再添加唯一索引,可使用以下SQL验证:

    select field,count(1) from table group by field having count(1) > 1
    

    复杂数据库字段变更:
    复杂数据库字段变更:

    • 通常做法是:双写读旧 -> 新字段离线验证 -> 旧字段全量拷贝至新字段 -> 双读旧为主diff -> 双读新为主diff -> 写新读新 -> 移除旧字段和逻辑;

    • 出问题之后,只回滚程序,不回滚数据。

    2、对外提供服务API变动设计

    (1)对外提供RPC服务

    入参新加字段:设置为可选的,如果没设置值,要有老业务逻辑兼容代码

    返回值字段:设置为可选的,如果是新版本肯定有值字段,需要在字段描述文档里做好备注

    如果入参和返回值结果差异较大,建议新建一个RPC方法,逐渐把业务方调用迁移到新方法

    (2)对外提供HTTP服务

    HTTP接口和RPC接口的不同是没有强制的约束,数据交换大多采用Json形式,虽然灵活性强,但是约束力低给管理带来很大的成本。因此HTTP接口文档必须给出类似RPC一样的规范,比如Swagger等工具,比如给指定字段名、类型、是否必填、不填写的默认值等。

    3、多版本发布

    对于客户端API服务或者基础服务来说,用户升级会有很大的延迟,对于服务提供方来说则需要尽量保证多版本同时可用。最好在最开始设计接口的时候就添加version字段,保证以后的扩展。

    4、静态资源发布

    因为静态资源一般放在CDN上缓存时间设置的比较长,比如1个月。这样假设发布的版本有问题,需要清理CDN缓存,并且也需要清理浏览器缓存,而且因为存在版本覆盖的问题,即使覆盖了也不一定保证是操作正确了。

    现在的工具默认都会把md5设置到js、css文件名中,可有效的避免以上问题。

    image-20211120215947571

    三、上线checklist

    尽管准备工作做的再好,难免也会出现疏漏,因此指定上线前checklist,组内同学交叉评审,保证上线前的最后一步,是很有必要的。

    发布策略一般是从下游逐步向上部署。而回滚方案相反,一般是从上游往下回滚。

    通用的checklist需要考虑以下几方面:

    1、依赖

    (1)存储(数据库、分布式缓存)

    是否有数据库变更需要代码上线前先提交,并且验证执行成功。

    (2)动态配置

    首先需要确认代码中的动态配置有无默认值,没有默认值需要先在动态配置系统上添加相关的配置。

    (3)下游

    确认下游jar包版本是否正确,线上最好使用release包。

    确认下游的业务方是否已经上线。

    (4)鉴权

    美团内部的服务调用都有鉴权,检查鉴权是否已经添加并且已生效

    2、上游

    (1)Nginx层

    确认路由策略,在发布过程中会不会造成用户不断刷新页面命中不同代码逻辑,给用户带来用户体验上的问题和困扰。

    (2)上游业务方

    确保和上游业务方沟通好,等当前服务全量发布后且观察、验证没问题再通知上游发布。

    3、业务内部

    通过代码review,QA测试等方式保证上线对现有业务逻辑没有影响。

    如有必要可建设业务的checklist规范

    • 代码review:重点查看代码规范、业务逻辑的正确性、对相关功能的影响

    • 测试用例:测试相关代码的正常逻辑、边界条件、其他功能不受影响,如果写好测试用例请参考其他专业的文档

    • 自动化测试:有条件的团队建议添加自动化测试,来保证核心业务流程的正确性

    四、可回滚发布

    1、回滚方案

    需考虑以下几方面:

    • 是否有动态开关、流量控制可以一键恢复到旧版本逻辑

    • 回滚代码会不会导致上游调用失败

    • 回滚代码:根据docker镜像、Git commitId、Git tag回滚

    2、可回滚验证

    方案设计要考虑可回滚性;通常要在test或预上线环境验证(演练)可回滚性。同时QA同学要把可回滚作为质量验收的一部分。

    3、平滑升级

    (1)线上验收

    通过staging环境或线上灰度链路, 进行线上验收。

    (2)蓝绿发布

    线上部署两个集群,每个集群都能抗住所有的流量,发布的时候一个集群接受用户请求,等当前集群全部发布成功后,再把流量全部迁移到新版本集群。

    优点:可保证新版本特性同一时间对所有用户生效;保证系统高可用,一个集群出问题,可快速切换到备用集群;

    缺点:日常使用的机器只有一半,造成浪费;

    蓝绿发布的高配方案:部署两套集群,通过Nginx层动态切换集群。

    蓝绿发布的低配方案:用动态开关控制新旧逻辑,等新版本全量上线后,再切换到新代码逻辑。

    (3)灰度发布(金丝雀发布)

    采用金丝雀部署,可以在生产环境的基础设施中小范围的部署新的应用代码。一旦应用新发布,只有少数用户被路由到它。最大限度的降低影响。检测新版本没问题,再逐步扩大发布范围直至全量。

    实现灰度发布,需要部署系统设置分批发布,同时必须有监控、报警等相关的系统的配合。确定没问题后再扩量。

    还有一点需要注意的就是灰度路由策略,一般服务中用的多是的随机策略,这样可能导致用户在发布过程中不断刷新页面,可能会来回命中新老版本逻辑,影响用户体验。避免方式有以下几种:

    • 采用用户ID做路由因子,问题是新增、删除机器时,算法匹配的机器会变,就需要引入一致性Hash算法,复杂性较高

    • RPC路由策略一般不能执行路由规则,就需要程序自己判断。常用做法是采用动态配置设置百分比值,算法如下:

    userId % 100 < $dynamicTrafficPercent ? oldVersion : newVersion
    
    (4)AB测试

    AB测试虽然也有流量控制的功能,但一般是用于验证不同版本之间的性能、用户体验、效果数据等的手段。是上线后由运营控制的。

    AB测试和灰度发布最大的不同是AB测试是通过桶的方式分配流量。

    4、监控报警

    常用的发布相关的监控报警包括:

    • 新、旧版本的流量及百分比

    • 对外提供的接口的性能指标、下游的性能指标(TP50、TP90、TP99、TP999)

    • 异常指标及报警

    • 业务指标

    5、发布完成周知

    • PM: 周知PM关注业务指标、客诉等

    • 上游:如果上游依赖此发布,周知上游开始发布

    • 下游:周知下周注意流量增量及耗时等情况

    五、上线步骤及规范

    1、不在高峰期上线,如必须上线,要发邮件申请,同时降低并发度

    2、上线前周知

    3、保证能回滚

    4、发布过程采用分组发布(强制)

    5、上线过程中观察系统指标、业务指标、异常指标等;如有异常立即禁用已发布机器

    6、上线后周知PM、上下游等

    7、有异常第一时间回滚

    六、总结

    从本文可以看出,保证线上稳定性是一个复杂且系统的工程,需要从技术规范、流程规范、周知、检查、工具支持等各个方面来保证。

    作者简介:木小丰,美团Java高级工程师,专注分享软件研发过程中的实践、思考。欢迎关注公共号:Java研发

    原文链接:构建可回滚的应用及上线checklist实践

    更多精彩文章:

    Maven依赖冲突问题排查经验

    升级Java17问题记录

    使用Groovy构建DSL

    Gradle最佳实践

    相关文章

      网友评论

          本文标题:构建可回滚的应用及上线checklist实践

          本文链接:https://www.haomeiwen.com/subject/lkavtrtx.html