Reactive Systems and How They Fulfil the Distributed Systems Design Goals
On 16th of September 2013 the Reactive Manifesto 1.0 was published. Since then it was slightly modified and evolved to the version 2.0 (reference). It declares the principles of building Reactive Systems and their characteristics. These systems are: message driven, resilient, elastic and therefore responsive. They consist of independent and isolated components which asynchronously exchange messages. The components can generate new messages, send the messages to themselves or to the other components. In this essay I would like to consider reactive systems, their characteristics and assess how well they suit for distributed systems development. To make the assessment I compare reactive system characteristics with distributed systems design goals.
The ideas that formed the basis of the Reactive Manifesto are not new. The works with similar thoughts appeared in the 1970s, they described the Actor Model. The Actor Model is based on the notion of actors. Actors are defined as entities which can receive and send messages to other actors, they are able to create new actors and change behaviour in response to incoming messages. Actors are composed into asynchronous message processing systems which are lock-free, parallel, support finite state machines and in which actors do not have shared state. However, the Actor Model did not gain much popularity and spreading at that time. The main reason for this was that in 1970s there were no multi-core processors and processing capacity of computers was low (??? ??????). The practical use of the model of actors designed for parallel computations was not justified. The message passing was also used as core feature of Smalltalk programming language. Actor Model was implemented in Erlang.
Firstly, what are the distributed systems design goals? According to Tanenbaum (ref page 7) “a distributed system should make resources easily accessible; it should hide the fact that resources are distributed across a network; it should be open; and it should be scalable”. As the goals were stated, it is time now to look more closely at the characteristics of the Reactive Systems.
The requirement of resilience forces developers to think about error handling at the very beginning of the design process. Reactive Manifesto proposes to confine errors to the components in which they occur or to propagate errors to the other components in a controlled way. The system should be able to operate without outages by restoring its failed components and data replication. This requirement ensures replication and failure transparency (reactive systems find source).
Asynchronous message processing gives reactive systems the ability to create loosely coupled and well isolated components (vaughn vernon). This allows to easily compose different components into a system and reuse them. Messaging also simplifies the design of component interfaces. It makes reactive systems open. Mechanisms of message routing help to achieve access, concurrency, relocation, migration and location transparency. Apart from this, asynchronous processing also provides higher performance and parallelism of reactive systems by reducing the length of pieces of code, which must be executed sequentially, this is explained by Amdal’s law (reference Goetz). Since an asynchronous call implies no time spent inside called code before returning control to the calling site, this allows the system to be as responsive as possible.
Elasticity requires the reactive system not only to be scalable but also demands a clear definition of how the system will respond to increased load. It involves automatic scaling of the system on demand, depending on the load at a particular moment.
Finally, combination of all the properties mentioned above provides simplicity of resource sharing. The interesting thing that in fact Reactive Manifesto combines all the goals of distributed systems into a single architectural style, this demonstrates that it suites well for the distributed systems development.
Moreover, a distinctive feature of reactive systems is the nonblocking back pressure. Back pressure is the load containment mechanism for the cases when a slower consumer component can not keep up with the incoming message stream from a faster producer. The idea is that the producer should stop sending messages until the consumer asks for the new ones, that means that a consumer manages the load. This eliminates possible failures of the components or loss of dropped messages due to high load .
Reactive systems can be used in a large number of solutions including Big Data, Microservices and Web Applications. Event-sourcing and streaming data processing are the two of the most interesting their applications. Event-sourcing (Fowler) can be naturally implemented on top of reactive systems, since it involves the exchange of events between objects, which is conveniently implemented as message passing (jboner). Reactive streams which are based on the principles of reactive manifesto are designed to cope well with infinite data streams. They leverage back pressure to increase message delivery guarantees and stability.
The aforementioned is the evidence that the ideas behind the reactive systems are perfectly suited for the development of distributed applications. Additionally, it is confirmed by the community. For a fairly short period from the first publication to this day the Reactive Manifesto was supported by more than 20,000 community members all over the world, that reflects the statistics on its page. Reactive Streams were evaluated by the community, and were proposed to be included in the main Java library – JDK 9 (JEP) and eventually released as its part. Pivotal Software (the developer the one of the most popular Java frameworks – Spring) released Reactive Spring which provides a reactive API. More than 10 books about various reactive technologies were published.References