前言
项目研发的过程中经历了需求评审、开发评审、代码编写、测试用例评审、项目测试、产品和UI验收等一系列流程,其中投入了大量的人力和精力。
然而最后的上线阶段,总是存在诸多不确定性和可变性,往往在测试阶段测N次都没有丝毫问题,一上线就会出现Bug(简直是墨菲定律的诅咒)。
经过多年的经验总结和残酷教训,我们将这些已知的或潜在的风险点详细梳理出来,希望每个项目的上线都可以踏踏实实、万无一失、顺顺利利。
本文,我们将从三个方面来防范上线风险:操作防范、双岗&自查、监控告警。
一、操作防范
主要包含了四大类别的防范:研发防范、配置防范、运维防范和审批防范。
1.1研发防范
1.1.1 通用层
- Loading/Confirm统一标准化
- 错误页/骨架屏/无数据/网络异常兜底规范
- 公告、弹窗规范
1.1.2 代码层
- 使用https、禁止非jd源、验证外网可用
- 环境切换通过系统变量区分
- Commit规范
- 单次提交独立功能代码
- 所有研发代码提交Coding
- 统一IDE和脚手架
- 开发环境node.js、npm、joyer、taro等版本统一
- 统一通用组件
- 沉浸式导航
- 共用组件,检测版本支持及容错处理
- 云梯组件
- 加密防刷:AKS,AAR
- 风控设备指纹
- 奇点埋点
- 下载唤起组件
- 分享组件以及金口令
- 数据处理
- 分页加载避免请求死循环
- 网关层错误码处理
- 服务端接口层错误码处理
- 主功能接口异常是跳转错误页/弹窗重试等必要处理
- 兜底方案
1.1.3 UI层
- 是否有动效
- 音视频是否兼容性
- 是否存在性能卡顿
1.1.4 安全层
- 编码问题:是否通过eslint
- 兼容问题:编码语法、方法属性、组件库最低支持版本等处理
- 逻辑功能:代码逻辑是否与预期功能一致
- 异常情况:是否考虑降级/容错/超时等异常情况
- 用户体验:新增或者修改功能对性能或者体验是否不良用户体验影响
- 安全:密文传输、防刷、脚本注入等
- mock:是否正确处理了mock数据的展示
- 敏感数据:对数据处理是否存在潜在客诉风险等
1.2 配置防范
1.2.1 研发配置
- 内容配置平台配置已上线的配置再次操作要注意不影响线上,尽量新增配置
- 配置数据类型不支持时间控件,禁止在上面配置时间或时间戳等数据
- 配置前的数据校验(例如:链接格式是否正确,数据长度是否需要限制等)
- 数据容错处理,若为重要数据需设置为必填项 "required": true;
1.2.2 运营配置
- 活动上线前,所有生产配置必须都完成
- 已上线的配置,再次操作需与产品及研发确认;运营内部双岗确认
- 预发环境验证,数据和生产保持一致(奖品类型、券类型、秒杀时间、任务类型等)
- 奖励、券或任务等需验证可正常发放或领取后再配置展示到前端
- 在活动领取利益点到其他活动页使用,需保证二级活动页面内使用利益点正常
1.2.3 环境配置
- 所有新项目统一使用joyer脚手架初始化
- 命令统一,本地环境、打包、发布各环境等
- vconsole、注释等仅在非生产包中配置
- 每个项目必须有mock环境,使用mock数据去验证各类情况,而不是修改或注释代码
- 老项目是否采用webpack、vue-cli统一规范
1.3 运维防范
1.3.1 域名解析操作
- ip是不在应用下存在
- 实例上是否具有可访问项目
- 找运维配合查看是否项目可访问
- 确保告知运维工单受理通知开发人员及时验证
1.3.2 CDN操作
- 确保源站域名和加速域名不一致
- 确保上传的加速内容与分发方式相匹配(图片、大文件、视频、直播流)
- 确保加速域名下的文件为静态资源(考虑是否需要做动静分离)
- 确保源站IP是否正确
- 申请接入后只代表CDN已完成后还注意需配置DNS解析变更
- 查询输入域名查看全国各地区解析是否生效
1.3.3 HSTS操作
- 确保客户端或应用是否https或开启https强跳是否有问题
- 对于vip下有多个应用或域名要通知各方确认是否有影响
1.3.4 http2操作
确保域名为https才可开启
1.3.5 ddos操作
CDN域名暂不用接入
1.3.6 扩容操作
- 机器审批完成确认执行结果全部成功
- 确保新扩容机器配置及项目部署
- 对于混合部署有多个应用存在需要所有应用都完成部署并验证(可让运维配合)
- 混合部署应用确保每个应用都要走复用工单
- 确保扩容操作完成后重启机器操作
1.3.7 缩容操作
- 确保CDN域名解析的为内网VIP(如果为rip需要走变更VIP工单流程)
- 混合部署确保每个应用都要走工单
- 预发机器需要补充预发域名反向代理变更工单
1.3.8 下线操作
- 确保下线机器是否影响线上(独立部署某个项目)
- 注意摘流量-摘机器等步骤完成才可下线
1.3.9 回滚操作
- 使用JDOS点击回滚操作
- 回滚选择的包要仔细检查是否是上次上线的
1.3.10 堡垒机操作
- 容器必须正常启动
- dockerfile构建的镜像,只能申请root权限且22端口必须打开
- 公共镜像,只能申请root权限且22端口必须打开
1.4 审批防范
- 是否经过测试节点审批
- 是否由leader审核
- 开发与审批权限是否分开
二、双岗&自查
上线前的双岗自查,是我们制定的一项标准流程。要求研发人员在上线前必须按照下面的清单,并寻求其他同事的协助进行项目代码的排查(当局者迷,旁观者清)。
2.1 前端
2.1.1 环境检查
- 域名是否接入CDN
- jen配置是否一致
- jen是否全部在线
- 是否开启gzip
- 部署机器数量与预期是否一致
2.1.2 公用组件
- 是否接入AAR
- 是否接入AKS
- 是否接入风控
- 是否添加SGM监控
2.1.3 需求检查
- 本次上线资源是否包含非本次产品需求迭代内容
- 页面引入资源是否都是本次上线内容
- 本次上线资源是否为预发已测试版本
2.1.4 代码检查
- 是否有第三方代码注入
- 是否存在敏感字段
- 是否去掉log/mock/Vconsole等调试工具
- 项目中是否存在http域名资源
- 服务端接口是否为线上
- 检测所有资源域名是否为线上外网域名
- 包资源文件hash是否由生产部署
- 仓库master代码是否是最新的
- 对于混合部署应用,本次上线是否只更新当前应用代码
- 对于通天塔自定义组件,本次改动是否考虑低版本,是否影响其他项目中引用的模板
2.1.5 回归检查
- 使用4G/5G验证
- 上线后操作CDN资源是否是最新上线的
- 上线后验证。对于混合部署的项目,最新分支是否合并到master
2.1.6 流程工单
- 双岗检查确认通过
- UI走查通过并确认
- 风控验收通过并确认
- 安全测试工单提交并完成
2.2 服务端
2.2.1 监控检查点
- 业务监控
- 订单
- 日志异常
- SQL异常
- SQL耗时
- 业务耗时监控
- 业务状态异常监控
- 异常流程监控
- 基础监控
- 第一类运维:应用系统所依赖的硬件、虚拟机、网络等
- 第二类运维:操作系统层面,比如cpu,内存,硬盘,IO等
- 第三类运维:中间件层面的,比如数据库,缓存,tomcat, ningx等
- 第四类运维:应用本身的,比如JVM监控, 日志归集等
- 第五类运维:新功能上线操作和日常应急演练工
2.2.2 通用自查点
- 上线顺序类
- 内部存在多个应用上线,依赖关系及上线顺序,是否已经考虑过
- 应用上线前,是否需先创建好了相关表结构,注册mq,rpc等操作
- 本次版本上线,是否涉及外部应用,是否需要别的模块配合,上线是否有顺序要求
- 安全类
- 是否要考虑外网安全问题,比如SQL注入,XSS攻击,敏感信息加密,账号爆破等
- 是否考虑接口通信安全问题,加签验签,秘钥管理等
- 各种访问是否考虑要增加白名单或者证书或者短信
- 数据库敏感字段是否加密
- 防刷,防重类
- 防重机制,哪几种状态和场景下允许重复发送订单
- 否有限制允许同一秒接受多笔同样的订单
- 平台唯一ID生成是否会有重复的可能
- 所有请求入口,定时器和API请求是否使用乐观锁。考虑并发重复处理问题,并且要判断更新影响条数
- 异常处理类
- 是否处理了各业务的主分支以外的异常分支
- 详细异常栈别吃掉
- 三方交互的是否完成
- 需要抓取IOException做处理
- IOException需要打印URL方便报警排查问题
- 需要设置连接超时和读取超时时间
- 是否需要通过代理出网
- 是否需要再三方添加白名单
- 三方是否有最大数限制
- 合理设置http连接数和关闭连接
- 日志规范类
- 日志打印是否有自己的业务规范,有助于日志巡检
- 定时任务类
- 业务定时器是否有浪打浪,重复处理的情况,并发配置是否设置成false
- 定时任务中处理的数据量是否有预期的执行size,是否会出现异常情况下,处理的size越来越多的情况
- SQL类
- 是否使用了唯一索引
- 唯一索引的使用是否正确,例如多个字段做为联合唯一索引,是否存在字段为null情况
- update和select语句是否有预期的执行size
- 是否避免使用复杂sql
- sql是否检查过执行计划,是否能命中索引,一段时间业务增长是否存在慢sql的可能性
- 缓存的使用
- 缓存使用,是否设置超时时间,超时时间设置是否正确,是秒单位,还是毫秒单位
- 缓存同步问题解决方案的评估(数据库悲观锁+事物+排序、redis悲观锁、CAS)
- 清楚redis的使用场景
- 事务的使用
- 代码中使用事务的需要考虑死锁场景
- 管理后台
- 管理后台下载,查询等功能是否有条数限制和频次限制
- 类型转换
- 类型转换是否正确,是否先判空再进行转化
- 连接数,线程数
- 线程的创建是合理地否限制了线程数量
- 相关中间件的连接池数量设置是否合理
- 返回码解析
- 解析响应码是否正确,特别是对于网络异常、catch异常、无此订单等特殊情况
- 响应吗解析-网络异常/订单不存在(网络异常导致和查询早于交易导致),非明确失败,不可以设置失败
- 系统设计问题
- 异步转同步,如果后端异步部分组件宕机或重启,导致同步dispatch数据一致被阻塞
- 是否存在单节点
- 是否要支持分布式部署
- 乐观锁防止并发修改,悲观锁
- 超时时间设置
- 任何RPC调用地方是否设置连接超时和响应超时时间,包括HTTP、redis、数据库等
- 金融属性
- 记账类功能需要考虑余额和流失是否在并发情况下准确
- 金额单位,精度是否正确
- 金额类型转换是否正确
- 时间写法
- 时间格式,精度是否有问题,是否会出现写库后四舍五入的情况,导致查询不匹配
- 数据库时间配置问题,是否设置东八区,活动是否对时间使用东八区格式
- 配置文件
- 线上配置文件是否单独抽离上线包,是否已提前在平台单独配置
- 若存在不抽离的配置文件,随代码提交的配置文件,是否已检查是正式环境的配置信息
2.2.3 资源支持项
- 是否要运营提供额外支持,比如运营后台参数配置等事项
- 是否要运维提供额外支持,比如配置网络环境、添加证书秘钥、创建文件目录、添加和删除jar包等事项
- 是否要DBA提供额外支持,比如新增模块添加数据库访问白名单等事项
三、监控告警
监控告警是上线后的风险治理必要机制,一旦出现告警,我们可以第一时间排查和解决,防止更多的客诉产生。
- RPC层监控
- 超时监控
- 异常报错
- 可用率
- CACHE监控
- redis连接异常
- r2m可用率
- r2m容量
- r2m主从切换
- MQ监控
- MQ接收重复
- MQ发送失败
- MQ内处理失败
- Task监控
- 定时任务未执行
- 定时任务超时
- 定时任务执行异常
- 业务异常监控
- 获取锁异常
- AKS和防刷未通过异常
- 任务领奖/接取等异常
- 人群没有权限
- JVM监控
- fullGc日志与告警
- jvm监控告警
- 容器监控
- 实例存活
- CPU负载&使用率
- 机器内存
- DB监控
- DB层CRUD执行异常
- cleverBD慢SQL定期巡查
- DB查询操作时间超长
- 线上环境(应用、数据库、配置等)审批负责人是否为当前leader
- 利益点监控
- 营销发奖失败
- 库存不足
- 活动未开始/已结束
- 被风控
- 防重失败
- 单个用户领取利益数量超过配置的警戒线
- 活动整体发放量超过配置的警戒线
- 其他异常失败
- 业务响应码监控
- 第三方接口正常码和异常码配置来监控可用率
- 配置校验
- 获取配置异常
- 配置中该配应配字段未配置
- 配置中字段配置类型异常
- 没有符合当前时间的配置
- 活动已结束但仍然有大量用户访问
- 多个配置的时间点冲突
- 配置的奖励Id/任务Id等在第三方接口未查询到
- 每次运营修改配置,修改项通过告警发送到研发,对告警分等级
- 活动资格校验
- 绕开某个校验告警
- 应是老用户领奖但新用户通过前置校验进入领奖流程