首页 > 解决方案 > 我们是否必须从 Zipkins 中的 WebClient 传递标头值

问题描述

我在客户端和服务器中使用 Spring Boot 和以下库,

dependencyManagement {
    imports {
        mavenBom "org.springframework.cloud:spring-cloud-dependencies:Finchley.SR2"
    }
}
 // Spring Cloud Sleuth
    compile group: 'org.springframework.cloud', name: 'spring-cloud-starter-sleuth', version: '2.0.1.RELEASE'
    compile group: 'org.springframework.cloud', name: 'spring-cloud-starter-zipkin', version: '2.0.1.RELEASE'

基于 spring 文档,“ https://cloud.spring.io/spring-cloud-sleuth/

运行这个应用程序,然后点击主页。您将在日志中看到 traceId 和 spanId 填充。如果此应用程序调用另一个应用程序(例如使用 RestTemplate),它将在标头中发送跟踪数据,如果接收器是另一个 Sleuth 应用程序,您将看到跟踪继续存在。

这将如何与 Spring5 Web 客户端一起使用?

标签: spring-cloud-sleuthzipkin

解决方案


它将以相同的方式工作。注入一个WebClientWebClientBuilder类型的bean就足够了。查看此示例https://github.com/spring-cloud-samples/sleuth-documentation-apps/blob/master/service1/src/main/java/io/spring/cloud/sleuth/docs/service1/Service2Client。爪哇

/**
 * @author Marcin Grzejszczak
 */
@Component
class Service2Client {

    private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());

    private final WebClient webClient;
    private final String serviceAddress;
    private final Tracer tracer;

    Service2Client(WebClient webClient,
            @Value("${service2.address:localhost:8082}") String serviceAddress,
            Tracer tracer) {
        this.webClient = webClient;
        this.serviceAddress = serviceAddress;
        this.tracer = tracer;
    }

    public String start() throws InterruptedException {
        log.info("Hello from service1. Setting baggage foo=>bar");
        Span span = tracer.currentSpan();
        String secretBaggage = ExtraFieldPropagation.get("baggage");
        log.info("Super secret baggage item for key [baggage] is [{}]", secretBaggage);
        if (StringUtils.hasText(secretBaggage)) {
            span.annotate("secret_baggage_received");
            span.tag("baggage", secretBaggage);
        }
        String baggageKey = "key";
        String baggageValue = "foo";
        ExtraFieldPropagation.set(baggageKey, baggageValue);
        span.annotate("baggage_set");
        span.tag(baggageKey, baggageValue);
        log.info("Hello from service1. Calling service2");
        String response = webClient.get()
                .uri("http://" + serviceAddress + "/foo")
                .exchange()
                .block()
                .bodyToMono(String.class).block();
        Thread.sleep(100);
        log.info("Got response from service2 [{}]", response);
        log.info("Service1: Baggage for [key] is [" + ExtraFieldPropagation.get("key") + "]");
        return response;
    }

    @NewSpan("first_span")
    String timeout(@SpanTag("someTag") String tag) {
        try {
            Thread.sleep(300);
            log.info("Hello from service1. Calling service2 - should end up with read timeout");
            String response = webClient.get()
                    .uri("http://" + serviceAddress + "/readtimeout")
                    .retrieve()
                    .onStatus(httpStatus -> httpStatus.isError(), clientResponse -> {
                        throw new IllegalStateException("Exception!");
                    })
                    .bodyToMono(String.class)
                    .block();
            log.info("Got response from service2 [{}]", response);
            return response;
        } catch (Exception e) {
            log.error("Exception occurred while trying to send a request to service 2", e);
            throw new RuntimeException(e);
        }
    }
}

推荐阅读