千家信息网

Spring Cloud Sleuth Span的示例分析

发表于:2026-11-01 作者:千家信息网编辑
千家信息网最后更新 2026年11月01日,这篇文章主要介绍了Spring Cloud Sleuth Span的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。Span自定
千家信息网最后更新 2026年11月01日Spring Cloud Sleuth Span的示例分析

这篇文章主要介绍了Spring Cloud Sleuth Span的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。

Span自定义

感谢SpanInjector和SpanExtractor,您可以自定义spans的创建和传播方式。

目前有两种在进程之间传递跟踪信息的内置方式:

  • 通过Spring Integration

  • 通过HTTP

Span ids从Zipkin兼容(B3)头(Message或HTTP头)中提取,以启动或加入现有跟踪。跟踪信息被注入到任何出站请求中,所以下一跳可以提取它们。

与以前版本的Sleuth相比,重要的变化是Sleuth正在实施Open Tracing的TextMap概念。在Sleuth,它被称为SpanTextMap。基本上这个想法是通过SpanTextMap可以抽象出任何通信手段(例如消息,http请求等)。这个抽象定义了如何将数据插入到载体中以及如何从那里检索数据。感谢这样,如果您想要使用一个使用FooRequest作为发送HTTP请求的平均值的新HTTP库,那么您必须创建一个SpanTextMap的实现,它将调用委托给FooRequest检索和插入HTTP标头。

Spring Integration

对于Spring Integration,有2个接口负责从Message创建Span。这些是:

  • MessagingSpanTextMapExtractor

  • MessagingSpanTextMapInjector

您可以通过提供自己的实现来覆盖它们。

HTTP

对于HTTP,有2个接口负责从Message创建Span。这些是:

  • HttpSpanExtractor

  • HttpSpanInjector

您可以通过提供自己的实现来覆盖它们。

例

我们假设,而不是标准的Zipkin兼容的跟踪HTTP头名称

  • for trace id - correlationId

  • for span id - mySpanId

这是SpanExtractor的一个例子

static class CustomHttpSpanExtractor implements HttpSpanExtractor {        @Override public Span joinTrace(SpanTextMap carrier) {                Map map = TextMapUtil.asMap(carrier);                long traceId = Span.hexToId(map.get("correlationid"));                long spanId = Span.hexToId(map.get("myspanid"));                // extract all necessary headers                Span.SpanBuilder builder = Span.builder().traceId(traceId).spanId(spanId);                // build rest of the Span                return builder.build();        }}static class CustomHttpSpanInjector implements HttpSpanInjector {        @Override        public void inject(Span span, SpanTextMap carrier) {                carrier.put("correlationId", span.traceIdString());                carrier.put("mySpanId", Span.idToHex(span.getSpanId()));        }}
  • 14

  • 15

  • 16

  • 17

  • 18

  • 19

  • 20

  • 21

你可以这样注册:

@BeanHttpSpanInjector customHttpSpanInjector() {        return new CustomHttpSpanInjector();}@BeanHttpSpanExtractor customHttpSpanExtractor() {        return new CustomHttpSpanExtractor();}

    Spring Cloud为了安全起见,Sleuth不会将跟踪/跨度相关的标头添加到Http响应。如果您需要标题,那么将标题注入Http响应的自定义SpanInjector,并且可以使用以下方式添加一个使用此标签的Servlet过滤器:

