Chapter 1. Reactive in a Nutshell
Reactive is an overloaded word. You may have searched for reactive with a search engine to understand what it’s all about. If you haven’t, no worries—you’ve saved yourself a lot of confusion. There are many reactive things: Reactive Systems, Reactive Programming, Reactive extensions, Reactive messaging. Every day new ones pop up. Are all these “reactives” the same reactive? Are they different?
These are the questions we are going to answer in this chapter. We are going to sneak a peek at the reactive landscape to identify and help you understand the various nuances of reactive, what they mean, the concepts associated with them, and how they relate to one another. Because yes, without spoiling too much, all these “reactives” are related.
Note
As noted in the preface, we use the noun Reactive, with an uppercase R, to aggregate all the various facets of the reactive landscape, such as reactive programming, reactive systems, reactive streams, and so on.
What Do We Mean by Reactive?
Let’s start at the beginning. Forget about software and IT for a few minutes, and use an old-fashioned approach. If we look for reactive in the Oxford English Dictionary, we find the following definition:
reactive (adjective)
Showing a response to a stimulus. 1.1 Acting in response to a situation rather than creating or controlling it. 1.2 Having a tendency to react chemically. 1.3 (Physiology) Showing an immune response to a specific antigen. 1.4 (Of a disease or illness) Caused by a reaction to something. 1.5 (Physics) Relating to reactance.
Among these definitions, two are relevant in our context. The first definition, showing a response to a stimulus, refers to some kind of reaction. Being reactive means reacting to stimuli, whatever they are. Subdefinition 1.1 says that being reactive is also about facing unexpected and uncontrolled situations. You will see throughout this book that cloud native applications, and distributed systems in general, face plenty of these kinds of situations. While these definitions are interesting, they don’t apply to software. But we can take these definitions into account to make a new one specific to software:
1.6 (Software) An application reacting to stimuli, such as user events, requests, and failures.
Yet, as you will see in this book, today’s reactive goes beyond this. Reactive is an approach to designing, implementing, and reasoning about your system in terms of events and flows. Reactive is about building responsive, resilient, and elastic applications. Reactive is also about resource utilization through efficient management of resources and communication. To put it another way: Reactive is about designing and building better distributed systems—more robust and more efficient. We call them reactive systems.
Reactive Software Is Not New
But wait, the definition (1.6) we just gave is not groundbreaking. On the contrary, you may feel some déjà vu, no? Isn’t the nature of software to react to user inputs and operating system signals? How does software behave when you hit a keystroke? It reacts. So, why are there so many books, talks, and debates about Reactive if it’s just regular software?1 Please be patient; there is a bit more to it.
But you are right; Reactive is not new. It’s actually pretty old. We can track the foundation of the ideas behind reactive software to just after the appearance of computers in the ’50s. The DYSEAC, a first-generation computer (in operation in 1954), was already using hardware interrupts as an optimization, eliminating waiting time in polling loops. This computer was one of the first systems to use reactive and event-driven architecture!
Reacting to events implies being event-driven. Event-driven software receives and produces events. The received events determine the flow of the program. A fundamental aspect of being event-driven is asynchronicity: you don’t know when you are going to receive events.2 That is precisely definition 1.1 from the previous section. You cannot plan when you will receive events, are not in control of which events you will get, and you need to be prepared to handle them. That’s the essence of being reactive: being asynchronous.
The Reactive Landscape
From this idea of being asynchronous and event-driven, many forms of Reactive have emerged. The reactive landscape is broad and crowded. Figure 1-1 depicts an excerpt of this landscape and the relationships among the main reactive things.
But don’t forget our objective: building better distributed systems—reactive systems. The other “reactives” are here to help us implement these systems.
The reasons for Reactive, and reactive systems in particular, come from distributed systems. As you will see in Chapter 3, building distributed systems is hard. In 2013, distributed system experts wrote the first version of “The Reactive Manifesto” and introduced the concept of reactive systems.
Yes, you can build distributed systems without applying reactive principles. Reactive provides a blueprint to ensure that no significant known concerns were overlooked while architecting and developing your system. On the other hand, you can apply these principles on nondistributed systems.
A reactive system is first and foremost responsive. It must handle requests in a timely fashion even under load or when facing failures. To achieve this responsiveness, the manifesto proposes using asynchronous message passing as the primary way to communicate between the components forming the system. You will see in Chapter 4 how this communication method enables elasticity and resilience, two essential attributes of solid distributed systems. The objective of this book is to show you how to build such reactive systems with Quarkus. So, building reactive systems is our primary goal.
Infusing asynchronous message passing at the core of distributed systems does not come without consequences. Your application needs to use asynchronous code and nonblocking I/O, the ability provided by the operating system to enqueue I/O interactions without having to actively wait for the completion. (We cover nonblocking I/Os in Chapter 4). The latter is essential to improve resource utilization, such as CPU and memory, another important aspect of Reactive. Today, many toolkits and frameworks, such as Quarkus, Eclipse Vert.x, Micronaut, Helidon, and Netty, are using nonblocking I/O for this very reason: doing more with limited resources.
Yet having a runtime leveraging nonblocking I/O is not enough to be reactive.
You also need to write asynchronous code embracing the nonblocking I/O mechanics.
Otherwise, the resource utilization benefits would vanish.
Writing asynchronous code is a paradigm shift.
From the traditional (imperative), do x; do y;
, you are now going to shape your code as on event(e) do x; on event(f) do y;
.
In other words, to be reactive, not only is your system an event-driven architecture, but also your code is going to become event-driven.
One of the most straightforward approaches to implementing such code is callbacks: you register functions invoked when events are received.
Like futures, promises, and coroutines, every other approach is based on callbacks and offers higher-level APIs.
Note
You may wonder why spreadsheets are in the landscape. Spreadsheets are reactive. When you write a formula in a cell and change a value read (in another cell) by the formula, the result of this formula is updated. The cell reacts to the update of a value (event), and the outcome (reaction) is the new result. Yes, your manager may be a better reactive developer than you are! But don’t worry, this book will change this.
Reactive programming, addressed in Chapter 5, is also an approach to writing asynchronous code. It uses data streams to structure your code. You observe the data transiting in these streams and react to it. Reactive programming provides a powerful abstraction and APIs to shape event-driven code.
But using data streams comes with an issue. If you have a fast producer directly connected to a slow consumer, you may flood the consumer. As you will see, we can buffer or use a message broker in between, but imagine flooding a consumer without them. That would be against the responsiveness and anti-fragile ideas promoted by Reactive. To help us with that particular issue, Reactive Streams proposes an asynchronous and nonblocking backpressure protocol where the consumer signals to the producer its availability. As you can imagine, this may not be applicable everywhere, as some data sources cannot be slowed down.
The popularity of Reactive Streams has increased over the past few years. For example, RSocket is a network protocol based on Reactive Streams. R2DBC proposes asynchronous database access using Reactive Streams. Also, RxJava, Project Reactor, and SmallRye Mutiny adopted reactive streams to handle backpressure. Finally, Vert.x allows mapping the Vert.x backpressure model to Reactive Streams.3
That concludes our quick tour of the reactive landscape. As we said, it’s crowded with many terms, and many tools. But never lose sight of the overall objective of Reactive: to build better distributed systems. That’s the primary focus of this book.
Why Are Reactive Architectures So Well-Suited for Cloud Native Applications?
The cloud—public, private, or hybrid—has put Reactive in the spotlight. The cloud is a distributed system. When you run your application on the cloud, that application faces a high degree of uncertainty. The provisioning of your application can be slow, or fast, or even fail. Communication disruptions are common, because of network failures or partitions. You may hit quota restrictions, resource shortages, and hardware failures. Some services you are using can be unavailable at times or moved to other locations.
While the cloud provides outstanding facilities for the infrastructure layer, it covers only half of the story. The second half is your application. It needs to be designed to be a part of a distributed system. It needs to understand the challenges of being part of such a system.
The reactive principles we cover in this book help to embrace the inherent uncertainty and challenges of distributed systems and cloud applications. It won’t hide them—to the contrary, it embraces them.
As microservices and serverless computing are becoming prominent architectural styles, the reactive principles become even more important. They can help ensure that you design your system on a solid foundation.
Reactive Is Not a Silver Bullet
As with everything, Reactive has pros and cons. It’s not a magic weapon. No solution works everywhere.
Remember microservices in the late 2010s? They quickly became exceedingly popular, and many organizations implemented them in areas for which they may not have been well-suited. This often traded one set of problems for another. Much like microservice architectures, reactive architectures have areas in which they are well-suited. They shine for distributed and cloud applications but can be disastrous on more monolithic and computation-centric systems. If your system relies on remote communication, event processing, or high efficiency, Reactive will be interesting. If your system uses mostly in-process interactions, handles just a few requests per day, or is computation-intensive, then Reactive won’t bring anything but complexity.
With Reactive, you put the notion of events at the core of your system. If you are used to the traditional synchronous and imperative way of building applications, the path to become reactive can be steep. The need to become asynchronous disrupts most traditional frameworks. We are moving away from the well-known Remote Procedure Call (RPC) and HTTP endpoints. So, with that disclaimer, it’s time to start our journey!
1 You can find a plethora of talks about Reactive on YouTube.
2 Asynchronous is the opposite of synchronous. Being asynchronous means happening at a different point in time, while being synchronous means happening at the same time.
3 See Vert.x Reactive Streams Integration for more details.
Get Reactive Systems in Java now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.