【发布时间】:2020-11-25 01:50:51
【问题描述】:
我在 GraphQL 上公开了一个旧版 Web 应用,但这个 Web 应用使用 Threadlocals(以及其他 Apache-Shiro)。
由于 GraphQL-java 似乎使用 fork-join pool 进行并发,我担心我需要走多远才能确保我的 ThreadLocals 仍然可以安全工作。
阅读文档和源代码,似乎大部分并发是由返回 CompletableFuture 的 DataFetchers 实现的,我无法确定这是否是唯一的并发源(我认为不是)以及是否DataFetchers 本身是从 fork-join pool 调用的
那么将我的DataFetcher 包装在设置并清除 ThreadLocals 的委托中是否安全?或者这仍然有被抢占并继续在fork-join pool 中的另一个线程上的风险,例如:
static class WrappedDataFetcher implements DataFetcher<Object> {
private DataFetcher<?> realDataFetcher;
WrappedDataFetcher(DataFetcher<?> realDataFetcher) {
this.realDataFetcher = realDataFetcher;
}
@Override
public Object get(DataFetchingEnvironment dataFetchingEnvironment) throws Exception {
try {
setThreadLocalsFromRequestOrContext(dataFetchingEnvironment);
return realDataFetcher.get(dataFetchingEnvironment);
} finally {
clearTreadLocals();
}
}
}
或者我是否需要在线程池中显式运行我的 DataFetchers,例如:
static class WrappedDataFetcherThreadPool implements DataFetcher<Object> {
private DataFetcher<?> wrappedDataFetcher;
private ThreadPoolExecutor executor;
WrappedDataFetcherThreadPool(DataFetcher<?> realDataFetcher, ThreadPoolExecutor executor) {
// Wrap in Wrapper from previous example to ensure threadlocals in the executor
this.wrappedDataFetcher = new WrappedDataFetcher(realDataFetcher);
this.executor = executor;
}
@Override
public Object get(DataFetchingEnvironment dataFetchingEnvironment) throws Exception {
Future<?> future = executor.submit(() -> wrappedDataFetcher.get(dataFetchingEnvironment));
return future.get(); //for simplicity / clarity of the question
}
}
我认为第二个解决了我的问题,但感觉有点矫枉过正,我担心性能。但我认为第一个风险是先发制人的。
如果有更好的方法来处理这个问题,我也很想听听。
注意:这与 GraphQL 的异步特性无关(我希望也能利用这一点),而是与运行多个请求的潜在副作用有关p>
【问题讨论】:
标签: java fork-join graphql-java