    static class CustomHttpServletResponseSpanInjector extends ZipkinHttpSpanInjector {        @Override        public void inject(Span span, SpanTextMap carrier) {                super.inject(span, carrier);                carrier.put(Span.TRACE_ID_NAME, span.traceIdString());                carrier.put(Span.SPAN_ID_NAME, Span.idToHex(span.getSpanId()));        }}static class HttpResponseInjectingTraceFilter extends GenericFilterBean {        private final Tracer tracer;        private final HttpSpanInjector spanInjector;        public HttpResponseInjectingTraceFilter(Tracer tracer, HttpSpanInjector spanInjector) {                this.tracer = tracer;                this.spanInjector = spanInjector;        }        @Override        public void doFilter(ServletRequest request, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {                HttpServletResponse response = (HttpServletResponse) servletResponse;                Span currentSpan = this.tracer.getCurrentSpan();                this.spanInjector.inject(currentSpan, new HttpServletResponseTextMap(response));                filterChain.doFilter(request, response);        }         class HttpServletResponseTextMap implements SpanTextMap {                 private final HttpServletResponse delegate;                 HttpServletResponseTextMap(HttpServletResponse delegate) {                         this.delegate = delegate;                 }                 @Override                 public Iterator> iterator() {                         Map map = new HashMap<>();                         for (String header : this.delegate.getHeaderNames()) {                                map.put(header, this.delegate.getHeader(header));                         }                         return map.entrySet().iterator();                 }                 @Override                 public void put(String key, String value) {                        this.delegate.addHeader(key, value);                 }         }}

      你可以这样注册:

      @Bean HttpSpanInjector customHttpServletResponseSpanInjector() {        return new CustomHttpServletResponseSpanInjector();}@BeanHttpResponseInjectingTraceFilter responseInjectingTraceFilter(Tracer tracer) {        return new HttpResponseInjectingTraceFilter(tracer, customHttpServletResponseSpanInjector());}

      Zipkin中的自定义SA标签

      有时你想创建一个手动Span,将一个电话包裹到一个没有被检测的外部服务。您可以做的是创建一个带有peer.service标签的跨度,其中包含要调用的服务的值。下面你可以看到一个调用Redis的例子,它被包装在这样一个跨度里。

      org.springframework.cloud.sleuth.Span newSpan = tracer.createSpan("redis");try {        newSpan.tag("redis.op", "get");        newSpan.tag("lc", "redis");        newSpan.logEvent(org.springframework.cloud.sleuth.Span.CLIENT_SEND);        // call redis service e.g        // return (SomeObj) redisTemplate.opsForHash().get("MYHASH", someObjKey);} finally {        newSpan.tag("peer.service", "redisService");        newSpan.tag("peer.ipv4", "1.2.3.4");        newSpan.tag("peer.port", "1234");        newSpan.logEvent(org.springframework.cloud.sleuth.Span.CLIENT_RECV);        tracer.close(newSpan);}
      重要记住不要添加peer.service标签和SA标签!您只需添加peer.service。

      自定义服务名称

      默认情况下,Sleuth假设当您将跨度发送到Zipkin时,您希望跨度的服务名称等于spring.application.name值。这并不总是这样。在某些情况下,您希望为您应用程序中的所有spans提供不同的服务名称。要实现这一点,只需将以下属性传递给应用程序即可覆盖该值(foo服务名称的示例):

      spring.zipkin.service.name: foo
      • 1

      主机定位器

      为了定义与特定跨度对应的主机,我们需要解析主机名和端口。默认方法是从服务器属性中获取它。如果由于某些原因没有设置,那么我们正在尝试从网络接口检索主机名。

      如果您启用了发现客户端,并且更愿意从服务注册表中注册的实例检索主机地址,那么您必须设置属性(适用于基于HTTP和Stream的跨度报告)。

      spring.zipkin.locator.discovery.enabled: true
      • 1

      Span Data作为消息

      您可以通过将spring-cloud-sleuth-stream jar作为依赖关系来累加并发送跨越Spring Cloud Stream的数据,并为RabbitMQ或spring-cloud-starter-stream-kafka添加通道Binder实现(例如spring-cloud-starter-stream-rabbit)为Kafka)。通过将spring-cloud-sleuth-stream jar作为依赖关系,并添加RabbitMQ或spring-cloud-starter-stream-kafka的Binder通道spring-cloud-starter-stream-rabbit来实现{ 22 /} Stream的累积和发送范围数据。
      Kafka)。这将自动将您的应用程序转换为有效载荷类型为Spans的邮件的制作者。

      Zipkin消费者

      有一个特殊的便利注释,用于为Span数据设置消息使用者,并将其推入Zipkin SpanStore。这个应用程序

      @SpringBootApplication@EnableZipkinStreamServerpublic class Consumer {        public static void main(String[] args) {                SpringApplication.run(Consumer.class, args);        }}

