spring-boot - Spring Cloud Sleuth如何开箱即用地在Webflux中传播MDC上下文,以便其内容可以记录在不同的线程中?

标签 spring-boot spring-cloud spring-webflux project-reactor spring-cloud-sleuth

我想知道Spring Cloud Sleuth如何在线程之间传播MDC上下文,从而使每个MDC参数都可用。

我已经阅读了https://simonbasle.github.io/2018/02/contextual-logging-with-reactor-context-and-mdc/,该文章建议使用订户上下文在线程之间传播MDC状态。

我需要从某些请求 header 中对其他参数进行类似的操作,因此我创建了将其放入当前线程的MDC并将其存储在订户上下文中的方法。但是,下一个继续执行的线程不可用。我应该以某种方式使用上下文中的值在新线程中再次调用MDC,但是如何?

@Slf4j
@RequiredArgsConstructor
@Order(Ordered.HIGHEST_PRECEDENCE)
public class ReactiveRequestCorrelationFilter implements WebFilter {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
        String principal = exchange.getRequest().getHeaders().getFirst("principal-header");
        MDC.put("principal", principal);
        return chain.filter(exchange)
                .subscriberContext(Context.of("principal", principal))
                .doOnTerminate(MDC::clear);
    }

}

看一下此 Controller 映射:
    @GetMapping(value = "/v1/departments", produces = MediaType.APPLICATION_JSON_VALUE)
    public Flux<Department> getDepartments() {
        log.info("getDepartaments");
        return webClient.get().uri("http://someService:8080/api/v1/departamentosFoo").retrieve().bodyToFlux(Departments.class)
                .doOnNext(dep -> log.info("found department {}", dep));
    }

它生成以下日志:
logging.pattern.console="%magenta([%thread]) [%X{traceId}] [%X{spanId}] [%X{principal}]  - %m%n"
[boundedElastic-2] [d0a916db8be0cbf7] [d0a916db8be0cbf7] []  - getDepartments
[boundedElastic-2] [d0a916db8be0cbf7] [fb2367685db70201] []  - found department Department(id=1, nombre=dep, fechaAlta=Fri Apr 24 14:16:20 CEST 2020, staff=1, tag=, empresa=true)
[reactor-http-nio-3] [d0a916db8be0cbf7] [d0a916db8be0cbf7] []  - found department Department(id=1, nombre=dep, fechaAlta=Fri Apr 24 14:16:20 CEST 2020, staff=1, tag=, empresa=true)

该请求从 react 器-http-nio线程开始,然后被切换到boundedElastic-2。如您所见,显示了traceId和spanId值,但未显示我放入过滤器中的值。 Sleuth如何设法将其上下文(traceId spanId)传播到其他线程中?

最佳答案

他们将Reactor Context和Reactor Hooks一起使用。
来自spring-cloud-sleuth的相关代码:link
更新:请注意对此进行了很多更改,请确保 check out 最新的实现,因为上面的链接指向旧提交。
其他几个可能有用的链接:

  • MDC with WebClient in WebMVC
  • How can the MDC context be used in the reactive Spring applications
  • MdcContextLifter
  • 关于spring-boot - Spring Cloud Sleuth如何开箱即用地在Webflux中传播MDC上下文,以便其内容可以记录在不同的线程中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61409047/

    相关文章:

    java - Spring:方法 getBean(String...) 如何根据输入字符串查找 bean?

    redis - spring boot 使用 redisTemplate 减少库存

    java - 微服务中实体类之间的关系

    java - Spring Cloud Stream KStream Consumer并发没有影响?

    java - com.sun.jersey.api.client.ClientHandlerException : java.net.ConnectException:连接被拒绝:在 Spring Boot 中连接

    spring-webflux - 如何使用 html 5 模式和 Spring webflux 处理页面刷新

    spring - 如何配置支持 session 的 MongoDB 集群?

    Spring Cloud的@RefreshScope导致 Controller 映射与其自身冲突

    java - Spring WebFlux + Security - 我们有 "remember-me"功能吗?

    java - WebFlux 通过证书进行身份验证?