程序员的知识教程库

网站首页 > 教程分享 正文

sleuth 代码结构及zipkin reporter-sender 分析

henian88 2024-08-17 16:07:43 教程分享 6 ℃ 0 评论

代码结构

spring sleuth 代码大致分为

  • dependencies,只定义了依赖jar
  • sleuth-zipkin 向zipkin发送span的 能力封装
  • starter-zipkin spring boot starter 定义封装,没有具体代码
  • strater-sleuth spring boot starter 定义封装,没有具体代码,如果span不是发送给zipkin,使用此starter就可以
  • core 核心代码,主要包括 annotation、各种注入(依赖brave)、log输出(主要是依托brave 及日志系统MDC)、propagation

spring-cloud-sleuth-2.1.3.RELEASE 的很多核心实现都依赖以下zipkin的包

  1. brave-5.7.0
  2. zipkin-reporter-java

可以说,如果要深入研究sleuth,就需要了解以上两个包

zipkin 的reporter

sleuth zipkin 的reporter主要依托ConditionalOnMissingBean及SpringBootCondition 实现可override及可配置型。

先从tracing 的创建来看,tracing默认创建是在TraceAutoConfiguration类中,具体函数如下

@Bean
	@ConditionalOnMissingBean
	// NOTE: stable bean name as might be used outside sleuth
	Tracing tracing(
			@Value("${spring.zipkin.service.name:${spring.application.name:default}}") String serviceName,
			Propagation.Factory factory, CurrentTraceContext currentTraceContext,
			Sampler sampler, ErrorParser errorParser, SleuthProperties sleuthProperties,
			@Nullable List<Reporter<zipkin2.Span>> spanReporters) {
		Tracing.Builder builder = Tracing.newBuilder().sampler(sampler)
				.errorParser(errorParser)
				.localServiceName(StringUtils.isEmpty(serviceName) ? DEFAULT_SERVICE_NAME
						: serviceName)
				.propagationFactory(factory).currentTraceContext(currentTraceContext)
				.spanReporter(new CompositeReporter(this.spanAdjusters,
						spanReporters != null ? spanReporters : Collections.emptyList()))
				.traceId128Bit(sleuthProperties.isTraceId128())
				.supportsJoin(sleuthProperties.isSupportsJoin());
		for (FinishedSpanHandler finishedSpanHandlerFactory : this.finishedSpanHandlers) {
			builder.addFinishedSpanHandler(finishedSpanHandlerFactory);
		}
		for (TracingCustomizer customizer : this.tracingCustomizers) {
			customizer.customize(builder);
		}
		return builder.build();
	}

先注意函数带有annotation ConditionalOnMissingBean,因此可以自定义一个Tracing bean来override。
其次看参数@Nullable List<Reporter<zipkin2.Span>> spanReporters,因此可以实现多个Reporter<zipkin2.Span> bean来实现一个span向多方报告,比如同时向zipkin kafka及写入logstat 日志。

@Bean
	public Reporter<Span> spanReporter() {
		return new Reporter<Span>() {
			@Override
			public void report(Span span) {
 				logger.info("customer report:" + span);
			}
		};
	}

默认reporter实现在类ZipkinAutoConfiguration中实现,具体代码如下

/**
	 * Zipkin reporter bean name. Name of the bean matters for supporting multiple tracing
	 * systems.
	 */
	public static final String REPORTER_BEAN_NAME = "zipkinReporter";

	/**
	 * Zipkin sender bean name. Name of the bean matters for supporting multiple tracing
	 * systems.
	 */
	public static final String SENDER_BEAN_NAME = "zipkinSender";

	@Bean(REPORTER_BEAN_NAME)
	@ConditionalOnMissingBean(name = REPORTER_BEAN_NAME)
	public Reporter<Span> reporter(ReporterMetrics reporterMetrics,
			ZipkinProperties zipkin, @Qualifier(SENDER_BEAN_NAME) Sender sender) {
		// historical constraint. Note: AsyncReporter supports memory bounds
		return AsyncReporter.builder(sender).queuedMaxSpans(1000)
				.messageTimeout(zipkin.getMessageTimeout(), TimeUnit.SECONDS)
				.metrics(reporterMetrics).build(zipkin.getEncoder());
	}

同样使用了ConditionalOnMissingBean,因此也可以通过自定义bean 实现 override,注意下实际实现类默认使BoundedAsyncReporter (来自zipkin reporter jar),具体span发送默认使先进入bounded queue,异步flush 发送。

发送span到bounded queue 或者调用自定义reporter 的report方法在 private static final class ListReporter implements Reporter<zipkin2.Span> 类,这个类在是public class TraceAutoConfiguration的inner 类,具体实现函数如下:

@Override
			public void report(Span span) {
				for (Reporter<zipkin2.Span> spanReporter : this.spanReporters) {
					try {
						spanReporter.report(span);
					}
					catch (Exception ex) {
						log.warn("Exception occurred while trying to report the span "
								+ span, ex);
					}
				}
			}

最后说下zipkin 三种reporter sender(rest、kafka、rabbitMQ)的实现,相关实现都在package org.springframework.cloud.sleuth.zipkin2.sender下,关键点如下;

  1. ZipkinKafkaSenderConfiguration,ZipkinRabbitSenderConfiguration,ZipkinRestTemplateSenderConfiguration 都实现@Bean(ZipkinAutoConfiguration.SENDER_BEAN_NAME)
  2. 如何实现3选一,依托@Conditional(ZipkinSenderCondition.class)来实现,即通过SpringBootCondition模式来实现根据配置项:spring.zipkin.sender.type 选择 bean实现类

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表