cod*_*ent 5 spring-boot project-reactor spring-cloud spring-cloud-sleuth spring-webflux
我想知道 Spring Cloud Sleuth 如何在线程之间传播 MDC 上下文,从而使 MDC 参数可用。
我读过这篇文章https://simonbasle.github.io/2018/02/contextual-logging-with-reactor-context-and-mdc/建议使用订阅者上下文在线程之间传播 MDC 状态。
我需要对某些请求标头中的其他参数执行类似操作,因此我创建了将其放入当前线程的 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);
}
}
Run Code Online (Sandbox Code Playgroud)
看看这个控制器映射:
@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));
}
Run Code Online (Sandbox Code Playgroud)
它生成此日志:
logging.pattern.console="%magenta([%thread]) [%X{traceId}] [%X{spanId}] [%X{principal}] - %m%n"
Run Code Online (Sandbox Code Playgroud)
[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)
Run Code Online (Sandbox Code Playgroud)
请求从 reactor-http-nio 线程开始,然后切换到 boundedElastic-2。如您所见,显示了 traceId 和 spanId 值,但未显示我放入过滤器中的值。Sleuth 如何将其上下文 (traceId spanId) 传播到其他线程?
Mar*_*nyi 10
2023 年更新:发布了关于反应式系统中上下文传播当前状态的新文章系列:https://spring.io/blog/2023/03/28/context-propagation-with-project-reactor-1-the-基本
2021 年更新:请注意,对此进行了相当多的更改,请务必检查最新的实现,如下链接指向旧提交。
他们使用 Reactor Context 和 Reactor Hooks。spring-cloud-sleuth 的相关代码:链接
其他几个可能有用的链接:
做了一些研究,根据 Martin 在他的回答中提供的信息,我得出了如下结果:
更新过滤器:
@Slf4j
@RequiredArgsConstructor
@Order(Ordered.HIGHEST_PRECEDENCE + 6)
public class ReactiveRequestCorrelationFilter implements WebFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
return chain.filter(exchange)
.doOnSubscribe(s -> {
String principal = exchange.getRequest().getHeaders().getFirst("principal-header");
ExtraFieldPropagation.set("principal", principal);
});
}
}
Run Code Online (Sandbox Code Playgroud)
应用程序.yml
spring:
sleuth:
log:
slf4j:
whitelisted-mdc-keys: principal
baggage-keys: principal
Run Code Online (Sandbox Code Playgroud)
有了这个,我的自定义字段开始出现在日志中,Sleuth 负责设置它并从 MDC 中清除它:
[boundedElastic-2] [fadba73bf6447d02] [fadba73bf6447d02] [myprincipal] getDepartaments
Run Code Online (Sandbox Code Playgroud)
您不需要任何自定义即可使其工作。传播自定义 HTTP 标头所需要做的就是将它们告诉 Sleuth:
#The one is on by default
spring.sleuth.log.slf4j.enabled=true
spring.sleuth.propagation-keys=principal-header
spring.sleuth.log.slf4j.whitelisted-mdc-keys=principal-header
Run Code Online (Sandbox Code Playgroud)
(我使用的是属性版本,但同样的事情适用于 yaml)
然后在您的 logback 配置中使用
[%X{principal-header}]
Run Code Online (Sandbox Code Playgroud)
就是这样!
注意,我个人更喜欢-header从标题名称中删除该位。
| 归档时间: |
|
| 查看次数: |
4292 次 |
| 最近记录: |