代码之家  ›  专栏  ›  技术社区  ›  Mohamed Ibrahim Elsayed

为什么Spring不为关系数据库提供反应式(非阻塞)客户端?

  •  7
  • Mohamed Ibrahim Elsayed  · 技术社区  · 6 年前

    Vert.x MySQL and Postgres . 我知道Spring为一些NoSQL数据库(如Cassandra和Mongo)提供了反应式支持,但他们是否愿意为关系数据库提供同样的支持?

    2 回复  |  直到 6 年前
        1
  •  38
  •   mp911de    6 年前

    Spring框架背后的想法是什么?

    Spring框架是一个用于提高开发人员生产力的库,Spring的组合项目(如Spring数据、Spring安全、Spring云)也是如此。

    这些项目建立在通过JSR或JEP标准化的现有API之上,或者建立在已经证明是有用和广泛使用的库之上。Spring团队不为数据库或其他集成构建驱动程序,这取决于数据库/驱动程序供应商。

    WebFlux与Vert.x的比较

    Spring WebFlux是典型Spring模块的一个很好的例子。它建立在现有非阻塞服务器(通过netty、Undertow和Jetty项目反应堆)之上。WebFlux为非阻塞、反应式应用程序提供了运行时容器,利用Spring组件帮助开发和运行此类应用程序。

    Vert.x是集成环境的一个很好的例子,它提供了自己的底层实现。Vert.x是高度优化的,这样的生态系统需要优化的集成。Vert.x为各种数据库提供了自己的实现,并提供了在Vert.x上下文中运行良好的API,但这些API不是JDBC。

    作为 M-Razavi 前面已经提到过,Java使用JDBC与关系数据库集成,而JDBC具有阻塞性—要减轻JDBC的阻塞性,没有什么明智的办法。将JDBC调用卸载到 Executor Thread 池)的用途有限,因为池最终会被请求饱和)。TL;DR,没有API可用,我们可以在上面提供反应式关系数据库集成。

    那么有什么选择呢?

    M-Razavi ADBA 这是Oracle的一项倡议,旨在使用futures为Java中的异步数据库访问提供标准化API。ADBA的一切工作仍在进行中,ADBA的团队很高兴得到反馈。一群博士后正在做一项研究 Postgres ADBA driver 这可以用于第一次实验。

    有两个独立的驱动程序,例如 Reactiverse's reactive-pg-client . 这些驱动程序带有特定于供应商的API,并不真正适合Spring中更广泛的集成。我们需要提供额外的层来公开一个通用的API,而新的驱动程序不能仅仅插入到您的应用程序中,所以它是开箱即用的。拥有一个标准API允许可插拔性,因此拥有一个标准API有巨大的价值。

    R2DBC去救援?

    由于缺少标准API和驱动程序的不可用性,一个团队 Pivotal 开始研究反应式关系API,它非常适合反应式编程。他们想出了 R2DBC 表示反应式关系数据库连接。到目前为止,R2DBC是一个孵化器项目,用于评估可行性,并开始讨论驱动程序供应商是否对支持反应式/非阻塞式/异步驱动程序感兴趣。

    到目前为止,有三种驱动程序实现:

    R2DBC附带了一个API规范( r2dbc-spi )还有一个客户( r2dbc-client )这使得SPI可用于应用程序。我们开始在一条小路上探险 Spring Data R2DBC 通过数据库客户端和支持反应式存储库提供反应式API的集成。

    R2DBC及其生态系统还很年轻,需要进行实验和反馈,以收集用例,并查看反应式关系数据库集成是否有意义。

    DatabaseClient 用法:

    PostgresqlConnectionFactory connectionFactory = new PostgresqlConnectionFactory(…);
    
    DatabaseClient databaseClient = DatabaseClient.create(connectionFactory);
    
    Mono<Integer> count = databaseClient.execute()
                    .sql("INSERT INTO legoset (id, name, manual) VALUES($1, $2, $3)")
                    .bind("$1", 42055)
                    .bind("$2", "Description")
                    .bindNull("$3", Integer.class)
                    .fetch()
                    .rowsUpdated();
    
    Flux<Map<String, Object>> rows = databaseClient.execute()
                    .sql("SELECT id, name, manual FROM legoset")
                    .fetch()
                    .all();
    
        2
  •  10
  •   M-Razavi    6 年前


    实际上,Spring不负责为关系数据库提供无阻塞驱动程序。