技术复盘案例

2021年某个版本上线后由技术团队共同参与的一次复盘总结

Posted by 高强 on January 13, 2022

问题与优化

nacos-server CPU 使用率高、YoungGC 频繁

  • starter 配置的时间单位和nacos-client单位不兼容(s/ms)

nacos 版本升级到 1.4.0,加上用户名密码认证

  • 提高性能及安全性

loki/prometheus/grafana 日志系统及性能监控优化

  • 配置 grafana dashboard 增强使用体验
  • loki 去掉 auth-center 日志采集,不暴露敏感信息

分销/分佣相关的参数通过 header 传递会不会更好

  • 处理方案:后端改造成本不大,需与前端讨论必要性

初始化接口报错 mallInnerInfoFeignClient.listTeamVisitorAmount(chUserUuidList)

  • feign @RequestParam 参数超过 8k

    建议:解决思路可以沉淀到文档中

1.4.3 未实现的已购列表和订单列表合并课程、商品、活动功能,怎么实现比较好

  • 中间表思路,可能会新建数据中心服务,并考虑使用 NoSQL
  • 扩展:后续审计等功能考虑吞吐量更大的 Kafka

api层的序列化有必要配置相关Null参数吗

  • SerializerFeature.WriteNullStringAsEmpty\SerializerFeature.WriteMapNullValue\SerializerFeature.WriteNullListAsEmpty

    结论:跟前端确认改动没问题后,在当前开发分支改动测试,跟随需求分支上线

线上HotFix复盘

h_mall_1.4_qr_expire_time

  • 开启了关注公众号的活动海报二维码过期时间未乘以 24 小时

    建议:细心写代码

f_mall_1.4.0.1

  • 处理开启了关注公众号的活动在H5分享赚分享海报后扫码返回的链接下单,没有分佣的情况

    建议:开发设计时多关注产品和需求

hot_fix_20201223

fix: 预支付购买判断新客错误

建议:细心写代码

hot_fix_20201224

  • fix: 新客判断错误
  • feat: 只有直接分享者才有专属佣金(总分佣可能超过 100%的问题)

    建议:需求分析和逻辑设计更细心,文档化和案例描述

f_mall_1.4.2.1/hot_fix_1.4.2.1_20210107

  • 同步代言人数据(带来访客,推广金额,推广订单,以及正在代言产品统计数据)
  • 导出活动报名表单内容错误

    建议:加强自测

hot_fix_20210109,mall-center

  • 代言人自购支付价格计算错误

    建议:自测,代码逻辑抽象出来

h_mall_1.4.3_20210111_1

  • fix 代言人自购省金额 fix 订单A的状态被其他订单更新为 PAID,导致无法处理订单A的支付通知

    建议:细心些代码,出问题保留现场信息

hot_fix_20200111_01

  • fix:身份介绍长度校验

    建议:规范参数

hot_fix_20210113 -> hot_fix_1.4.3_20210114

  • 新客折扣显示错误

    建议:自测,代码逻辑抽象出来

技术分享

调度中心改造思路及组件布局@xxx

  • XXL-Job 架构
  • 定时任务任务改造方案
  • 旧数据同步方案

结论:

  1. 继续讨论调度器和执行器在项目中的定位,以及部分情况如活动通知、订单支付过期等任务跟执行器的交互逻辑怎么实现
  2. 对于定时任务旧数据的同步可以按定时任务类型出改造文档
  • 告警中心改造思路及规划@xxx

处理 CI 脚本的情况细分,比如仓库 pom 改了,是否仓库下所有模块都要打包

  • 流程及规范
  • 目前的后端开发流程及前后端测试协作流程的总结和优化建议

Teambition 上跟前端共同维护的联调部分,有接口变更可以标注得更清晰

  • 及时更新 Teambition 信息
  • 多个分支同时开发,部分分支上线后其他在开发的分支容易忘记合并master新代码
  • hot fix 上线后合并 master,新分支合并 master 代码的时机和建议操作者

上线前即冻结版本再打包上线,上线后处理 BUG 都开新分支处理

  • 上线后合并 master,源分支的发起者最好马上合并 master 代码到在研分支
  • 普通的入参异常和业务逻辑异常区分
  • ParamException 这种参数异常跟业务逻辑没直接关系的,独立出来,且不需要马上告警(发生太频繁时可以定制告警策略触发告警)
  • 其他异常如越权操作等独立出来,可以接入告警
  • 不直接继承 RuntimeException
  • commons 包变更频繁:message 等模块基本每个版本都要升级
  • commons 可以考虑仅用于可以抽象的共性逻辑,如MQ回调处理等
  • MQ 消息体定义及Routing Key、Exchange Key、Queue Name 等定义可以放到 dto-message

各个服务的版本号统一维护还是子服务单独维护

  • parent, commons, dto 的版本可以单独维护,开发分支可以跟业务分支一致
  • 包版本号和分支名不需要同步,版本号是按规范递增的,分支名用于表示分支处理的内容,版本号放到 ChangeLog 是关联的
  • hot fix 和普通的 feature 分支都使版本号递增,如 h_mall_1.4.3_20210111_01 可以对应 version = 1.4.3.0,其中二者的关联性可以在上线文档中体现出来

每次上线都需要全员(后端)准备或等待上线完毕,流程或分工上有没有办法优化

  • 上线分支人员需要 Ready,其他人自便

扩展思考

群内分享问题1

从redis中迭代取key然后查库比对,部署机器16核32G,jvm设置30g内存g1算法,年轻代给了25g,发现程序运行5分钟左右就会停止3分钟。
看了下gc的时间也不长,每次就0.06秒也就是60ms左右,但是不知道为啥程序停止所有线程3分钟,也没有发生full gc,ygc也就1分钟1次吧

原因:redis proxy 命令调用频率限制

群内分享问题2

使用@FeignClient 标注的一个接口,调用另外一个服务(url写死的),然后注入到controller里 结果启动就卡住(附 jstack 信息)

原因:死锁

建议

  • 多提点产品建议,多从业务的角度思考技术

文章分享

阿里工程师谈,什么是好的代码?