如何解决GraphQL-Java上的ThreadLocals
我要在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();
}
}
}
还是我需要像这样在Threadpool中显式运行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的异步特性无关(我希望也能利用它),而是与通过fork-join pool
可能在请求之间混淆的用footLocals运行多个请求的可能的副作用有关。
解决方法
据我所知,graphql-java不使用其自己的线程池,而是依赖于应用程序。它使用将来的回调实现它的方式。说这是应用程序的当前状态。
具有线程本地存储TLS_1的线程T_1执行数据提取器DF_1。
Graphql-java引擎将同步回调附加到DF_1返回的将来。如果未返回future,则将结果包装在完整的future中,然后附加同步回调。由于回调是同步的,将来完成的线程将运行该回调。如果除T_1之外的任何其他线程完成了将来,则TLS_1将会丢失(除非将其复制到执行线程中)。一个示例是无阻塞HTTP I / O库,该库使用I / O线程来完成将来的响应。
在此链接中,作者对graphql-java库中的线程行为发表了更多评论
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。