Sleuth源码解析

本文详细解析了Spring Sleuth的工作原理,包括span和trace id的概念,以及它们如何在微服务调用链中传递。重点分析了Sleuth如何处理日志打印、TracingFilter过滤器的拦截机制以及RestTemplate的拦截过程,确保链路追踪信息的完整传递。此外,还介绍了Sleuth的链路信息抽样策略,以优化性能。
摘要由CSDN通过智能技术生成

一、概念介绍

先说几个概念。
span:span是sleuth中最基本的工作单元,一个微服务收到请求后会创建一个span同时产生一个span id,span id是一个64位的随机数,sleuth将其转化为16进制的字符串,打印在日志里面。其对应的实现类是RealSpan。
trace id:在一个调用链条中,trace id是始终不变的,每经过一个微服务span id生成一个新的,所以通过trace id可以找出调用链上所有经过的微服务。trace id默认是64位,可以通过spring.sleuth.traceId128=true设置trace id为128位。调用链的第一个服务,其span id和trace id是同一个值。

sleuth目前并不是对所有调用访问都可以做链路追踪,它目前支持的有:rxjava、feign、quartz、RestTemplate、zuul、hystrix、grpc、kafka、Opentracing、redis、Reator、circuitbreaker、spring的Scheduled。

二、原理分析

1.处理日志打印

先来看一下后处理器TraceEnvironmentPostProcessor,TraceEnvironmentPostProcessor用于处理日志打印,如果应用程序不设置日志打印格式,那么该类会设置默认的打印格式,该类比较简单。

class TraceEnvironmentPostProcessor implements EnvironmentPostProcessor {
   

	private static final String PROPERTY_SOURCE_NAME = "defaultProperties";

	@Override
	public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
   
		Map<String, Object> map = new HashMap<>();
		// This doesn't work with all logging systems but it's a useful default so you see
		// traces in logs without having to configure it.
         //将打印的日志格式存入map中
		//日志打印一共四个内容:应用名、trace id、span id、是否发送到zipkin
		if (Boolean.parseBoolean(environment.getProperty("spring.sleuth.enabled", "true"))) {
   
			map.put("logging.pattern.level",
					"%5p [${spring.zipkin.service.name:" + "${spring.application.name:}},%X{traceId:-},%X{spanId:-}]");
		}
		addOrReplace(environment.getPropertySources(), map);
	}
	//下面这个方法用于将日志打印的格式设置到默认配置中
	//如果应用没有设置打印格式,则使用默认配置
	private void addOrReplace(MutablePropertySources propertySources, Map<String, Object> map) {
   
		MapPropertySource target = null;
		if (propertySources.contains(PROPERTY_SOURCE_NAME)) {
   
			PropertySource<?> source = propertySources.get(PROPERTY_SOURCE_NAME);
			if (source instanceof MapPropertySource) {
   
				target = (MapPropertySource) source;
				for (String key : map.keySet()) {
   
					if (!target.containsProperty(key)) {
   
						target.getSource().put(key, map.get(key));
					}
				}
			}
		}
		if (target == null) {
   
			target = new MapPropertySource(PROPERTY_SOURCE_NAME, map);
		}
		if (!propertySources.contains(PROPERTY_SOURCE_NAME)) {
   
			propertySources.addLast(target);
		}
	}

}

日志打印的设置完毕后,在来看SleuthLogAutoConfiguration,该类也是与日志打印相关的。该类的注释是:

 * {
   @link Configuration} that adds a {
   @link Slf4jScopeDecorator} that prints tracing information in the logs.

意思是SleuthLogAutoConfiguration将Slf4jScopeDecorator添加到配置中,可以在日志中打印追踪信息。从注释中可以看出SleuthLogAutoConfiguration只与Slf4j对接。下面来看一下代码:

	@Configuration(proxyBeanMethods = false)
	@ConditionalOnClass(MDC.class)
	@EnableConfigurationProperties(SleuthSlf4jProperties.cla
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值