当前位置: 首页 > 知识库问答 >
问题:

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

权浩阔
2023-03-14

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

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

如下所示,我尝试在服务singleton bean中设置一个CompletableFuture字段(我知道这是一种代码味道,因为singleton服务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;
    }

我怀疑这是由于完全未来的共享使用,但我不知道我应该采取什么方法。RxJava对可观察的策略有什么用处吗?

共有1个答案

呼延晋
2023-03-14

我现在找到了一个实用的答案。

@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将很乐意处理返回的单个侦听器。

遗憾的是,它仍然在单例中使用state,而单例是由多个线程并发访问的,所以我担心并发问题的情况,比如在创建新订阅的过程中,新请求仍在可观察的完成。

 类似资料:
  • 问题内容: 我正在尝试执行上述程序,但为同一程序提供了不同的值。对于给定的字符串执行多次时,是否有任何方法可以获取相同的字节? 问题答案: 在这里,您不打印a的值。正如owlstead在注释中正确指出的那样,将在字节数组上调用Object.toString()方法。导致这种格式的输出: 如果要打印数组中的每个元素,则必须遍历它。 甚至更简单,请使用以下方法:

  • 当前的问题是,以下SQL查询在通过phpMyAdmin SQL页面运行时查找并返回结果,但在使用PDO通过PHP脚本运行时不返回任何结果。(如未找到匹配结果) 有问题的查询: 我怀疑这与排序规则或正在使用的字符集有关,因为不使用任何特殊字符会得到预期的结果。 数据库使用的是latin1_swedish_ci排序规则。我尝试将pdo::mysql_attr_init_command设置为“设置名称'

  • 我的查询如下: > 在我的应用程序中,我需要在计划中同时运行多个pyspark应用程序。是否有任何方法可以同时从spark驱动程序运行多个pyspark应用程序,从而创建单独的sparkcontext对象? 如果第一个查询的答案是否定的,那么我可以运行一个应用程序从驱动程序,另一个从执行程序,但我可以一次运行它。 null 配置:VM-1:Hadoop主节点、Spark驱动程序和执行程序、Mong

  • 在程序中有一部分代码,用于执行查询: 数据集 () 表应该有大约 20000 条记录(行计数),但在程序内部,它在调试模式下说只有 20 条记录。 我在同一个数据库表上单独运行了脚本,该表在 SQL Server 连接字符串中使用,但在 SQL Server Management Studio 中,它按预期返回了 20000 条记录。 该脚本看起来像: 它是相同的脚本文本,代码也会执行该文本。 有

  • 问题内容: 我有一个数据库,每天在其中创建一个表来记录流程实例。这些表标记为MESSAGE_LOG_YYYYMMDD 目前,我想针对所有这些表顺序执行相同的QUERY。我在下面编写了PL / SQL,但陷入了第10行。如何针对此处的所有表成功执行SQL语句? 问题答案: http://download.oracle.com/docs/cd/B10500_01/appdev.920/a96590/a

  • 问题内容: 假设有一个函数,应该执行一个HTTP请求并将其用于该请求。 如果在循环中调用if ,我希望下一个请求是在上一个完成之后执行的(串行执行,一个接一个)。为了不使回调和Promises混乱,我想使用async / await模式(与Babel.js一起编译以与Node 6+一起运行)。 但是,我不清楚如何等待响应对象进行进一步处理,以及如何作为以下结果返回它: 如果我使用 mocha 为H

  • 问题内容: 上面的语句返回3行。但是下面的语句仅返回2行。 我知道为什么会这样,但是有一种方法可以强制item_id 1返回两次? 我要退货的示例: id-> 1筹码€2.50 id-> 1筹码€2.50 id-> 2可口可乐€1.60 -------------------- 总计€6.60 问题答案: 您可以加入另一个表,例如 或者只是在您的应用程序中复制它们。 您实际上不需要做您所要的。

  • 我目前使用的是mysql 我有两个名为person和zim_list_id的表,这两个表都有超过200万行