当前位置: 首页 > 知识库问答 >
问题:

使用SpringWebFlux实现跟踪id

唐阳晖
2023-03-14

我希望为每个请求生成唯一的traceId,并将其传递给所有服务。在SpringMVC中,使用MDC上下文并将traceId放在头文件中相当容易,但在反应式堆栈中,由于ThreadLocal,它根本不起作用。

一般来说,我希望使用单个traceId记录我拥有的每个服务上的每个请求和响应,该traceId可以识别整个系统中的特定操作。

我试图根据文章创建自定义过滤器:https://azizulhaq-ananto.medium.com/how-to-handle-logs-and-tracing-in-spring-webflux-and-microservices-a0b45adc4610但它似乎不起作用。我目前的解决方案只有日志响应和TraceId在发出请求后丢失,所以没有on响应。让我们试着想象有两个服务:service1service2。下面我试着勾勒出它应该如何工作。

它应该如何工作

  1. 客户端-

它实际上是如何工作的

  1. 客户端-

这是我的做法

@Component
public class TraceIdFilter implements WebFilter {

    private static final Logger log = LoggerFactory.getLogger(TraceIdFilter.class);

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
        Map<String, String> headers = exchange.getRequest().getHeaders().toSingleValueMap();
        return Mono.fromCallable(() ->  {
            final long startTime = System.currentTimeMillis();

            return new ServerWebExchangeDecorator(exchange) {
                @Override
                public ServerHttpRequest getRequest() {
                    return new RequestLoggingInterceptor(super.getRequest(), false);
                }

                @Override
                public ServerHttpResponse getResponse() {
                    return new ResponseLoggingInterceptor(super.getResponse(), startTime, false);
                }
            };
        }).contextWrite(context -> {
            var traceId = "";
            if (headers.containsKey("X-B3-TRACEID")) {
                traceId = headers.get("X-B3-TRACEID");
                MDC.put("X-B3-TraceId", traceId);
            } else if (!exchange.getRequest().getURI().getPath().contains("/actuator")) {
                traceId = UUID.randomUUID().toString();
                MDC.put("X-B3-TraceId", traceId);
            }

            Context contextTmp = context.put("X-B3-TraceId", traceId);
            exchange.getAttributes().put("X-B3-TraceId", traceId);


            return contextTmp;
        }).flatMap(chain::filter);

    }


}

Github:https://github.com/Faelivrinx/kotlin-spring-boot

有什么现有的解决方案吗?

共有1个答案

罗允晨
2023-03-14

在SpringWebFlow中,您不再拥有ThreadLocal,但是您对每个链请求都有一个独特的上下文。您可以附加一个跟踪到这个上下文如下:

@Component
public class TraceIdFilter implements WebFilter {

    private static final Logger log = LoggerFactory.getLogger(TraceIdFilter.class);

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {

        return chain.filter(exchange)
                .subscriberContext(
                        ctx -> {
                            .....
                            var traceId = UUID.randomUUID().toString();
                            return   ctx.put("X-B3-TraceId", traceId);
                            .....
                        }
                );

    }


}

现在,服务中的链将在上下文中具有此属性。您可以使用静态方法Mono.subscriberContext()从服务中检索它。例如,您可以通过这种方式获取traceId

Mono.subscriberContext()
    .flaMap(ctx -> {
       .....
       var traceId = ctx.getOrDefault("traceId", null);
       .....
    )
 类似资料:
  • (我想一个选择是重新修改我们的Feign接口,使其具有@feignclient,并重新修改所有自定义拦截器、编码器等的应用方式,但最终这可能是一项很大的工作,风险也很大。) 我是否需要做一个特殊的请求拦截器来手动地注入这些(例如,从一个自动连线的跟踪器)?有没有一种干净的方法(或现有的类)来做到这一点?

  • 跟踪行为控制着 Entity Framework Core 是否会在其变更跟踪器里维持实体实例的信息。如果实体是被跟踪的,任何检测到的该实体的变更都将在 SaveChanges() 时持久化到数据库中。Entity Framework Core 还会对已跟踪的、之前已加载到 DbContext 实例中的查询和实体进行相互的导航属性装配。 提示 你可以在 GitHub 上查阅当前文章涉及的代码样例。

  • 我最近将我的项目从spring boot 1.4.1、spring cloud Sleuth 1.1.0、spring cloud Zipkin 1.1.0升级到spring boot 1.5.3、spring cloud Sleuth 1.2.0、spring cloud Zipkin 1.2.0。 在最新版本的spring cloud Sleuth中,他们添加了“错误”标签,一旦出现任何异常,

  • 我试图使用grpc客户端的StackDrive/谷歌云跟踪定义在https://github.com/googleapis/googleapis/blob/master/google/devtools/cloudtrace/v1/trace.proto 我正在发送协议 但我得到的唯一回报是这个例外: 同样,我尝试了以下ListTrace请求 并获得: 我对API非常陌生,所以我不知道我在这里做错了

  • 问题内容: 在程序快要结束时,我希望将类的所有实例中的特定变量加载到字典中。 例如: 假设实例数量会有所不同,我希望将Foo()的每个实例的x dict加载到新的dict中。我该怎么办? 我在SO中看到的示例假定一个已经具有实例列表。 问题答案: 跟踪实例的一种方法是使用类变量: 在程序结束时,您可以像下面这样创建字典: 只有一个列表:

  • Trace 事件提供了一种机制,可以集中由 V8,Node 核心, 以及用户代码生成的跟踪信息。 启动 Node.js 应用时添加 --trace-events-enabled 标记,可以启用 Tracing. 可以通过在 --trace-event-categories 标记后跟一个用逗号分隔的类别名称列表, 来指定特定的跟踪记录集合。 node 和 v8 默认启用。 node --trace-