        将通过Spring Cloud StreamBinder(例如RabbitMQ包含spring-cloud-starter-stream-rabbit)来收听您提供的任何运输的Span数据,Redis和Kafka的类似起始者) 。如果添加以下UI依赖关系

        io.zipkin.javazipkin-autoconfigure-ui
        • 1

        • 2

        然后,您将有一个Zipkin服务器,您的应用程序在端口9411上承载UI和API。

        默认SpanStore是内存中的(适合演示,快速入门)。对于更强大的解决方案,您可以将MySQL和spring-boot-starter-jdbc添加到类路径中,并通过配置启用JDBC SpanStore,例如:

        spring:  rabbitmq:    host: ${RABBIT_HOST:localhost}  datasource:    schema: classpath:/mysql.sql    url: jdbc:mysql://${MYSQL_HOST:localhost}/test    username: root    password: root# Switch this on to create the schema on startup:    initialize: true    continueOnError: true  sleuth:    enabled: falsezipkin:  storage:    type: mysql
        注意@EnableZipkinStreamServer还用@EnableZipkinServer注释,因此该过程还将公开标准的Zipkin服务器端点,以通过HTTP收集spans,并在Zipkin Web UI中进行查询。

        定制消费者

        也可以使用spring-cloud-sleuth-stream并绑定到SleuthSink来轻松实现自定义消费者。例:

        @EnableBinding(SleuthSink.class)@SpringBootApplication(exclude = SleuthStreamAutoConfiguration.class)@MessageEndpointpublic class Consumer {    @ServiceActivator(inputChannel = SleuthSink.INPUT)    public void sink(Spans input) throws Exception {        // ... process spans    }}
        注意上面的示例消费者应用程序明确排除SleuthStreamAutoConfiguration,因此它不会向其自己发送消息,但这是可选的(您可能实际上想要将消息跟踪到消费者应用程序中)。

        为了自定义轮询机制,您可以创建名称等于StreamSpanReporter.POLLER的PollerMetadata类型的bean。在这里可以找到这样一个配置的例子。

        @Configurationpublic static class CustomPollerConfiguration {        @Bean(name = StreamSpanReporter.POLLER)        PollerMetadata customPoller() {                PollerMetadata poller = new PollerMetadata();                poller.setMaxMessagesPerPoll(500);                poller.setTrigger(new PeriodicTrigger(5000L));                return poller;        }}

        度量

        目前Spring Cloud Sleuth注册了与spans相关的简单指标。它使用Spring Boot的指标支持
        来计算接受和删除的数量spans。每次发送到Zipkin时,接受的spans的数量将增加。如果出现错误,那么删除的数字spans将会增加。

        感谢你能够认真阅读完这篇文章,希望小编分享的"Spring Cloud Sleuth Span的示例分析"这篇文章对大家有帮助,同时也希望大家多多支持,关注行业资讯频道,更多相关知识等着你来学习!

        服务 应用程序 程序 跨度 应用 数据 跟踪 主机 名称 标签 消息 消费者 消费 示例 篇文章 检索 例子 可以通过 属性 接口 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 互联网科技公司华为 涨乐互联网科技 互联网科技会 盈实互联网科技 互联网科技金融公司 卓越科技(互联网 ) 广州互联网络科技有限公司 甘肃拓世互联网科技有限公司 新华互联网科技校企合作 互联网科技生活的内容 中盈科技互联网信息有限公司 武汉健翔互联网络科技有限公司 杭州壁岐互联网科技有限公司 洛阳昕诺飞互联网科技有限公司 天津腾达互联网科技有限公司 南博望互联网科技有限公司 广东工业互联网大赛深圳学泰科技 厦门江牛科技互联网 广西泛欧互联网科技有限公司 北京品多多互联网科技有限公司 互联网核心科技是什么 未来的互联网科技 北京禾田雨橡互联网科技 滨湖区互联网智能科技产品供应 银川新华互联网科技职业技术培训学校图片 互联网科技项目计划书材料类 中和天地互联网科技有限公司 互联网金融运营模式中的金融科技 中国互联网公司的科技投入 互联网时代高科技布局
        0