一次解决服务升级之后出现异常的情况

287

背景描述

一个服务使用了 Prometheus 来进行数据采集,今天对这个项目的 metrics 使用进行了优化:将分散到各处的 metrics 放到同一个 go 文件,并将 metrics 的直接调用封装成了一个方法,这样看起来就整洁多了,当我高高兴兴地将代码打包成新版本,用几台机器先升上去之后,就在 grafana 看到了异常 span 数量急剧增多,这时候就慌了,不过幸亏平时回滚操作运用的很熟练,直接将所有机器一键回滚,万事大吉,然后就开始排查问题了。

排查思路

  1. 这个问题在第一次遇到的时候是修改了 分位数 统计之后发现的,当时猜测是依赖的包之间有冲突,因为之前输入了 go get -u all 更新全部包,在删除本地下载的包之后重新编译,问题解决
  2. 这次发现问题依旧,使用上述方法之后发现不管用,猜测是方法调用导致写入太慢,下游的服务接收日志有延迟,导致大量日志被丢失,换成前几个版本的代码进行测试:问题依旧
  3. 在下游的服务中搜索有问题的日志的 traceID ,发现同一个 traceIDspan 分布到好几个机器上,正常情况是相同的 traceIDspan 会发送到同一台机器,猜测是往 kafka 写入日志的时候出现了问题:客户端写入 kafka 的时候有个 balance 过程,代码中是自己手动实现了一个,猜测是这个出现了问题,换了包自带的 balance() 之后问题依旧
  4. 接着查看 kafka-go 的源码,在相关的地方进行日志的打印(这个是真的难搞),发现当设置的 balancer == nil 的时候,会默认调用轮询方法进行 balance,继续深入查看,新版本的 kafka-go (0.4.2)的 newWriter() 有问题,漏掉了 balancer 变量,导致配置里不管有没有赋值都为空,问题解决:直接使用 Writer{} 进行初始化,但是又有个问题,如果配置中的 brokers 值为多个,就会出现 bug,只有一个的时候就运行良好,其中排除了赋值可能出现的格式问题
  5. 最终的解决办法,回退到 0.3.6 版本,go mod 有个很坑的点:它会自己帮你升级到新的版本,所以要想保留在旧版本,那么就需要使用 replace