spring-cloud-sleuth - 我们是否必须从 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 客户端一起使用?
解决方案
它将以相同的方式工作。注入一个WebClient
或WebClientBuilder
类型的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);
}
}
}
推荐阅读
- android - 应用内帐单检查 skuid
- php - 在 php slim 3 中列出所有带有组的路由
- c++ - 函数局部枚举声明与 ADL 的交互
- python - 更改 Django 的 cookie 域设置会如何导致零星的 CSRF 失败?
- nginx - nginx SSL 连接失败
- python - python嵌入C++,函数返回shared_ptr(pybind11/boost_python)
- r - 匹配所有出现的术语 R 的正则表达式函数
- facebook - 如何使用 Facebook 登录配置 ASP.NET 身份 - 严格重定向
- angular - 如何使用 lodash _.filter() 过滤 Firestore 集合?
- android - Android Things SIM700E LTE + GPS 驱动程序