Skip to content

Commit

Permalink
Merge pull request quarkusio#17675 from cescoffier/reactive-doc-part-1
Browse files Browse the repository at this point in the history
Start rewriting the reactive documentation
  • Loading branch information
cescoffier authored Jun 4, 2021
2 parents 5f7622e + 14103fc commit 2c069ce
Show file tree
Hide file tree
Showing 24 changed files with 753 additions and 800 deletions.
3 changes: 1 addition & 2 deletions docs/src/main/asciidoc/cassandra.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -413,8 +413,7 @@ link:https://javadoc.io/doc/com.datastax.oss.quarkus/cassandra-quarkus-client/la
interface] gives you access to a series of reactive methods that integrate seamlessly with Quarkus
and its reactive framework, Mutiny.

TIP: If you're not familiar with Mutiny, read the
link:https://quarkus.io/guides/getting-started-reactive[Getting Started with Reactive guide] first.
TIP: If you are not familiar with Mutiny, please check xref:mutiny-primer.adoc[Mutiny - an intuitive reactive programming library].

Let's rewrite our application using reactive programming with Mutiny.

Expand Down
3 changes: 2 additions & 1 deletion docs/src/main/asciidoc/context-propagation.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ With this, you will get context propagation for ArC, RESTEasy and transactions,
[TIP]
.Mutiny
====
This section uses Mutiny reactive types, if you're not familiar with them, read the link:getting-started-reactive#mutiny[Getting Started with Reactive guide] first.
This section uses Mutiny reactive types.
If you are not familiar with Mutiny, check xref:mutiny-primer.adoc[Mutiny - an intuitive reactive programming library].
====

Let's write a REST endpoint that reads the next 3 items from a link:kafka[Kafka topic], stores them in a database using
Expand Down
980 changes: 197 additions & 783 deletions docs/src/main/asciidoc/getting-started-reactive.adoc

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/src/main/asciidoc/getting-started.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -493,7 +493,7 @@ Furthermore, users can supply a custom banner by placing the banner file in `src
This guide covered the creation of an application using Quarkus.
However, there is much more.
We recommend continuing the journey with the link:building-native-image[building a native executable guide], where you learn about creating a native executable and packaging it in a container.
If you are interested in reactive, we recommend the link:getting-started-reactive[Getting started with reactive guide], where you can see how to implement reactive applications with Quarkus.
If you are interested in reactive, we recommend the xref:getting-started-reactive.adoc[Getting Started with Reactive guide], where you can see how to implement reactive applications with Quarkus.

In addition, the link:tooling[tooling guide] document explains how to:

Expand Down
2 changes: 1 addition & 1 deletion docs/src/main/asciidoc/grpc-getting-started.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ To override it, set the `quarkus.generate-code.grpc.scan-for-imports` property i
Now that we have the generated classes let's implement our _hello_ service.

With Quarkus, implementing a service requires to implement the generated service interface based on Mutiny, a Reactive Programming API integrated in Quarkus, and expose it as a CDI bean.
Learn more about Mutiny on the link:getting-started-reactive#mutiny[Getting Started with Reactive guide].
Learn more about Mutiny on the xref:mutiny-primer.adoc[Mutiny guide].
The service class must be annotated with the `@io.quarkus.grpc.GrpcService` annotation.

=== Implementing a service
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 2 additions & 1 deletion docs/src/main/asciidoc/mailer.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,8 @@ NOTE: The two APIs are equivalent feature-wise. Actually the `Mailer` implementa
[TIP]
.Mutiny
====
The reactive mailer uses Mutiny reactive types, if you're not familiar with them, read the link:getting-started-reactive#mutiny[Getting Started with Reactive guide] first.
The reactive mailer uses Mutiny reactive types.
If you are not familiar with Mutiny, check xref:mutiny-primer.adoc[Mutiny - an intuitive reactive programming library].
====

To send a simple email, proceed as follows:
Expand Down
3 changes: 2 additions & 1 deletion docs/src/main/asciidoc/mongodb-panache.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -786,7 +786,8 @@ and when defining your repositories: `ReactivePanacheMongoRepository` or `Reacti
[TIP]
.Mutiny
====
The reactive API of the MongoDB with Panache uses Mutiny reactive types, if you're not familiar with them, read the link:getting-started-reactive#mutiny[Getting Started with Reactive guide] first.
The reactive API of the MongoDB with Panache uses Mutiny reactive types.
If you are not familiar with Mutiny, check xref:mutiny-primer.adoc[Mutiny - an intuitive reactive programming library].
====

