带有 Webflux 的 JDBC - 如何分派到容器线程

2024-02-09

我正在使用 webflux 进行小型概念验证。在我的应用程序的一部分中,我想与一个数据库进行通信(通过 JDBC),该数据库是阻塞的并且不太适合反应器。尽管如此,对于这个概念验证,我正在考虑以下技巧:

  1. 定义一个专用的线程池(我们称之为DBThreadPool) as ExecutorService具有等于​​ JDBC 连接池大小的固定线程数。将该池包装在 Reactor Scheduler 中(名为dbScheduller)
  2. 包装阻塞调用(如 Reactor 文档中所述)并将其安排在dbScheduller:

    public Flux<DbUser> allUsers() {
        return Mono.fromCallable(() -> <jdbcQueryHere>)
            .flatMapIterable(Function.identity())
            .log("DB-OPER").subscribeOn(dbScheduller);
    }
    
  3. 查询完成后,我想处理返回的Flux<DbUser>使用一些反应式运算符,但在容器线程这样我就可以释放数据库线程。根据 Reactor 文档,可以通过以下方式完成publishOn方法:

    public Mono<ServerResponse> allUsers(ServerRequest request) {
        return ServerResponse.ok()
        .contentType(APPLICATION_STREAM_JSON)
        .body(
            usersDao.allUsers()
            .publishOn(<netty Thread pool as scheduller>)
            .map(<some function>)
            .filter(<some predicate>), 
        DbUser.class);
    }
    

您认为这是一种可行的方法(直到我们获得数据库的非阻塞驱动程序)吗?

如何访问容器(netty)线程池,以便利用其线程之一来完成(对数据库中的数据进行后处理并写入响应)HTTP 请求?

我知道我可以单独使用数据库线程(通过省略publishOn)用于完成 HTTP 请求,但我想尽快释放它(以便它可以由也需要访问数据库的另一个请求重用),并将其余工作(这可能会很耗时)留给netty 托管线程(它可以是最初执行我的线程)handler method).


您认为这是一种可行的方法(直到我们获得数据库的非阻塞驱动程序)吗?

我个人确实认为这是一个有效的方法。BUT许多其他人(他们中的大多数人比我更了解反应式编程)怀疑这是一个好主意。

您的替代方案:

  • 为阻塞的数据库调用编写一个单独的服务并使用WebClient https://docs.spring.io/spring-framework/docs/5.0.0.M3/javadoc-api/org/springframework/web/client/reactive/WebClient.html

    优点:阻塞和非阻塞代码的清晰分离。

    缺点:多了一个服务边界,包括网络。

  • 为您的阻塞数据库调用编写一个单独的服务,包括它自己的用户界面。

    优点:没有服务间通信。

    缺点:减少应用程序中实际响应的百分比。

  • 如果您想在此服务中保留阻止代码,这是正确的方法。

如何访问容器(netty)线程池?

如果您只是渲染响应,则不需要,因为这会自动发生在 netty 线程上。

如果你有实际的转变要做,没有现成的东西可以做到这一点。我想人们可以使用一些 Netty API 并实现一个Scheduler基于此。但我对 Netty 的了解还不够,无法帮助解决这个问题。

为了回答后续问题,我问自己:

但这不是一个巨大的遗漏吗?

The publishOn方法并不是真正为此目的。他们的用例更多地用于例如在管道末端需要使用特定线程或线程池的 Swing 应用程序。

我个人的感觉是 Reactor 应该有这样的东西,但开发人员目前并不相信这是一个好主意。因此,如果您认为这对您的应用程序确实有意义,我建议:开票 https://jira.spring.io/browse/SPR/?selectedTab=com.atlassian.jira.jira-projects-plugin:components-panel并准备好论证你的观点。要么你成功,要么我们都知道为什么这是一个坏主意:-)

还要别的吗?

很高兴您问如果您在反应性管道中的线程池上执行阻塞操作,您应该考虑如何处理当线程池(或相应资源)过载时的情况,即它处理事件的速度比生成事件的速度慢。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

带有 Webflux 的 JDBC - 如何分派到容器线程 的相关文章

随机推荐