Book Image

Scala Reactive Programming

By : Rambabu Posa
Book Image

Scala Reactive Programming

By: Rambabu Posa

Overview of this book

Reactive programming is a scalable, fast way to build applications, and one that helps us write code that is concise, clear, and readable. It can be used for many purposes such as GUIs, robotics, music, and others, and is central to many concurrent systems. This book will be your guide to getting started with Reactive programming in Scala. You will begin with the fundamental concepts of Reactive programming and gradually move on to working with asynchronous data streams. You will then start building an application using Akka Actors and extend it using the Play framework. You will also learn about reactive stream specifications, event sourcing techniques, and different methods to integrate Akka Streams into the Play Framework. This book will also take you one step forward by showing you the advantages of the Lagom framework while working with reactive microservices. You will also learn to scale applications using multi-node clusters and test, secure, and deploy your microservices to the cloud. By the end of the book, you will have gained the knowledge to build robust and distributed systems with Scala and Akka.
Table of Contents (16 chapters)

Reactive Manifesto

Reactive Manifesto is a manifesto that describes how to design and architect Reactive systems according to your needs. It describes the four traits of Reactive systems. As of now, we are using Reactive Manifest v.2.0, which was initially published on September 16, 2014.

As per Reactive Manifest 1.0 (initial and old version), Reactive systems are Responsive, Scalable, Resilient, and Event-Driven.

As per Reactive Manifest 2.0, Reactive systems are Responsive, Scalable, Resilient, and Message-Driven.

We can find the manifesto on GitHub as a repository, available at https://github.com/reactivemanifesto/reactivemanifesto.

Need of Reactive Manifesto

We need to understand what the main need of Reactive Manifesto is, so that we will get clear picture about it.

The main needs or goals of Reactive Manifesto are as follows:

  • Users or customers need responses in a timely manner. They don't like slow responses and they don't use slow systems. If they don't get quick responses as needed, they will look for other options.
  • We should have an API to support asynchronous streaming data with non-blocking backpressure.
  • API for Reactive Technology (frameworks, tools, languages, IDEs, and so on) implementors.
  • Heterogeneous Reactive systems should work in an interoperable way.
  • We should have a better approach for consumers to avoid buffer overflow issues.

Principles of Reactive systems

In this section, we will discuss what the four traits or principles of Reactive systems are that we should follow to develop Reliable, Flexible, Scalable, Distributable, and Resilient applications.

Reactive Manifesto defines the following four principles:

  • Message-Driven
  • Elastic
  • Resilient
  • Responsive

This preceding diagram is copied from Reactive Manifesto. These are design and architectural principles. They are also known as the Four tenants of Reactive Streams or Four core building blocks of Reactive Streams.

We will pick up each trait one-by-one and discuss it in detail in subsequent sections.

Message-Driven

The core or base principle of the Reactive systems is Message-Driven architecture. It is the foundation principle or method for the rest of the three principles—Elasticity, Resilience, and Responsiveness.

This means a Reactive system depends on asynchronous message-passing between its components to use the benefits of Message-Driven architecture for free.

In simple words, Message-Driven = React to messages.

Even though RP represents the system's changes in terms of events, a Reactive system converts them into messages under the hood.

One more important point to note is that in a Reactive system, even failures are represented as messages, so it's easy to perform failure handling.

So, in a Reactive system, all of its components communicate with each other by sending messages. The Message-Driven approach gives us the following benefits:

  • Messages are immutable by design
  • They share nothing, so are thread-safe by design
  • They provide loose coupling between system components
  • They can work across the network, so they support Location Transparency
  • They support scalability
  • They support Resilience because they avoid single-point-of-failure using partitioning and replication techniques
  • They support better throughput
  • They provide easy-to-apply backpressure

So in RP, we write code in a stream of events, and then Reactive systems convert them into a stream of messages.

Elasticity

Elasticity means scalability. Our system should support scale up/scale down and scale out/ scale in. Our Reactive system should support scale up/scale out so that it responds to the users in a timely manner. It should also support scale down/scale in order to save our organization cost.

In simple words, Elastic = React to load.

This means our system should respond to users in a timely manner even at a heavy load.

With this property, a Reactive system can allocate and/or deallocate resources for every component dynamically and automatically to match demands.

If our Reactive system follows the Message-Driven approach, it supports Elasticity easily:

Elasticity = Scale up/down + Scaleout/in

Scale up: When the load increases, a Reactive system should be able to easily upgrade it with more and more powerful resources (for instance, more CPU Cores) automatically, based on the demand:

Scale down: When the load decreases, a Reactive system should be able to easily degrade it by removing some resources (for instance, CPU Cores) automatically, based on demand:

Scale out: When the load increases, a Reactive system should be able to easily extend it by adding some new nodes or servers automatically, based on the demand:

Scale in: When the load decreases, a Reactive system should be able to easily sink it by removing some nodes or servers automatically, based on the demand:

Resilience

Resilience is not just fault-tolerance, it's beyond fault-tolerance. A Reactive system should fully recover from failure; this is known as self-healing.

In simple words, Resilient = React to failure.

Resilience means a Reactive system should respond to users even in the event of failures, by recovering itself. This is possible by isolating the failure handling to a different component. In a Reactive system, all failures are converted into messages and then processed.

For instance, in Akka Toolkit, Akka Streams (one of the popular Reactive Streams implementations) uses the supervision technique to do this failure handling.

