March 15, 2017

The Zen of Microservices (2) : Monolith vs Microservice

Sample Monolithic Architecture

The monolithic architecture diagram depicts a well-designed, modular application. It has several well-defined internal modules. It interacts with external systems via adapters that separate the core application logic from infrastructure details like transport and persistence.

This means:

What is Microservice Architecture (MSA)?

Independent services vs Modules

Unlike monoliths, which are typically built out of modules, microservice architecture is built on independent services that are split out by business functions, with a share-nothing architecture.

This means:

Best Practices: Distributed vs. Monolithic

Microservice architecture places high value on independence and resilience which means that best practices from monolithic applications do not always translate over to MSA.
Some key examples:

Message-based communication vs Method calls:

Monolithic applications pass data via method calls to internal modules or libraries with practically zero latency. Typically, large, complex data structures maybe passed around with little to no impact on system performance. In contrast, message-passing is the primary means of communication in MSA. A large part of processing centers around publishing, consuming, parsing, tracking, serializing and deserializing messages. The choice of message format (HTTP over JSON, RPC, XML, ProtoBuf etc) and their size and complexity have systemic implications.

Lightweight components

Monolithic applications are generally deployed infrequently and as such significant startup and tear-down time/effort including some level of manual intervention is acceptable and often factored into service-level agreements (SLAs). Microservices are expected to auto-scale in response varying loads so they must be built as transient, lightweight components to allow for quick and automated spin-up and tear-down.

Non-blocking, event-driven, asynchronous operations

In Monolithic applications, the vast majority of operations are synchronous and blocking. Events are usually internal, and used to facilitate decoupling of distinct modules. Asynchronous operations are usually delegated to Job Queues. Since performance and availability is highly prioritized in MSA, non-blocking, asynchronous operations are preferred over blocking calls where clients wait "online" for the results of operations. Events are used to decouple and parallelize operations for scalability and resilience.

Eventual Consistency

The transactional model of relational databases (ACID) dominates how data is processed and persisted in monolithic applications. Operations are modeled to be binary in nature – either a success or a failure – and the result is immediately relayed to the user. While the "happy path" in MSA can model atomic transactions, it's distributed nature brings to the surface issues of strong and weak consistency. In order to offer high resiliency, performance and availability microservices are built to tolerate varying latencies and partial failures, which may involve embracing both strong and weak consistency models.

Concurrent Processing

Monolithic applications typically default to single-threaded concurrency models and when multi-threaded, concurrent processing is invoked it is carefully coordinated to prevent race-conditions and other undesirable outcomes. The standard architecture patterns for MSA always assume concurrent processing and as such start at a much higher level of complexity in terms of process interactions. Managing and coordinating concurrent processing in a central architectural concern at the system level. Microservices are built with the intent of running many concurrent instances as consumers and producers with the system.

Highly Observable

The distributed nature of microservices and the focus on performance forces observability to the forefront of design. Viewing the internal state, logs and other operational details of each instance is key to understanding the system as a whole and so they expose as much information as possible in standardized, consumable formats to gather metrics, analytics and maintain audit logs of operations. This becomes even more critical when instances are transient i.e quickly spun-up to perform an operation and torn-down immediately.

Image Credits:

  • LinkedIn
  • Tumblr
  • Reddit
  • Google+
  • Pinterest
  • Pocket