To the brave new world of reactive systems and back
Reactivity is surely an important topic, though I believe we’ve spent too much time talking about reactive programming, while only briefly mentioning the other implementation — reactive systems. It’s time to reevaluate.
Reactive systems are of particular attention in today’s IT world, because we need complex, highly distributed applications that can handle a high load.
Before we explore reactive systems, their basic principles and practical application, let’s brush up quickly the core idea of reactivity.
A quick warm-up on reactivity
The big idea behind reactivity is to create applications that will gracefully deal with modern data that is often fast, high volume, and highly variable.
Reactive systems are not the same thing as reactive programming. Reactive programming is used at the code level, while reactive systems deal with architecture. And they don’t imply the obligatory use of reactive programming.
In 2014, the Reactive Manifesto 2.0 boiled the basic concepts of modern reactive systems into four fundamental principles:
- Responsiveness: Be available for users and, whatever happens (overload, failure, etc.), be ready to respond to them.
- Resilience: Stay immune to faults, disruptions, and extremely high loads.
- Elasticity: Use of resources efficiently and balance the machine performance — vertical scaling up or down — or easily regulate the number of machines involved — horizontal scaling up or down — depending on the load.
- Message-driven character: Embrace a completely non-blocking communication via sending immutable messages to addressable recipients.
Though the principles often get enumerated as a list, they are closely interrelated and can be modified to read as follows:
A reactive system bases on message-driven communication that guarantees exceptionally loose coupling of the components and thus allows the system’s elasticity and resilience, both of which contribute to its high availability (responsiveness) to a user in case of overloads, disruptions, and failures.
What you need to build a reactive system
Reactive systems are about architectural decisions. There is no need to use a specific language to create a reactive application There’s also no obligatory need to call on any particular framework or tool.
There are frameworks, however, that adhere to the reactive philosophy and make a system’s implementation simpler. For example, you can leverage the benefits of Akka actors, Lagom framework, or Axon.
As we mentioned, reactive systems are based on certain design decisions, some of which are detailed in the book Reactive Design Patterns by Brian Hanafee, Jamie Allen, and Roland Kuhn. We’ll give you a taste of several popular patterns that make a system reactive.
- Multi-level organization: Level down potentially unstable or dangerous components — ones that are often overloaded or vulnerable to frequent changes or exposed to third parties. So if failures or disruptions occur, there will always be a higher-level component to continue the work or to tell a user that something is wrong.
- Message queues: Separate data consumers from data producers. Back pressure mechanisms allow a reactive system — not a user — to control the speed of the environment. In order not to shock the server with a massive data flow, the back pressure mechanisms allow the server to extract the messages from the queue at a convenient and safe speed.
- Pulse patterns: An accountable server should send health check responses to a responsible server at regular intervals. This prevents the messages from going into the void in case of an unnoticed server failure.
- Data replication: Different data consistency patterns — active-passive, consensus-based, conflict-free — maintain the system availability in case of failures and crashes in database clusters.
- Safety locks: Continuously track the state of servers. In case of too many breakdowns or highly increased latency, safety locks automatically exempt the server from the process and let it recover.
When to switch to a reactive approach
Disclaimer: In the vast majority of cases, building a reactive architecture is rather costly and requires a lot of effort and time. It requires the introduction of mediator components, data replication, etc. If you choose the reactive approach, make sure your application really needs it.
Simply put, you adopt reactive architecture when you need its benefits. You turn to it when mission-critical applications can’t fail or you need to tackle extremely heavy loads. If you build an application with more than 100,000 users and want impeccable UX with increased responsiveness and high availability, then a reactive architecture may be worth it.