You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

Spring Boot 1.5中如何排除Feign调用/客户端的Sleuth链路追踪

嘿,针对你在Spring Boot 1.5微服务里遇到的Feign链路追踪过滤需求,我整理了几个适配这个版本栈的实用方案,你可以根据自己的场景选择:

方案1:自定义注解+拦截器,灵活跳过指定方法/客户端

这种方式能让你精准控制单个Feign方法或整个客户端是否追踪,灵活性最高。

步骤1:定义跳过追踪的注解

先创建一个自定义注解,用来标记不需要追踪的Feign方法或客户端:

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface SkipTrace {
}

步骤2:自定义Feign拦截器

我们需要编写一个拦截器,优先于Sleuth的默认拦截器执行,检查当前调用是否标记了@SkipTrace,如果是就跳过追踪逻辑:

import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;

@Component
@Primary // 确保这个拦截器优先于Sleuth默认拦截器加载
public class SkipTraceFeignInterceptor implements RequestInterceptor {

    // 注入Sleuth的默认追踪拦截器,用于正常请求的处理
    private final RequestInterceptor sleuthDelegate;

    public SkipTraceFeignInterceptor(RequestInterceptor sleuthDelegate) {
        this.sleuthDelegate = sleuthDelegate;
    }

    @Override
    public void apply(RequestTemplate template) {
        // 获取当前Feign调用的方法和目标客户端类信息
        Method targetMethod = template.metadata().method();
        Class<?> clientClass = template.metadata().targetType();

        // 检查方法或类上是否有@SkipTrace注解
        if (targetMethod.isAnnotationPresent(SkipTrace.class) || clientClass.isAnnotationPresent(SkipTrace.class)) {
            // 跳过追踪,直接返回,不注入Zipkin追踪头
            return;
        }
        // 正常调用Sleuth的拦截器处理追踪逻辑
        sleuthDelegate.apply(template);
    }
}

步骤3:标记需要跳过的Feign调用

现在你可以在整个Feign客户端或者单个方法上添加@SkipTrace注解:

// 整个客户端的所有调用都跳过追踪
@SkipTrace
@FeignClient(name = "unimportant-service")
public interface UnimportantFeignClient {
    @GetMapping("/api/data")
    String getUnimportantData();
}

// 仅单个方法跳过追踪,其他方法正常追踪
@FeignClient(name = "mixed-service")
public interface MixedFeignClient {
    @SkipTrace
    @GetMapping("/api/skip")
    String getSkippedData();

    @GetMapping("/api/trace")
    String getTracedData();
}

方案2:给指定Feign客户端使用原始Client,完全绕过Sleuth包装

如果你想让某个Feign客户端的所有调用都不被追踪,可以直接给它配置原始的Feign Client,跳过Sleuth的包装逻辑。

步骤1:创建Feign配置类

编写一个配置类,返回原始的Feign Client实例:

import feign.Client;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class NoTraceFeignConfig {

    @Bean
    public Client feignClient() {
        // 返回Feign默认的Client,不经过Sleuth的TraceFeignClient包装
        return new Client.Default(null, null);
    }
}

步骤2:给目标Feign客户端引用这个配置

在Feign客户端的configuration属性里指定刚才的配置类:

@FeignClient(name = "unimportant-service", configuration = NoTraceFeignConfig.class)
public interface UnimportantFeignClient {
    @GetMapping("/api/data")
    String getUnimportantData();
}

这样这个客户端的所有请求都不会生成追踪Span,完全绕过Sleuth的处理。

方案3:通过自定义采样器过滤(适合全局规则)

如果你的需求是基于服务名或URI等全局规则过滤,可以自定义Sleuth的采样器,决定哪些Span不发送到Zipkin。不过要注意,这种方式仍然会创建Span,只是不提交到Zipkin,性能上不如前两种方案。

import org.springframework.cloud.sleuth.Sampler;
import org.springframework.cloud.sleuth.Span;
import org.springframework.stereotype.Component;

@Component
public class CustomTraceSampler implements Sampler {

    @Override
    public boolean isSampled(Span span) {
        // 根据远程服务名判断是否跳过采样
        String remoteService = span.remoteServiceName();
        if ("unimportant-service".equals(remoteService)) {
            return false; // 不采样,不发送到Zipkin
        }
        // 其他请求保持默认采样逻辑(这里直接返回true,你也可以结合默认采样器)
        return true;
    }
}

注意事项

  • 因为你用的是Spring Boot 1.5,对应的Spring Cloud版本大概率是Dalston或Edgware系列,上述方案都是适配这些版本的。如果遇到template.metadata()不可用的情况,可以尝试通过ThreadLocal在调用前标记是否跳过追踪。
  • 方案1中的@Primary注解必须加,否则自定义拦截器可能不会优先执行。
  • 方案2的配置类要确保只被目标Feign客户端引用,不要全局生效,否则所有Feign调用都会跳过追踪。

内容的提问来源于stack exchange,提问作者slippery

火山引擎 最新活动