The reactive variant of the `Person` class will be:
Expand Down
3 changes: 2 additions & 1 deletion docs/src/main/asciidoc/mongodb.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,8 @@ It is recommended to switch to the `io.quarkus.mongodb.reactive.ReactiveMongoCli
[TIP]
.Mutiny
====
The MongoDB reactive client uses Mutiny reactive types, if you're not familiar with them, read the link:getting-started-reactive#mutiny[Getting Started with Reactive guide] first.
The MongoDB reactive client uses Mutiny reactive types.
If you are not familiar with Mutiny, check xref:mutiny-primer.adoc[Mutiny - an intuitive reactive programming library].
====

[source,java]
Expand Down
340 changes: 340 additions & 0 deletions docs/src/main/asciidoc/mutiny-primer.adoc

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion docs/src/main/asciidoc/neo4j.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,8 @@ To make life a bit easier, we will use https://smallrye.io/smallrye-mutiny/[Muti
[TIP]
.Mutiny
====
The following example uses Mutiny reactive types, if you're not familiar with them, read the link:getting-started-reactive#mutiny[Getting Started with Reactive guide] first.
The following example uses Mutiny reactive types.
If you are not familiar with Mutiny, check xref:mutiny-primer.adoc[Mutiny - an intuitive reactive programming library].
====

Add the following dependency to your `pom.xml`:
Expand Down
193 changes: 193 additions & 0 deletions docs/src/main/asciidoc/quarkus-reactive-architecture.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
////
This guide is maintained in the main Quarkus repository
and pull requests should be submitted there:
https://github.com/quarkusio/quarkus/tree/main/docs/src/main/asciidoc
////
= Quarkus Reactive Architecture

include::./attributes.adoc[]

Quarkus is reactive.
It's even more than this: Quarkus unifies reactive and imperative programming.
You don't even have to choose: you can implement reactive components and imperative components then combine them inside the very **same** application.
No need to use different stacks, tooling or APIs; Quarkus bridges both worlds.

This page will explain what we mean by _Reactive_ and how Quarkus enables it.
We will also discuss execution and programming models.
Finally, we will list the Quarkus extensions offering reactive facets.

== What is _Reactive_?

The _Reactive_ word is overloaded and associated with many concepts such as back-pressure, monads, or event-driven architecture.
So, let's clarify what we mean by _Reactive_.

_Reactive_ is a set of principles and guidelines to build responsive distributed systems and applications.
The https://www.reactivemanifesto.org/[Reactive Manifesto] characterizes _Reactive Systems_ as distributed systems having four characteristics:

1. Responsive - they must respond in a timely fashion
2. Elastic - they adapt themselves to the fluctuating load
3. Resilient - they handle failures gracefully
4. Asynchronous message passing - the component of a reactive system interact using messages

image::reactive-systems.png[alt=Reactive Systems Pillars]

In addition to this, the https://principles.reactive.foundation/[Reactive Principles white paper] lists a set of rules and patterns to help the construction of reactive systems.

== Reactive Systems and Quarkus

Reactive System is an architectural style that can be summarized by: distributed systems done right.
Relying on asynchronous message passing helps enforce the loose coupling (both in terms of space and time) between the different components.
You send messages to virtual destinations. The receiver can be anywhere or can even not be when the message is sent.
The elasticity pillar allows scaling up and down individual components according to the load.
Elasticity also provides redundancy, which helps with the resilience pillar.
Failures are inevitable.
Components forming a reactive system must handle them gracefully, avoid cascading failures, and self-adapt themselves.

A responsive system can continue to handle the request while facing failures and under fluctuating load.
Quarkus has been tailored for that.
It provides features that will help you design, implement and operate reactive systems.

== Reactive Applications

Quarkus is not only going to help you build reactive systems.
It's also going to make sure that each constituent enforces the reactive principles and is highly efficient.

Efficiency is essential, especially in the Cloud and in containerized environments.
Resources, such as CPU and memory, are shared among multiple applications.
Greedy applications that consume lots of memory are inefficient and put penalties on sibling applications.
You may need to request more memory, CPU, or bigger virtual machines.
It either increases your monthly Cloud bill or decreases your deployment density.

I/O is an essential part of almost any modern system.
Whether it is to call a remote service, interact with a database, or send messages to a broker, there are all I/O-based operations.
Efficiently handling them is critical to avoid greedy applications.
For this reason, Quarkus uses non-blocking I/O, which allows a low number of OS threads to manage many concurrent I/Os.
As a result, Quarkus applications allow for higher concurrency, use less memory, and improve the deployment density.

== How does Quarkus enable Reactive?

Under the hood, Quarkus has a reactive engine.
This engine, powered by Eclipse Vert.x and Netty, handles the non-blocking I/O interactions.

image::quarkus-reactive-core.png[Quarkus Reactive Core]

Quarkus extensions and the application code can use this engine to orchestrate I/O interactions, interact with databases, send and receive messages, and so on.

== Reactive execution model

While using non-blocking I/O has tremendous benefits, it does not come for free.
Indeed, it introduces a new execution model quite different from the one used by classical frameworks.

Traditional applications use blocking I/O and an imperative (sequential) execution model.
So, in an application exposing an HTTP endpoint, each HTTP request is associated with a thread.
In general, that thread is going to process the whole request and the thread is tied up serving only that request for the duration of that request.
When the processing requires interacting with a remote service, it uses blocking I/O.
The thread is blocked, waiting for the result of the I/O.
While that model is simple to develop with (as everything is sequential), it has a few drawbacks.
To handle concurrent requests, you need multiple threads, so, you need to introduce a worker thread pool.
The size of this pool constrains the concurrency of the application.
In addition, each thread has a cost in terms of memory and CPU.
Large thread pools result in greedy applications.

image::blocking-threads.png[alt=Imperative Execution Model and Worker Threads]

As we have seen above, non-blocking I/O avoids that problem.
A few threads can handle many concurrent I/O.
If we go back to the HTTP endpoint example, the request processing is executed on one of these I/O threads.
Because there are only a few of them, you need to use them wisely.
When the request processing needs to call a remote service, you can't block the thread anymore.
You schedule the I/O and pass a continuation, i.e., the code to execute once the I/O completes.

image::reactive-thread.png[alt=Reactive Execution Model and I/O Threads]

This model is much more efficient, but we need a way to write code to express these continuations.

== Reactive Programming Models

The Quarkus architecture, based on non-blocking I/O and message passing, allows multiple supporting reactive development models that are all different in how they express continuations.
The two main ways to write reactive code with Quarkus are:

* Reactive Programming with https://smallrye.io/smallrye-mutiny[Mutiny], and
* Coroutines with Kotlin

First, https://smallrye.io/smallrye-mutiny[Mutiny] is an intuitive, event-driven reactive programming library.
With Mutiny, you write event-driven code.
Your code is a pipeline receiving events and processing them.
Each stage in your pipeline can be seen as a continuation, as Mutiny invokes them when the upstream part of the pipeline emits an event.

The Mutiny API has been tailored to improve the readability and maintenance of the codebase.
Mutiny provides everything you need to orchestrate asynchronous actions, including concurrent execution.
It also offers a large set of operators to manipulate individual events and streams of events.

[TIP]
Find more info about Mutiny and its usage in Quarkus on xref:mutiny-primer.adoc[Mutiny support documentation].

Co-routines are a way to write asynchronous code sequentially.
It suspends the execution of the code during I/O and registers the rest of the code as the continuation.
Kotlin coroutines are great when developing in Kotlin and only need to express sequential compositions (chain of co-dependent asynchronous tasks).

== Unification of Imperative and Reactive

Changing your development model is not simple.
It requires relearning and restructuring code in a non-blocking fashion.
Fortunately, you don't have to do it!

Quarkus is inherently reactive thanks to its reactive engine.
But, you, as an application developer, don't have to write reactive code.
Quarkus unifies reactive and imperative.
It means that you can write traditional blocking applications on Quarkus.
But how do you avoid blocking the I/O threads?
Quarkus implements a https://en.wikipedia.org/wiki/Proactor_pattern[proactor pattern] that switches to worker thread when needed.

image::proactor-pattern.png[The proactor pattern in Quarkus]

Thanks to hints in your code (such as the `@Blocking` and `@NonBlocking` annotations), Quarkus extensions can decide when the application logic is blocking or non-blocking.
If we go back to the HTTP endpoint example from above, the HTTP request is always received on an I/O thread.
Then, the extension dispatching that request to your code decides whether to call it on the I/O thread, avoiding thread switches, or on a worker thread.This decision depends on the extension.
For example, the RESTEasy Reactive extension uses the @Blocking annotation to determine if the method needs to be invoked using a worker thread, or if it can be invoked using the I/O thread.

Quarkus is pragmatic and versatile.You decide how to develop and execute your application.
You can use the imperative way, the reactive way, or mix them, using reactive on the parts of the application under high concurrency.

[#quarkus-extensions-enabling-reactive]
== Quarkus Extensions enabling Reactive

Quarkus offers a large set of reactive APIs and features.This section lists the most important, but it's not an exhaustive list.
Quarkus adds new features in every release, and the https://github.com/quarkiverse[Quarkiverse] proposes many extensions enabling _Reactive_.

=== HTTP

* RESTEasy Reactive: an implementation of JAX-RS tailored for the Quarkus architecture.
It follows a reactive-first approach but allows imperative code using the `@Blocking` annotation.
* Reactive Routes: a declarative way to register HTTP routes directly on the Vert.x router used by Quarkus to route HTTP requests to methods.
* Reactive Rest Client: allows consuming HTTP endpoints.Under the hood, it uses the non-blocking I/O features from Quarkus.
* Qute - the Qute template engine exposes a reactive API to render templates in a non-blocking manner.

=== Data

* Hibernate Reactive: a version of Hibernate ORM using asynchronous and non-blocking clients to interact with the database.
* Hibernate Reactive with Panache: provide active record and repository support on top of Hibernate Reactive.
* Reactive PostgreSQL client: An asynchronous and non-blocking client interacting with a PostgreSQL database, allowing high concurrency.
* Reactive MySQL client: An asynchronous and non-blocking client interacting with a MySQL database
* The MongoDB extension: exposes an imperative and reactive (Mutiny) APIs to interact with MongoDB.Mongo with Panache offers active record support for both the imperative and reactive APIs.
* The Cassandra extension: exposes an imperative and reactive (Mutiny) APIs to interact with Cassandra
* The Redis extension: exposes an imperative and reactive (Mutiny) APIs to store and retrieve data from a Redis key-value store.

=== Event-Driven Architecture

* Reactive Messaging: allows implementing event-driven applications using reactive and imperative code.
* Kafka Connector for Reactive Messaging: allows implementing applications consuming and writing Kafka records
* AMQP 1.0 Connector for Reactive Message: allows implementing applications sending and receiving AMQP messages.

=== Network Protocols and Utilities

* gRPC: implement and consume gRPC services.Offer reactive and imperative programming interfaces.
* GraphQL: implement and query (client) data store using GraphQL. Offers Mutiny APIs and subscriptions as event streams.
* Fault Tolerance: provide retry, fallback, circuit breakers abilities to your application.It can be used with Mutiny types.

[#engine]
=== Engine

* Vert.x : the underlying reactive engine of Quarkus.
The extension allows accessing to the managed Vert.x instance, as well as its Mutiny variant (exposing the Vert.x API using Mutiny types)
* Context Propagation: capture and propagate contextual objects (transaction, principal…) in a reactive pipeline
3 changes: 2 additions & 1 deletion docs/src/main/asciidoc/reactive-event-bus.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,8 @@ public class GreetingService {
[TIP]
.Mutiny
====
The previous example uses Mutiny reactive types, if you're not familiar with them, we recommend reading the link:getting-started-reactive#mutiny[Getting Started with Reactive guide].
The previous example uses Mutiny reactive types.
If you are not familiar with Mutiny, check xref:mutiny-primer.adoc[Mutiny - an intuitive reactive programming library].
====

=== Configuring the address
Expand Down
2 changes: 1 addition & 1 deletion docs/src/main/asciidoc/reactive-sql-clients.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ Reactive REST endpoints in your application that return Uni or Multi need `Mutin
[TIP]
====
In this guide, we will use the Mutiny API of the Reactive PostgreSQL Client.
If you're not familiar with Mutiny reactive types, read the link:getting-started-reactive#mutiny[Getting Started with Reactive guide] first.
If you are not familiar with Mutiny, check xref:mutiny-primer.adoc[Mutiny - an intuitive reactive programming library].
====

