为啥 Spring 不为关系数据库提供响应式(非阻塞)客户端?
Posted
技术标签:
【中文标题】为啥 Spring 不为关系数据库提供响应式(非阻塞)客户端?【英文标题】:Why does Spring not provide reactive (non-blocking) clients for relational databases?为什么 Spring 不为关系数据库提供响应式(非阻塞)客户端? 【发布时间】:2019-04-14 03:48:44 【问题描述】:我使用Vert.x 工具包来创建响应式应用程序,并支持mysql and Postgres 等关系数据库。我知道 Spring 为 Cassandra 和 Mongo 等一些 NoSQL DB 提供响应式支持,但他们愿意为关系 DB 提供相同的支持吗?
【问题讨论】:
Spring WebFlux 和 rxjava2-jdbc by Robert B Roeser link.medium.com/6ONWHPEsKR ***.com/questions/42299455/… baeldung.com/rxjava-jdbc github.com/davidmoten/rxjava2-jdbc 异步 JDBC 仍在处理中:blogs.oracle.com/java/… 【参考方案1】:Spring 框架背后的想法是什么?
Spring Framework 是一个用于提高开发人员生产力的库,Spring 的投资组合项目(例如 Spring Data、Spring Security、Spring Cloud)也是如此。
这些项目建立在现有 API 之上,这些 API 要么通过 JSR 或 JEP 标准化,要么建立在已证明有用且广泛使用的库之上。 Spring 团队不会为数据库或其他集成构建驱动程序,这取决于数据库/驱动程序供应商。
WebFlux 与 Vert.x 相比
Spring WebFlux 是典型 Spring 模块的一个很好的例子。它建立在现有的非阻塞服务器(Project Reactor 通过 netty、Undertow 和 Jetty)之上。 WebFlux 为非阻塞、反应式应用程序提供运行时容器,利用 Spring 组件帮助开发和运行此类应用程序。
Vert.x 是一个很好的集成环境示例,它提供了自己的低级实现。 Vert.x 进行了高度优化,这样的生态系统需要优化的集成。 Vert.x 为各种数据库提出了自己的实现,并提供了在 Vert.x 上下文中运行良好的 API,但这些 API 不是 JDBC。
关系数据库 API
正如M-Razavi 已经提到的,Java 使用 JDBC 与关系数据库集成,而 JDBC 具有阻塞特性——没有任何明智的做法可以减轻 JDBC 的阻塞特性。将 JDBC 调用卸载到 Executor
(通常是 Thread
池)的用处有限,因为池最终会因请求而饱和)。 TL;DR,没有可用的 API,我们可以在此基础上提供反应式关系数据库集成。
那么有哪些选择呢?
M-Razavi 已经提到ADBA,这是 Oracle 的一项举措,旨在为使用期货的 Java 异步数据库访问提供标准化 API。 ADBA 中的一切仍在进行中,ADBA 背后的团队很高兴收到反馈。一群 Postgres 人正在开发一个 Postgres ADBA driver,它可以用于第一次实验。
但是,ADBA 是未来的目标,我预计我们不会看到 ADBA 与 Java 12 一起发布。
有几个独立的驱动程序,例如Reactiverse's reactive-pg-client。这些驱动程序带有特定于供应商的 API,并不真正适合 Spring 中更广泛的集成。我们需要提供额外的层来公开一个通用的 API,而且新的驱动程序不能只是插入到您的应用程序中,因此它可以开箱即用™。拥有标准 API 可实现可插拔性,因此拥有标准 API 具有巨大价值。
R2DBC 救援?
由于缺乏标准 API 和驱动程序不可用,Pivotal 的一个团队开始研究一种非常适合反应式编程目的的反应式关系 API。他们提出了R2DBC,它代表反应式关系数据库连接。截至目前,R2DBC 是一个孵化器项目,旨在评估可行性并开始讨论驱动程序供应商是否对支持反应式/非阻塞/异步驱动程序感兴趣。
截至目前,共有三种驱动实现:
PostgreSQL H2 Microsoft SQL ServerR2DBC 附带一个 API 规范 (r2dbc-spi
) 和一个客户端 (r2dbc-client
),使 SPI 可用于应用程序。我们开始探索Spring Data R2DBC 集成,它通过数据库客户端和支持响应式存储库提供响应式 API。
R2DBC 及其生态系统还很年轻,需要进行实验和反馈以收集用例并了解反应式关系数据库集成是否有意义。
现在,你可以通过 Spring Data 消费 R2DBC,下面的 sn -p 显示 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();
【讨论】:
你能更新你的答案添加 R2DBC MySQL 支持吗?干杯 同时,ADBA项目已停止。【参考方案2】:Spring WebFlux 是创建非阻塞 REST 应用程序的好方法。开始使用 WebFlux 时遇到的一个问题是 JDBC,因为 JDBC 是阻塞的。像 Cassandra 或 Couchbase 这样的新学校数据库具有非阻塞驱动程序。在 Couchbase 的案例中,它的驱动程序使用 RXJava。在为数据库创建异步驱动程序方面付出了一些努力,Oracle 也在努力创建 ADBA。不幸的是,现在还处于早期阶段,如果您想与 JVM 上的 SQL 数据库通信,您会遇到阻塞驱动程序。 实际上,Spring 不负责为关系数据库提供非阻塞驱动程序。
【讨论】:
我不知道为什么这被否决了,但我也读到 jdbc 本质上是阻塞的。 你是对的,但我想知道,因为我提到了 Vert.x 等其他工具为关系数据库提供异步客户端。 大多数时候,这些工具将口红放在阻塞的数据库客户端上(在与连接池大小相同的托管线程池中执行它)并将其称为反应式。见例如。 ***.com/questions/50432154/… 嗯...似乎是真的,我以前不知道。 我已经读到将 Reactor 与阻塞数据库(例如 JDBC)一起使用是没有用的,因为数据库在检索数据时会保持线程等待。你有什么想法?以上是关于为啥 Spring 不为关系数据库提供响应式(非阻塞)客户端?的主要内容,如果未能解决你的问题,请参考以下文章
为啥在 Spring 响应式 Mongo 中订阅有效而阻止无效?