gpt4 book ai didi

java - 同步并行 API 请求以从长时间运行的查询返回相同结果而无需多次执行的最佳实践是什么?

转载 作者:行者123 更新时间:2023-12-02 00:44:37 26 4
gpt4 key购买 nike

我正在开发一个由多个客户端调用的后端 Spring Boot 项目。其中一项功能是合并两个不同数据库的数据并返回结果,这可能需要长达 2 分钟的时间。

我希望能够并发调用此端点,等待已在运行的请求并返回相同的结果,而无需再次运行查询。

如下所示,我尝试在服务单例 bean 中设置一个 CompletableFuture 字段(我知道这是一种代码味道,因为单例服务 bean 应该是无状态的)。

//RestController
@Async
@GetMapping
public CompletableFuture<List<Foo>> getSyncedFoo() {
return service.syncFoo();
}

//ServiceImpl

private CompletableFuture<List<Foo>> syncTask;

@Override
@Async
@Transactional
public CompletableFuture<List<Foo>> syncFoo() {
if (this.syncTask == null || this.syncTask.isDone()) {
this.syncTask = CompletableFuture.supplyAsync(() -> {
// long running task
return new ArrayList<>();
});
}
return this.dbaseSyncTask;
}

我预计调用 API 端点的多个前端客户端会在大致相同的时间接收相同的响应,从而导致后端仅执行一次长时间运行的操作。

该操作实际上只执行了一次,但其中一个客户端收到了 503(服务不可用),而另一个客户端收到了预期的响应。

我怀疑这是由于 CompletableFuture 的共享使用造成的,但我不知道应该采取什么方法。 RxJava 对 Observable 策略有用吗?

最佳答案

目前我已经找到了一个实用的答案。

@Service
public class FooServiceImpl implements FooService {

private CompletableFuture<List<Foo>> syncFuture;
private Observable<List<Foo>> syncObservable;

@Override
public Single<List<Foo>> syncFoo() {
if (syncFuture == null || syncFuture .isDone()) {
syncFuture = syncFooAsync();
syncObservable = Observable.fromFuture(syncFuture).share();
}
return Single.fromObservable(syncObservable);
}

private CompletableFuture<List<Foo>> syncFooAsync() {
return CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(10_000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
return new ArrayList<>();
}
});
}

}

通过使用 RxJava 库,可以使用 Observable::share 方法将创建的 observable 多播到多个监听器,并且 @RestController 将愉快地处理返回的 Single(s)。

遗憾的是,它仍然使用单例中的状态,该状态由多个线程同时访问,因此我担心会出现并发问题,例如 Observable 完成,而新请求仍在创建新订阅的过程中。

因此,我不建议将此作为最佳实践,因此我不会将其标记为最终答案。

关于java - 同步并行 API 请求以从长时间运行的查询返回相同结果而无需多次执行的最佳实践是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57909849/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com