=== JSON Binding
Expand Down
3 changes: 2 additions & 1 deletion docs/src/main/asciidoc/rest-client-reactive.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,8 @@ public class CountriesResource {
[TIP]
.Mutiny
====
The previous snippet uses Mutiny reactive types, if you're not familiar with them, read the link:getting-started-reactive#mutiny[Getting Started with Reactive guide] first.
The previous snippet uses Mutiny reactive types.
If you are not familiar with Mutiny, check xref:mutiny-primer.adoc[Mutiny - an intuitive reactive programming library].
====

When returning a `Uni`, every _subscription_ invokes the remote service.
Expand Down
3 changes: 2 additions & 1 deletion docs/src/main/asciidoc/rest-client.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -472,7 +472,8 @@ public class CountriesResource {
[TIP]
.Mutiny
====
The previous snippet uses Mutiny reactive types, if you're not familiar with them, read the link:getting-started-reactive#mutiny[Getting Started with Reactive guide] first.
The previous snippet uses Mutiny reactive types.
If you are not familiar with Mutiny, check xref:mutiny-primer.adoc[Mutiny - an intuitive reactive programming library].
====

When returning a `Uni`, every _subscription_ invokes the remote service.
Expand Down
3 changes: 1 addition & 2 deletions docs/src/main/asciidoc/rest-json.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -512,8 +512,7 @@ Use `Multi` when you have multiple items that may be emitted asynchronously.

You can use `Uni` and `Response` to return asynchronous HTTP responses: `Uni<Response>`.

More details about Mutiny can be found in the link:getting-started-reactive#mutiny[Getting Started with Reactive guide].

More details about Mutiny can be found in xref:mutiny-primer.adoc[Mutiny - an intuitive reactive programming library].

== HTTP filters and interceptors

Expand Down
2 changes: 1 addition & 1 deletion docs/src/main/asciidoc/resteasy-reactive.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -975,7 +975,7 @@ public class Endpoint {

Most of the time, there are ways to achieve the same blocking operations in an asynchronous/reactive
way, using https://smallrye.io/smallrye-mutiny/[Mutiny], http://hibernate.org/reactive/[Hibernate Reactive]
or any of the link:getting-started-reactive[Quarkus Reactive extensions] for example:
or any of the xref:quarkus-reactive-architecture.adoc#quarkus-extensions-enabling-reactive[Quarkus Reactive extensions] for example:

[source,java]
----
Expand Down
2 changes: 1 addition & 1 deletion docs/src/main/asciidoc/vertx.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ vertx.fileSystem().readFile("lorem-ipsum.txt")
[TIP]
.Mutiny
====
If you're not familiar with Mutiny, we recommend to read the link:getting-started-reactive#mutiny[Getting Started with Reactive guide] first.
If you are not familiar with Mutiny, check xref:mutiny-primer.adoc[Mutiny - an intuitive reactive programming library].
====

== Using Vert.x in Reactive JAX-RS resources
Expand Down

0 comments on commit 2c069ce

Please sign in to comment.