使用旧的线程局部值使Project Reactor Scheduler具有弹性

时间:2018-06-20 13:41:42

标签: spring-webflux project-reactor

我正在使用Spring Webflux通过Schedulers.elastic()从另一服务调用一项服务

Mono<Integer> anaNotificationCountObservable = wrapWithRetryForFlux(wrapWithTimeoutForFlux(
                notificationServiceMediatorFlux.getANANotificationCountForUser(userId).subscribeOn(reactor.core.scheduler.Schedulers.elastic())
        )).onErrorReturn(0);

在主线程中,我设置了一个InhertitableThreadLocal变量,在子线程中,我试图访问它,并且工作正常。

这是我用于存储threadlocal的类

@Component
public class RequestCorrelation {

    public static final String CORRELATION_ID = "correlation-id";

    private InheritableThreadLocal<String> id = new InheritableThreadLocal<>();

    public String getId() { 
       return id.get(); 
    }

    public void setId(final String correlationId) { 
       id.set(correlationId); 
    }

    public void removeCorrelationId() {
       id.remove();
    }
}

现在问题是第一次正常运行,这意味着我在threadlocal中设置的值将传递给其他服务。

但这也是第二次,它使用的是旧ID(在上次请求中生成)。

我尝试使用Schedulers.newSingle()而不是elastic(),但它可以正常工作。 因此,请考虑一下,因为elastic()正在重用线程,所以这就是为什么它无法清除/或正在重用的原因。

我应该如何解决问题。 我在过滤器中设置了本地线程,并在myfiler中清除了该线程

requestCorrelation.setId(UUID.randomUUID().toString());
chain.doFilter(req,res)
requestCorrelation.removeCorrelationId();

1 个答案:

答案 0 :(得分:1)

在利用反应堆管道时,切勿将资源或信息绑定到特定线程。 Reactor本身与时间表无关;使用您的库的开发人员可以选择在另一个调度程序上调度工作-如果您决定强制执行调度模型,则可能会失去性能优势。

相反,您可以将数据存储在reactor context内。这是一种类似于地图的结构,与订户相关,并且与计划安排无关。

这是诸如spring security和micrometer之类的项目存储通常属于threadlocal的信息的方式。