Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does Spring not provide reactive (non-blocking) clients for relational databases?

I've used Vert.x toolkit for creating reactive applications with support for relational DBs like MySQL and Postgres. I know Spring provides reactive support for some NoSQL DBs like Cassandra and Mongo but are they willing to provide the same for relational DBs?

like image 466
Mohamed Elsayed Avatar asked Nov 11 '18 01:11

Mohamed Elsayed


People also ask

Is Spring boot reactive programming?

Reactive Microservices With Spring BootOne is based on a Servlet API with Spring MVC and Spring Data constructs. The other is a fully reactive stack that takes advantage of Spring WebFlux and Spring Data's reactive repositories. In both cases, Spring Security has you covered with native support for both stacks.

Are Spring boots non-blocking?

Spring WebFlux supports reactive backpressure and Servlet 3.1+ with its non-blocking I/O. Hence, it can be run on Netty, Undertow, Jetty, Tomcat, or any Servlet 3.1+ compatible server.

How is Spring WebFlux non-blocking?

Spring Webflux does not block a thread to handle each request, because no thread is kept waiting for something to be done (e.g. waiting for an answer from a database). As written in 1., it can be blocked while waiting for an answer from a database or from another service that is called via HTTP.

Is Spring MVC reactive?

Spring-mvc supports a reactive client but once the processes reach servlet api, they work in blocking mode.


2 Answers

What's the idea behind the Spring Framework?

Spring Framework is a library to improve developer productivity, and so are Spring's portfolio projects such as Spring Data, Spring Security, Spring Cloud.

These projects build on top of existing APIs which are either standardized through a JSR or a JEP or on top of libraries that have proved to be useful and widely used. The Spring team does not build drivers for databases or other integrations, that's up to the database/driver vendors.

WebFlux compared to Vert.x

Spring WebFlux is an good example for a typical Spring module. It builds on top of existing non-blocking servers (Project Reactor via netty, Undertow, and Jetty). WebFlux provides a runtime container for non-blocking, reactive applications leveraging Spring components to assist in developing and running such applications.

Vert.x is an excellent example of an integrated environment that provides its own low-level implementations. Vert.x is heavily optimized and such an eco-system requires optimized integrations. Vert.x came up with own implementations for various databases and provides APIs that work well in a Vert.x context but these APIs are not JDBC.

Relational Database APIs

As M-Razavi already mentioned, Java uses JDBC to integrate with relational databases and JDBC is of a blocking nature – there's nothing sensible one could do about to mitigate the blocking nature of JDBC. Offloading JDBC calls to an Executor (typically Thread pool) is limited in its usefulness as the pool eventually saturates with requests). TL;DR, there's no API available on top of which we could provide a reactive relational database integration.

So what are the options?

M-Razavi already mentioned ADBA that is an initiative from Oracle to provide a standardized API for asynchronous database access in Java using futures. Everything in ADBA is still work in progress and the team behind ADBA is happy to get feedback. A bunch of Postgres folks is working on a Postgres ADBA driver that can be used for first experiments.

However, ADBA is a future goal and I expect that we don't see ADBA released with Java 12.

There are a couple of independent drivers such as Reactiverse's reactive-pg-client. These drivers come with a vendor-specific API and aren't really suited for a broader integration in Spring. We would need to provide additional layers to expose a common API, and new drivers couldn't be just plugged into your application so it works-out-of-the-box™. Having a standard API allows pluggability, so there's huge value in having a standard API.

R2DBC to the rescue?

Lacking a standard API and the non-availability of drivers, a team at Pivotal started to investigate on a reactive relational API that would be an ideal fit for reactive programming purposes. They came up with R2DBC which stands for Reactive Relational Database Connectivity. As of now, R2DBC is an incubator project to evaluate the feasibility and to start discussions whether driver vendors are interested at all in supporting reactive/non-blocking/asynchronous drivers.

As of now, there are three driver implementations:

  • PostgreSQL
  • H2
  • Microsoft SQL Server

R2DBC comes with an API specification (r2dbc-spi) and a client (r2dbc-client) that makes the SPI usable for applications. We started exploring on a Spring Data R2DBC integration that provides reactive APIs through a database client and by supporting reactive repositories.

R2DBC and its eco-system are still young and ask for experiments and feedback to collect use cases and to see whether a reactive relational database integration would make sense.

Right now, you can consume R2DBC through Spring Data and the following snippet shows DatabaseClient usage:

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();
like image 161
mp911de Avatar answered Oct 22 '22 17:10

mp911de


Spring WebFlux is a great way to create a non-blocking REST application. One issue that you run into when start working with WebFlux is JDBC, because JDBC is blocking. New school databases like Cassandra or Couchbase have non-blocking drivers. In Couchbase’s case its driver uses RXJava. There is some effort going into creating asynchronous drivers for databases, as well as Oracle’s effort to create ADBA. Unfortunately, these are early days, and if you want to talk to a SQL database on the JVM you’re stuck with a blocking driver.
Actually, Spring is not responsible for providing a none blocking driver for relational databases.

like image 30
M-Razavi Avatar answered Oct 22 '22 16:10

M-Razavi