首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Resilience4j上下文传播程序无法传播线程本地域值

Resilience4j上下文传播程序无法传播线程本地域值
EN

Stack Overflow用户
提问于 2021-04-27 21:06:17
回答 2查看 199关注 0票数 0

我正在尝试将我的断路器代码从Hystrix迁移到Resilience4j。通信是在两个应用程序之间进行的,其中一个应用程序是包含java代码本身中所有弹性4j配置的工件,第二个应用程序是微服务直接使用它。

有一个RequestId在微服务中生成,并传播到工件上下文,在那里它被打印到日志中。使用Hystrix时,它工作得非常好,但是自从我转移到resilience之后,我的请求Id就变成了空。

下面是我对批量头部和上下文传播器的配置:

代码语言:javascript
复制
ThreadPoolBulkheadConfig bulkheadConfig = ThreadPoolBulkheadConfig.custom()
            .maxThreadPoolSize(maxThreadPoolSize)
            .coreThreadPoolSize(coreThreadPoolSize)
            .queueCapacity(queueCapacity)
            .contextPropagator(new DummyContextPropagator())
            .build();

    // Bulk Head Registry
    ThreadPoolBulkheadRegistry bulkheadRegistry = ThreadPoolBulkheadRegistry.of(bulkheadConfig);

    // Create Bulk Head
    ThreadPoolBulkhead bulkhead = bulkheadRegistry.bulkhead(name, bulkheadConfig);

虚拟上下文传播器:

代码语言:javascript
复制
public class  DummyContextPropagator implements ContextPropagator {
private static final Logger log = LoggerFactory.getLogger( DummyContextPropagator.class);

@Override
public Supplier<Optional<Object>> retrieve() {
    return () -> (Optional<Object>) get();
}

@Override
public Consumer<Optional<Object>> copy() {
    return (t) -> t.ifPresent(e -> {
        clear();
        put(e);
    });
}

@Override
public Consumer<Optional<Object>> clear() {
    return (t) ->  DummyContextHolder.clear();
}

public static class  DummyContextHolder {

    private static final ThreadLocal threadLocal = new ThreadLocal();

    private  DummyContextHolder() {
    }

    public static void put(Object context) {
        if (threadLocal.get() != null) {
            clear();
        }
        threadLocal.set(context);
    }

    public static void clear() {
        if (threadLocal.get() != null) {
            threadLocal.set(null);
            threadLocal.remove();
        }
    }

    public static Optional<Object> get() {
        return Optional.ofNullable(threadLocal.get());
    }
}
}

然而,似乎什么都不起作用,所以我可以获得RequestId。

我做的每件事都是正确的,还是有其他方法可以做到这一点?

EN

回答 2

Stack Overflow用户

发布于 2021-05-26 11:53:51

我认为当你在子线程中时,你应该从父线程中获取参数,在hystrix中使用command-model来修饰callabletask

在resilience4j中,我认为你可以像这样修复它:

代码语言:javascript
复制
@Resource
DispatcherServlet dispatcherServlet;

@PostConstruct
public void changeThreadLocalModel() {
    dispatcherServlet.setThreadContextInheritable(true);
}
票数 0
EN

Stack Overflow用户

发布于 2021-05-26 14:35:04

我发现当您使用"dispatcherServlet.setThreadContextInheritable(true);“时,我的上一个答案可能会导致一些问题

它可能会污染您的自定义线程池的threadlocalmap;

这是我的最终解决方案,它只适用于resilience4j;

代码语言:javascript
复制
@Resource
Resilience4jBulkheadProvider resilience4jBulkheadProvider;

@PostConstruct
public void concurrentThreadContextStrategy() {
    ThreadPoolBulkheadConfig threadPoolBulkheadConfig = ThreadPoolBulkheadConfig.custom().contextPropagator(new CustomInheritContextPropagator()).build();
    resilience4jBulkheadProvider.configureDefault(id -> new Resilience4jBulkheadConfigurationBuilder()
            .bulkheadConfig(BulkheadConfig.ofDefaults()).threadPoolBulkheadConfig(threadPoolBulkheadConfig)
            .build());
}


private static class CustomInheritContextPropagator implements ContextPropagator<RequestAttributes> {

    @Override
    public Supplier<Optional<RequestAttributes>> retrieve() {
        //  give requestcontext to reference from threadlocal;
        //  this method call by web-container thread, such as tomcat, jetty,or undertow, depends on what you used;
        return () -> Optional.ofNullable(RequestContextHolder.getRequestAttributes());
    }

    @Override
    public Consumer<Optional<RequestAttributes>> copy() {
        // load requestcontex into real-call thread
        // this method call by resilience4j bulkhead thread;
        return requestAttributes -> requestAttributes.ifPresent(context -> {
            RequestContextHolder.resetRequestAttributes();
            RequestContextHolder.setRequestAttributes(context);
        });
    }

    @Override
    public Consumer<Optional<RequestAttributes>> clear() {
        // clean requestcontext finally ;
        // this method call by resilience4j bulkhead thread;
        return requestAttributes -> RequestContextHolder.resetRequestAttributes();
    }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67283655

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档