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纯模式下的手动上下文传播
- 如何使用WebFilter实现授权头检查 2022-01-01
- Spring Boot连接到使用仲裁器运行的MongoDB副本集 2022-01-01
- Java包名称中单词分隔符的约定是什么? 2022-01-01
- Eclipse 插件更新错误日志在哪里? 2022-01-01
- value & 是什么意思?0xff 在 Java 中做什么? 2022-01-01
- C++ 和 Java 进程之间的共享内存 2022-01-01
- Safepoint+stats 日志,输出 JDK12 中没有 vmop 操作 2022-01-01
- Jersey REST 客户端:发布多部分数据 2022-01-01
- 将log4j 1.2配置转换为log4j 2配置 2022-01-01
- 从 finally 块返回时 Java 的奇怪行为 2022-01-01
