Reactive Systems
it’s much cheaper to make changes to sticky notes than production code
Microliths
A microlith is defined as a single instance service where synchronous method calls have been turned into synchronous RPC calls (often over REST) and blocking database access remains blocking. This architecture is maintaining the strong coupling we wanted to move away from, but with higher latency added by IPC. Oreilly link
Monoliths disguised as a set of microservices
Individual microservice
Isolate all the things
Isolation between services makes it natural to adopt Continuous Delivery.
Act Autonomously
Only when services are isolated can they be fully autonomous and make decisions independently, act independently, and cooperate and coordinate with others to solve problems.
Single Responsibility
“micro” should refer to scope of responsibility, and the guiding principle here is the Unix philosophy of SRP:
let it do one thing, and do it well
.
Own Your state, Exclusively
A microservice owns its data!
Stay mobile, but addressable
Mobility is the possibility of moving services around at runtime while they are being used.
Characteristics about Reactive Systems
Responsive
Responsive systems focus on providing rapid and consistent response times, establishing reliable upper bounds so they deliver a consistent quality of service.
Resilient
The system stays responsive in the face of failure. Resilience is achieved by replication, containment, isolation and delegation. Failures are contained within each component, isolating components from each other and thereby ensuring that parts of the system can fail and recover without compromising the system as a whole.
Elastic
The system stays responsive under varying workload. Reactive Systems can react to changes in the input rate by increasing or decreasing the resources allocated to service these inputs.
Message Driven
Reactive Systems rely on asynchronous message-passing to establish a boundary between components that ensures loose coupling, isolation and location transparency. This boundary also provides the means to delegate failures as messages. Employing explicit message-passing enables load management, elasticity, and flow control by shaping and monitoring the message queues in the system and applying back-pressure when necessary.
Reactive Programming
Main characteristics of Reactive Programming are asyncronous execution, non-blocking I/O, back-pressured streaming and circuit breakers.
Another important property is the two channel communication, where one channel is used to send data and the other channel to control back-pressure and errors.
Asyncronous Programming and non-blocking I/O
Using async programming and non-blocking I/O helps to prevent resource contention. A resource experiencing ongoing contention can be described as oversubscribed. A process should not hold a thread hostage. With more threads comes more context switching, which is very costly. How long does it take to make a context switch?.
To reap the benefits of non-blocking execution, all parts in a request chain need to participate. REST over HTTP through its synchronous nature introduces strong coupling between the services making it a very bad default protocol for inter-service communication.
If you need to use REST over HTTP, which could be a good option in certain cases, always use it outside the regular communication flow so as not to block the regular request-response cycle.
Always apply Back-Pressure
Back-pressure is all about flow control, ensuring that a fast producer should not be able to overwhelm a slower consumer by being allowed to send it more data than it can handle. Back-pressure includes having a back-channel where the consumer can manage control flow by communicating with the producer.
It is paramount that all of the parties in the workflow/data pipeline participate and speak the same protocol.
In cases when dealing with components that cannot communicate async then a way of protecting the system from overload is to wrap the component that cannot speak async into a wrapper called circuit breaker.
Circuit Breaker is a finite-state machine with a finite set of states Open, Closed, Half-Open.
The JVM supports a backpressure mechanism implemented in Java 9 as the Flow API.
Micro-services frameworks with back-pressure mechanisms:
A comparison between RatPack and Dropwizard
Reactive Streams Specification
Implementations
Java JDK 9 Flow API
A mix of Iterator and Observer patterns where the Subscriber initially requests N elements and then the Publisher will push at most N elements towards the Subscriber.
Publisher
The publisher publishes the stream of data items to the registered subscribers. It publishes items to the subscriber asynchronously, normally using an Executor.
Subscriber
The Subscriber subscribes to the Publisher for the callbacks. Data items are not pushed to the Subscriber unless requested, but multiple items may be requested.
Subscription
Links a Flow.Publisher and Flow.Subscriber. Subscribers receive items only when requested, and may cancel at any time, via the Subscription.
Project Reactor
RxJava
Migrating towards Reactive Micro-liths
- Start from the edge and replace synchronous and blocking communication with async and non-blocking. A good technique is event driven with pub/sub mechanism using Apache Kafka or AWS Kinesis.
- Replace database access layer with an async one, removing the SPF from the system.
RxJava
RxJava is a Java VM implementation of Reactive Extensions: a library for composing asynchronous and event-based programs by using observable sequences.
It extends the observer pattern to support sequences of data/events and adds operators that allow you to compose sequences together declaratively while abstracting away concerns about things like low-level threading, synchronization, thread-safety and concurrent data structures.
Observable
onCompleted()
onError()
onNext()
Subscriber
Reactor Core
Reactor Core is a Java 8 library which implements the reactive programming model. It’s built on top of the Reactive Streams Specification, a standard for building reactive applications. Reactive Streams Specification not to be confused with Java 8 Stream API, they are totally different.
Reactive Streams Specification
Reactive Streams is an initiative to provide a standard for asynchronous stream processing with non-blocking back pressure. This encompasses efforts aimed at runtime environments (JVM and JavaScript) as well as network protocols.
Interface Publisher
A Publisher is a provider of a potentially unbounded number of sequenced elements, publishing them according to the demand received from its Subscriber(s). A Publisher can serve multiple Subscribers subscribed subscribe(Subscriber) dynamically at various points in time.
interface Publisher<T>{}
Flux
A Reactive Streams Publisher with rx operators that emits 0 to N elements, and then completes (successfully or with an error). It is intended to be used in implementations and return types. Input parameters should keep using raw Publisher as much as possible.
public abstract class Flux<T> extends Object implements Publisher<T> {}
Mono
A Reactive Streams Publisher with basic rx operators that completes successfully by emitting an element, or with an error.
Mono
public abstract class Mono<T> extends Object implements Publisher<T> {}