时间进入二零二三年,今年是将一个辛苦的一年。今年将面临几方面的挑战,一个是将原先 部署在物理服务器上的数据都迁移上云。然后就是,加快培养几个团队新人,让他们尽快承 接目前的主要业务所涉及的服务,并且要求能够独立解决用户问题并对服务做出优化。这样 我就能将一些工作转交到他们名下,专注今年预估耗时较长的重要目标。还有就是,个人的 在技术和其他方面学习也到了一个攻坚阶段,这些方面决定了我未来 7~8 年的人生方向。
这一周,我的主要的精力在几个服务的日志框架与日志追踪的设计与规范上。首先是解决日 志追踪的问题,为了能够跨服务地对调用过程中产生的日志进行统一的追踪,需要现将 TraceId 统一。但是目前这几个服务 TraceId 的类型层次不齐,有使用 Long 类型的也有 用字符串的。并且,这些服务所使用的语言和技术栈也不一致。直接使用一些标准的分布式 追踪框架中的 TraceId 应该无法支持所有服务目前的情况,只能用在一些技术栈比较新的 服务上。 所以,从兼容性与改造的简洁性考虑,准备采用自定义生成的 Long 类型的数值 作为 TraceId 并且限定位数为 16 位。前四位以 99 开头,作为统一 TraceId 的特征,然 后剩余两位标识服务。接下来 4 位为当前的微秒数,最后的 8 位为两组四位随机数拼接。
虽然说这种 TraceId 并不能保证唯一性,但是在当前这种情况下是足够用的。如果服务为 Java 技术栈,生成 TraceId 需要充分考虑到线程竞争的情况,最好为每个线程分配一个随 机数发生器。或者,直接使用 TreadLocal。 Java 服务在处理请求时,会提取请求中的 TraceId。如果 TraceId 是 99 开头的,就不生成新的 TraceId 了。如果不是的话,按照 上述方式产生 TracId 并存储于 MDC 中。当遇到异步执行的时候,需要注意拷贝 MDC 中的 内容到旁线程,不然会丢失追踪信息。当需要调用下游服务时,需要将存储的 TaceId 传递 给下游服务。最后,当请求处理完毕时,需要清空 MDC,防止污染下一个请求的追踪信息。