首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Spring Cloud Sleuth 是如何增加链路信息

Spring Cloud Sleuth 是如何增加链路信息

原创
作者头像
艳艳代码杂货店
修改2021-10-08 14:14:44
修改2021-10-08 14:14:44
59300
代码可运行
举报
运行总次数:0
代码可运行

通过之前的源码分析,我们知道,在最开始的 TraceWebFilter,我们将 Mono 封装成了一个 MonoWebFilterTrace,它的核心源码是:

代码语言:javascript
代码运行次数:0
运行
复制
@Override
public void subscribe(CoreSubscriber<? super Void> subscriber) {
	Context context = contextWithoutInitialSpan(subscriber.currentContext());
	Span span = findOrCreateSpan(context);
	//将 Span 放入执行上下文中,对于日志其实就是将链路信息放入 org.slf4j.MDC
	//日志的 MDC 一般都是 ThreadLocal 的 Map,对于 Log4j2 的实现类就是 org.apache.logging.log4j.ThreadContext,其核心 contextMap 就是一个基于 ThreadLocal 实现的 Map
	//简单理解就是将链路信息放入一个 ThreadLocal 的 Map 中,每个线程访问自己的 Map 获取链路信息
	try (CurrentTraceContext.Scope scope = this.currentTraceContext.maybeScope(span.context())) {
		//将实际的 subscribe 用 Span 所在的 Context 包裹住,结束时关闭 Span
		this.source.subscribe(new WebFilterTraceSubscriber(subscriber, context, span, this));
	}
	//在 scope.close() 之后,会将链路信息从  ThreadLocal 的 Map 中剔除
}

@Override
public Object scanUnsafe(Attr key) {
	if (key == Attr.RUN_STYLE) {
		//执行的方式必须是不能切换线程,也就是同步的
		//因为,日志的链路信息是放在 ThreadLocal 对象中,切换线程,链路信息就没了
		return Attr.RunStyle.SYNC; 
	}
	return super.scanUnsafe(key);
}

WebFilterTraceSubscriber 干了些什么呢?出现异常,以及 http 请求结束的时候,我们可能想将响应信息,异常信息记录进入 Span 中,就是通过这个类封装实现的。

经过 MonoWebFilterTrace 的封装,由于 Spring-WebFlux 处理请求,其实就是封装成我们上面得出的 Mono 之后进行 subscribe 处理的请求,所以这样,整个内部 Mono 的 publish 链路以及 subscribe 链路,就被 WebFilterTraceSubscriber 中的 scope 包裹起来了。只要我们自己不在 GatewayFilter 中转换成某些强制异步的 Mono 或者 Flux 导致切换线程,链路信息是不会丢失的。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档