Go 语言如果没有 ctx 传递,如何让 Trace ID 连贯传递呢?

2023-08-24 18:33:10 +08:00
 RedisMasterNode

RT 对于 Go (这类)没有 ThreadLocal 的语言,如果在服务方法调用之间缺漏了 ctx context.Context 的传递,Trace 的信息就无法传递下去。

通常来说对于平台、工具方来说(例如做 Trace 平台的人),想推动所有业务都去改造是相当困难的,请教一下了解的 V 友有什么办法能 “改善” 这种情况?

2550 次点击
所在节点    Go 编程语言
28 条回复
juzzle
2023-08-24 18:38:46 +08:00
用一个全局的 map ,key 是 goroutine 的唯一 Id ,value 是 RequestId
RedisMasterNode
2023-08-24 18:48:40 +08:00
@juzzle 我想了一下,这种方案可以在流量进来和流量出去的时候为(可能是空白的) ctx 补充 trace id ,但是印象中:
1. goroutine 没有唯一 ID ,之前了解到是故意这样设计的,不知道这种情况后来有没有改进
2. goroutine 之间的 trace id (可能)不容易传递

其实更想了解有没有一些无侵入,业务不感知的方案,能够达到同 goroutine 内补全 trace id 的效果(也就是可以不考虑问题 2 )
danbai
2023-08-24 19:01:41 +08:00
流量进来从堆栈拿 gid 出去再判断。这是魔法
danbai
2023-08-24 19:04:02 +08:00
Nazz
2023-08-24 19:04:56 +08:00
错误往上抛, 最后在中间件里面打印日志, 中间件里面可以访问 ctx 拿到 trace_id
RedisMasterNode
2023-08-24 19:09:04 +08:00
@Nazz 不是,哥们,那你这个 trace id 如何传递给下一个调用方呢?
RedisMasterNode
2023-08-24 19:10:57 +08:00
@danbai 记下魔法了,跟 1 楼其实是一样的。让我们猜猜业务方愿不愿意改 orz
JustSong
2023-08-24 19:16:08 +08:00
ctx 肯定要传啊😂
RedisMasterNode
2023-08-24 19:39:16 +08:00
@JustSong 这个东西就跟你和刚用 Redis 的人讨论可不可以使用 `KEYS` 一样的,不可能要求所有人立刻就知道这个东西重要不重要,可行与否,以及是否强制要传。等发现问题要改的时候往往是很难改得动,所以才会有很强的需求寻找如何优雅解决,而不是反推他们 “全部做对”(当然,全部做对肯定是最好最好的,不能因为难就否认)。
qloog
2023-08-24 19:52:27 +08:00
如果真不想全改,可以改一些有网络请求的组件,比如数据库,http client, redis 之类的,调用方只要升级核心组件即可,其他方法有好多其实也可以不用传递,毕竟没有网络请求。如果真想全部 trace, 建议加上 ctx, 长期来看还是有好处的,长痛不如短痛。
Nazz
2023-08-24 19:57:09 +08:00
@RedisMasterNode 得传递 ctx🌚
odirus
2023-08-24 20:00:35 +08:00
负责过类似的工作,手动传最稳定、可靠。要是担心的话在测试环境拦截出口、入口日志,分析是否有缺失的,有缺失的就告警出来。
kkhaike
2023-08-24 20:03:08 +08:00
使用 golangci-lint 的 contextcheck
https://golangci-lint.run/usage/linters/
https://github.com/kkHAIKE/contextcheck

这个是我写的😊
crysislinux
2023-08-24 20:13:26 +08:00
我倾向于显示传递,其实五楼推荐的办法是合适的,业务抛出业务相关的数据。中间件里输出信息的时候带上 reqId 。但是那种业务上要传的比如 tenant id 就没办法了。显式的传好了。
RedisMasterNode
2023-08-24 20:17:41 +08:00
@odirus
@kkhaike
谢谢两位朋友的建议,是个可以实施并且可以慢慢推的方式,可能落地起来还需要搭配一些宣讲一点点改善
RedisMasterNode
2023-08-24 20:22:33 +08:00
@crysislinux 五楼这个是不好的解决方案,视角很局限,我们想解决的是业务间传递的问题,而对于单一的服务,如果它自己有这样的需求,它肯定有办法独立解决,向上抛错误也好,补齐 ctx 也罢。

而在跨团队协作里面推动所有人完成一件事是比较困难的,一个单元没解决好,大家都没办法拿到最好的结果。

另外回归到方案本身,它是不太有实践价值的,试想你现在只在 request log 显示了 trace id ,其他所有日志都没 trace id ,你如何串联所有日志?那,这个 trace id 只出现在 request log 的意义又是什么,岂不是跟没有 id 一样了。
crysislinux
2023-08-24 20:52:48 +08:00
@RedisMasterNode 这个需求其实很普遍,一搜遍地都是,但是绝大部分框架都没提供一个方案,Java 我不是很熟悉不说了。nodejs 这边 async context 没进标准,nodejs 自己的 async hooks 可靠性不够,这个 feature 本身推进的也慢。可能业界并不觉得这是一个很值得解决的问题。。不过从业务的角度来说有这个东西确实会很方便。
matrix1010
2023-08-24 21:05:38 +08:00
teli
2023-08-24 22:11:23 +08:00
有个办法,拿到 goroutine 的 id ,不知道还有没有效
xiaocaiji111
2023-08-25 10:56:57 +08:00
如果想要 threadLocal 这种效果只能用魔法拿到 gid ,不过好像不太稳定
我们开始项目小也没有考虑过 traceId ,后面项目中函数参数不管用不用的到默认第一个就是 context ,再后来做电商生态等原因回归了 java 。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/968060

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX