Manual context propagation in Quarkus native mode(Quarkus纯模式下的手动上下文传播)
问题描述
我正在尝试使上下文传播在Quarkus纯模式下工作。
以下代码在JVM模式下按预期工作,但在本机模式下返回MDC value: null。
正如预期的那样,我的意思是:
对curl http://localhost:8080/thread-context的响应是MDC value: from-thread-context
@Inject
ManagedExecutor managedExecutor;
@Inject
ThreadContext threadContext;
private final Supplier<String> mdcValueSupplier =
() -> "MDC value: " + MDC.get("foo") + "
";
@GET
@Path("thread-context")
public String get() throws ExecutionException, InterruptedException {
MDC.put("foo", "from-thread-context");
Supplier<String> ctxSupplier = threadContext.contextualSupplier(mdcValueSupplier);
return managedExecutor.supplyAsync(ctxSupplier).get();
}
我已经创建了一个github repo,其中包含演示应用的完整代码和重现该问题的逐步说明。
存在依赖项io.quarkus:quarkus-smallrye-context-propagation。
Quarkus版本:1.9.2
问:是我的代码有问题,还是Quarkus有问题?
参考:Quarkus documentatin on context propagation
推荐答案
您的代码基本上很好[1],Quarkus在这方面也很好--但有两件事需要理解。
第一,您没有执行任何类型的手动上下文传播。您的代码是意外运行的,因为Quarkus使用JBoss LogManager作为记录器,并且它的MDC不是普通的ThreadLocal,它是一个InheritableThreadLocal。因此,它有时会传播上下文本身。但这并不是可以依赖的。例如,如果您执行实时重新加载(通过稍微修改代码并再次运行curl),它也将停止在JVM模式下工作。
第二,上下文传播的要点是将线程本地状态从一个线程转移到另一个线程,但这不是自动发生的。您可以通过调用相应的API自己执行该操作(即手动上下文传播),也可以实现ThreadContextProvider。
我简要介绍了MDC API(http://www.slf4j.org/api/org/slf4j/MDC.html),似乎可以使用getCopyOfContextMap和setContextMap实现基本的上下文传播。下面是我快速组装的一个实现--注意,我没有对代码进行太多测试:
import org.eclipse.microprofile.context.spi.ThreadContextProvider;
import org.eclipse.microprofile.context.spi.ThreadContextSnapshot;
import org.slf4j.MDC;
import java.util.Map;
public class MdcContextProvider implements ThreadContextProvider {
@Override
public ThreadContextSnapshot currentContext(Map<String, String> props) {
Map<String, String> propagate = MDC.getCopyOfContextMap();
return () -> {
Map<String, String> old = MDC.getCopyOfContextMap();
MDC.setContextMap(propagate);
return () -> {
MDC.setContextMap(old);
};
};
}
@Override
public ThreadContextSnapshot clearedContext(Map<String, String> props) {
return () -> {
Map<String, String> old = MDC.getCopyOfContextMap();
MDC.clear();
return () -> {
MDC.setContextMap(old);
};
};
}
@Override
public String getThreadContextType() {
return "SLF4J MDC";
}
}
如果您创建的META-INF/services/org.eclipse.microprofile.context.spi.ThreadContextProvider文件包含此类的完全限定名称,则MDC传播应该适用于您,即使是在本机中也是如此。
MDC所做的任何更改都不会传播回原始线程,因为SLF4J故意不提供对后备映射的访问,它只分发副本。这对你来说可能没问题,也可能不好。
[1]如果您将ManagedExecutor提交给ManagedExecutor,则Supplier您的Supplier不必将Supplier提交给ManagedExecutor,ManagedExecutor会自动执行此操作。
这篇关于Quarkus纯模式下的手动上下文传播的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:Quarkus纯模式下的手动上下文传播
基础教程推荐
- 多个组件的复杂布局 2022-01-01
- Java Swing计时器未清除 2022-01-01
- 如何在 Spring @Value 注解中正确指定默认值? 2022-01-01
- Java 实例变量在两个语句中声明和初始化 2022-01-01
- 不推荐使用 Api 注释的描述 2022-01-01
- 如何在 JFrame 中覆盖 windowsClosing 事件 2022-01-01
- 在 Java 中创建日期的正确方法是什么? 2022-01-01
- 验证是否调用了所有 getter 方法 2022-01-01
- 从 python 访问 JVM 2022-01-01
- 大摇大摆的枚举 2022-01-01
