Microservices in Practice: Evaluation and Critical Appraisal of ludotheca-share-mesh

Github Repo: https://github.com/marco13-moo/ludotheca-share-mesh
Evaluation and Critical Appraisal
Comparison To Alternative Styles
Comparison to Monolithic Architecture
Monoliths define modularity in accordance to programming constructs such as Java packages which are easy to violate [3:12]. Method calls in monoliths are not executed remotely, there is tight coupling between boundaries and a single datastore for all components is often found. In the context of a sole-developer building the book-lending system based on parsing JSON payloads and performing CRUD operations on the datastore, a monolith proves superior. Monoliths prove far simpler in design and faster execution times if persistence I/O is not performed over the network.
Monoliths do fall short when developing at scale as:
Lack of decoupling via API defined boundaries provides no fault-tolerance guarantees.
Larger development teams will require greater coordination due to tightly coupled modules, slowing the software delivery process.
Lack of modularity could prove shorter software longevity as migration to new technology stacks may be too complex.
Scaling is achieved on a per application basis, proving costly if only a specific module is experiencing heavy load.
As demonstrated with this project, one may fall into a distributed monolithic trap if the microservices architecture is not correctly designed such as:
Having heavy reliance on orchestration-based sagas.
Incorrectly leveraging technology stacks- as illustrated with the "too many standards" bad architectural smell.
Comparison to Service-Orientated Architecture
Both microservices and service-orientated architecture are styles structuring the system as a set of services [3:14]. The key differences between the two is within the scope of inter-service communication, service size and datastore architecture implemented.
Inter-service communication: Microservices architecture places an emphasis on dumb pipes. Service-to-service communication is either dealt with using a message broker or lightweight protocols such as REST or gRPC.
Data: Microservices incorporates a database per service model whilst SOA adheres to shared databases.
Service Size: A service is usually monolithic within the SOA style, microservices incorporate greater granularity with a focus on smaller services.
Summary of Leveraging Microservices as a Teaching Framework
The aim of this project was the exploration of software engineering developments, and leveraging microservices to create a framework to be used within the teaching scope of software architecture and engineering.
It was necessary to develop a family of systems that has low cost of evolution, deployment flexibility as well as minimal learning overhead towards new mechanisms.
Within scope of these aims, the strengths and weaknesses of leveraging microservices as a teaching framework is detailed below [3:14]:
Strengths:
Microservices allow for continuous deployment and delivery of large and complex applications.
- The book lending microservices easily integrate with gitlab's CI/CD tooling and GKE clusters.
The architectural style allows for service decomposition, providing easier system maintenance.
- Book lending system is decomposed into 3 core microservices that can be extended/maintained via adherence to it's API contract. API gateway can be swapped out.
Microservices are independently deployable and scalable, allowing for autonomous team development.
- Book lending microservices are independently scalable/deployable on a localhost via Eureka (for learning) as well as Kubernetes via Kubernetes native service discovery (for production runs).
New technologies can be easily integrated.
- Book lending system illustrates this with a minor asynchronous messaging extension using RabbitMQ.
Microservices allow for strong fault isolation due to characteristics that design for failure (ie, strong module boundaries, independent deployment).
- One can take down a microservice in the book lending system and it will still run. Kubernetes further promotes this via self-healing pods that spool back up after an unexpected failure. Strong modules defined via API only inter-service/client communication.
Weaknesses:
Service decomposition is often ill-defined. Incorrect decomposition may also lead to a distributed monolith.
Wrong pattern choices may lead to monolithic operational characteristics:
- Book-lending system illustrated this with the orchestration based saga
As a microservices style forms part of the distributed architecture family, the fallacies and complexities of building a distributed system follow suit.
Features that span across multiple services require a higher level of coordination.
A greater toolset range is needed that one won't find in a monolithic counterpart, such as service discovery or circuit breaker mechanisms.
Evaluation of the Resource Sharing System as a Teaching Framework
Within the scope of teaching software architecture and engineering, the book-lending system provides the following strengths and weaknesses:
Strengths:
Demonstrates practical use of architectural patterns.
Provides students to be part of autonomous teams and practice cross-functional software development.
Provides a practical opportunity in illustrating trade-offs one encounters in engineering and architecture.
Introduces a base system to explore concepts in distributed computing.
Allows students to leverage a wider tooling array with the School's Gitlab system, be it GKE integration or CI/CD pipelines.
Provides an introductory learning experience to new concepts such as cloud-based infrastructure, containers and container orchestration.
Weaknesses:
Limited language support of Spring may be an issue if other languages want to be implemented in future iterations.
Heavy reliance on Spring Cloud dependencies may shorten system lifespan.
The difficulty towards system evolution, such as migration of communication or cross-functionality patterns, has yet to be encountered.
Use of JPA for persistence mapping may hinder datastore choices.
Full exploration of service scaling, roll-backs and continuous updates with Kubernetes does prove resource intensive, limiting its scope towards expensive cloud-based deployment rather than locally run Kubernetes nodes.
Fallacies of Distributed Computing
As the architectural style of the book-lending system is of a distributed systems type, Deutsch's [2] fallacies of distributed computing did take place during development.
The two most prominent fallacies encountered and their effects were:
The network topology does not change: this was most prominent during deployment of Eureka service discovery on Kubernetes, as the internal networking structure of Kubernetes was not suited to Eureka.
The network is reliable: a lack of a timeout check for a HTTP response may lead to inter-service/client calls being stalled.
Use and Application of Fairbanks' Architectural Hoisting
Architectural hoisting was a concept prominently explored throughout the development of the system. Fairbanks defines architectural hoisting as a "design technique where the responsibility for an intentional design constraint is moved away from developer vigilance into code, with the goal of achieving a global property on the system" [19]. Thus, global properties such as scalability or performance are hoisted to the architecture rather than the developer. This enforces a shift towards use of infrastructure code such as frameworks and libraries, assigning the design constraint away from developer vigilance.
Framework and runtime service use provided a templated solution towards solving architectural and business logic problems. This allowed problems to be solved faster and made sure the system followed architectural design constraints/guide rails.
Hoisting provided a standardized guide rail implementation in the system- minimizing architectural risks and developer errors. But trade-offs still do occur.
Developer vigilance drift provides a risk of over-constraining developers to a point where system changes are no longer possible. A prominent example of this would be how the book-lending system constrains the developer to adhere to Java and Spring-based products/libraries in order to align the microservices guide rails. For example, developers are contrainted to Spring's use of Tomcat servlets for each Spring Boot microservice in order to adhere to the microservices design constraint of independently deployable services. Hoisted systems further prove difficult to debug. This was shown as leveraging service discovery
/deployment tools were so far removed from the developer that it meant simple issues such as inter-service communication became too complex to debug.
Appraisal of the Book Lending's Microservice Architecture against Definition by Fowler and Lewis
With Fowler and Lewis's early attempts in 2014 at formerly tackling a definition for microservices architecture, their brief blog statement is often considered the de facto standard to what microservices entail [4]. The definition may be found in the context survey.
Comparing this definition to the book-lending microservices system shows:
The book-lending application is decomposed into a suite of small independently deployed services focused on business capabilities.
Each service is its own process communicating with each other using API-based HTTP resources.
Using Kubernetes on the Google Cloud Platform, there is a bare minimum need for centralized service management and one can independently scale and deploy each service leveraging Kubernetes native service discovery.
Spring and JPA invokes a minor set of language, library and datastore constraints. Loose service coupling and API-based communication does entail this constraint be easily mitigated via service mesh migration.
Future Evolution to Address Architectural and System Shortfalls
An alternative to the microservices chassis pattern is the service mesh. The service mesh pattern provides key microservice features such as circuit breaker patterns and service discovery being implemented upon the networking layer, routing traffic between services in accordance to the specified features [3:380].
This provides fewer dependencies within each microservice and further allows for a large range of languages to be supported, voiding Spring's limited language support. Popular service mesh frameworks include Istio and Linkerd. Istio and Linkerd are compatible with Spring using Kubernetes service discovery, there is future potential for the system to evolve towards service mesh use.
A migration towards use of asynchronous messaging patterns for inter-service communication will be needed to explore the choreography-based saga pattern within the book-lending system. This evolution will prevent the architectural risk of the system becoming a distributed monolith.
Leaving Remarks
The task at hand was not an easy feat. Thorough research was required for every stage in development and each choice of an architectural pattern implementation was to be compared and justified. An array of unexpected issues unfolded, from repository limitations to design pivots due to deprecated libraries. Nevertheless, development of the microservices-based system prevailed.
As a teaching framework, the system's microservices shows the prevalence of trade-offs that software architects and engineers will encounter on a regular basis. Simply striving to meet as many characteristics as possible will certainly come at a cost in providing a focused solution towards a given problem [2].
Through strict adherence to "architectural hoisting" [19], the system provides a relevant frame of reference towards illustrating the connection between architecture and engineering in software systems.
With microservices providing a strong emphasis on autonomous development teams and devops culture [20], it is one of a limited set of architectural styles that helps guide good software engineering and deployment practices.
With the resource-sharing system being a distributed architecture, the complexity of building a distributed system and the fallacies that follow along were practically illuminated.
With the aim of exploring recent developments made in software engineering, the system provides a concrete display of the benefits and drawbacks of leveraging development frameworks and automated deployment mechanisms.
As the core focus of the system and microservices architecture was providing ease of deployment, increased software longevity and evolutionary cost reduction - the system was able to leverage cloud tooling, infrastructure and a conservative technology stack that not only practically displays the key strengths and weaknesses of microservices, but welcomes continuous improvement and change. Through iterative evolution, be it a migration to a service mesh or asynchronous inter-service communication; the system provides a stable foundational base for future exploration in software engineering and architecture.
Subscribe to my newsletter
Read articles from Marco directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Marco
Marco
Senior DevOps Engineer exploring the world of distributed systems