Refer to Chapter 4, Building Reactive Applications with Akka, to understand this Supervision technique.

In a Reactive system:
  • Failures are messages
  • Events are messages

Responsiveness

The last but very important trait is responsiveness. In Reactive systems, Responsive means reacting to the users or customers in a timely manner. Here, we should understand this point—a user should get a response when needed, otherwise they will lose interest and go for other options. In the current Reactive World, the following two things are the same:

  • Not giving response to users when needed or in a timely manner
  • Not giving any response to users at all

Even though our system does give a response to the user at a later time, the user does not need it then. Our system loses the users and ultimately, we lose our business.

In simple words, Responsive = React to users.

After going through these four traits of a Reactive system, we should understand the following things:

  • The main goal of a Reactive system is responsiveness
  • The core method that a Reactive system should follow is Message-Driven
  • The core principles of a Reactive system are Elasticity and Resilience:

The core method of a Reactive system, that is, the Message-Driven approach, will give us Elasticity and Resilience for free:

These three traits of a Reactive system (that is, Message-Driven, Elasticity, and Resilience) give us the main goal or value of that Reactive system—responsiveness.

After going through the Reactive Manifesto, we can represent it in a pictorial form, as shown here:

Why Reactive Streams specification?

In this section, we will understand, first of all, why we really need the Reactive Streams specification. We will also answer a few more questions, like—What is the use of this specification or standard, and who really needs this specification?

RSS (Reactive Streams Specification) is a standard or specification. It explains how to develop frameworks, tools, toolkits, languages, libraries, IDEs, data stores, servers, and so on, which work in Reactive.

Are we getting any benefits by following this specification? Yes. That's why we need this specification.

The main goals or benefits of this specification are as follows:

  • To support reactiveness
  • To support interoperability:

If we observe the preceding diagram, we can understand that many applications are using many Reactive technologies. If they follow their own approach to develop their Reactive systems, then it is a bit tough for them to talk to or work with each other. It is possible to implement some kind of adapters or interfaces to fill the gap and make them work with each other. However, it is not only an old and tedious approach, but also outdated and obsolete.

If we have a specification or standard or API similar to the Reactive Streams Specification and everybody develops their tools, frameworks, and so on, by following this, then there will be no need for extra tools, such as adapters. They can work with each other without using any adapters and without any issues.

This means it enables heterogeneous Reactive systems to work with each other, that is, work in an interoperable way.

As a Java or Scala developer, we know what the use of an API is, why we need it, and who needs it. So, we need a Reactive API or standard or specification to implement or develop Reactive libraries, Reactive servers, Reactive languages, Reactive databases, Reactive tools, Reactive applications, or systems.

Initially, a set of developers from top companies such as Lightbend, Netflix, Pivotal, Redhot, and Oracle Corporation worked together on this area and prepared a specification to develop Reactive systems (or applications) easily. This is known as RSS (Reactive Streams Specification). They requested Oracle Corporation introduce an API to develop Reactive systems easily in a way that they should work interoperably. Finally, Oracle Corporation introduced a Reactive Streams API as part of JEP-266 in JDK 9 (Java SE 9). This API is known as the Flow API.

In the next section, we will discuss this Flow API in detail.

From my point of view, specification, standard, API, interface, abstract, and blue-print are all the same. They have the same meaning.

Why is Play Framework the best for Reactive systems?

Play Framework is the best full-stack web framework available in the current market to develop Reactive Web Applications, Reactive systems, Reactive architecture, Reactive microservices, or Reactive libraries using both FP and RP paradigms, that is, FRP.

The following are the reasons to clarify why Play is good for RP:

  • Play Framework is built on top of the Akka Toolkit
  • By design, the Akka Toolkit supports Reactive Architecture using an Actor Model and Akka Streams
  • Akka Streams is the best Reactive API to develop Reactive data streaming
  • Play Framework has an integrated module for the Akka Streams API
  • Play Framework is written in Scala (a JVM language) and supports both Scala and Java programming languages
  • Both Scala and Java run on JVM
  • Scala supports FP very well
  • FP is the best programming paradigm for RP
  • The latest Play Framework has moved from Iteratees to Reactive Streams
  • It is a full-stack web framework for Reactive programming

Reactive systems versus traditional systems

In this section, we will see the main differences between a Reactive system and non-Reactive system, that is, a traditional system.

The first and foremost difference is that a Reactive system takes a user or customer request as an event or message, and then reacts to those events in a timely manner. Once it's done, it continuously looks for the next event, as illustrated here:

On the other hand, a traditional system takes input(s) from a user, performs an operation based on inputs, and sends an output or response to the user; that's it:

In a Reactive system, the RP model eases the development. As a Reactive system supports abstraction at a very high level, it is easy to develop the applications because we need to concentrate on only our application business logic. Meanwhile, in a traditional system, we need to take care of the application business logic while writing some low-level logic, as it does not support high-level abstraction.

In a Reactive system, changes are propagated automatically. For instance, in a spreadsheet, we have a formula at cell A3, A3 =A1+A2. When we change the value of A1 or A2 or both, then all their references will be updated automatically. This means A3 will be updated automatically. It is not possible in a traditional system or non-Reactive system.

In Reactive systems, we concentrate on the flow of control, whereas in traditional systems, we concentrate on the flow of data.