39

Effective Microservices: 10 Best Practices

 4 years ago
source link: https://towardsdatascience.com/effective-microservices-10-best-practices-c6e4ba0c6ee2?gi=4f5f86d167ef
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

JbuaYrr.jpg!web

Effective Microservices: 10 Best Practices

In a previous post: Microservice Architecture: A brief overview and why you should use it in your next project , I have discussed in detail over Microservice Architecture and the advantages/disadvantages of using it in modern Software Development. So, what exactly is Microservice Architecture? Here is my definition:

Microservice Architecture is about decomposing a Software System into autonomus Modules which are independently deployable and which communicates via lightweight, language agnostic way and together they fulfill the business goal .

Software Systems are Complex. As the human brain can only handle complexity up to a certain limit, the high complexity of large software systems leads to many problems. A large-scale and complex software system is difficult to develop, enhance, maintain, modernize, scale. Over the years, there are many attempts to tackle the complexity of Software Systems. During the 70s, Modular Software Development was introduced by David Parnas and Edsger W. Dijkstra to tackle the complexities of Software Systems . During the 1990s, layered Software Architecture was introduced to tackle the complexities of Business Applications. Since the beginning of this century , Service Oriented Architecture (SOA) came to the fore to develop complex business applications. Microservice Architecture is the latest methodology to handle the complexity of modern Software Applications. One question may arise: why we need a new Software Development methodology suddenly? The short answer is that the whole ecosystem related to Software Development has changed significantly in the last decade. Nowadays, Software is developed using Agile methodology, deployed on Container+Cloud using CI/CD, persisted on NoSQL databases, rendered on a modern browser or smartphone and the machines are connected via a high-speed network. As a result of these factors, Microservice Architecture is born in 2012.

Microservice or Monolith:

There are mainly two groups of peoples who share opposite views about Microservice vs Monolith. For one group, Microservice Architecture is all about Cargo-Cult or Hype Driven Development which is just a playground for Technology addicted Developers. For another group, Microservice Architecture is the “ One Architecture to Rule them All ” which can take away the complexity of any Software Systems. In my opinion, Microservice and Monolith Architecture are complementary. For applications that are lean in the long term, Monolith Architecture is the right approach. On the other hand, for application which is large and complex or has the potential to become large and complex, Microservice Architecture is the right solution. Modern Software development is so vast that both Microservice Architecture and Monolith Architecture will co-exist in the same way as SQL and NoSQL co-exist.

Best Practices:

Designing Microservice Architecture the right way is quite challenging and difficult. On contrary to Monolith Architecture which gives one solution for all, Microservice Architecture gives a different solution for different problems. If the wrong solution is chosen, then the Microservice Architecture is just a ticking time bomb that is destined to explode. A badly designed Microservice Architecture is worse than a Monolith. Defining a set of Best practices for Microservice Architecture is also challenging. I have seen some conference talks where some renowned and respected Software Engineers have proposed Microservice Architecture best practices which are counterproductive.

Here I am proposing some best practices which will help to develop effective Microservice Applications where the target project is supposed to live more than 6 months and team size is moderate to large (6+ developers). Full disclosure, there also some other posts regarding Microservice Architecture best practices e.g. Characteristics of a Microservice Architecture by Martin Fowler or Microservices Patterns by Chris Richardson or Adopting Microservices at Netflix: Lessons for Architectural Design by Tony Mauro . There are also some great talks e.g. Microservices Patterns and Antipatterns by Stefan Tilkov , 10 Tips for failing badly at Microservices by David Schmitz , Principles of Microservices by Sam Newman .

Domain Driven Design:The foremost challenge to develop Microservices is to split a large, complex application into small, autonomous, independently deployable Modules. If Microservices are not split in the right way, there will be tightly coupled Microservices which will have all the disadvantages of a Monolith and all the complexities of Microservices aka Distributed Monolith . Fortunately, there is already a Solution which can greatly help in this regard. Eric Evans , a Software Engineering Consultant back then, had encountered recurring issues regarding software complexity in Business Applications across different companies and has summarized his valuable insight in the book “ Domain Driven Design: Tackling Complexity in the Heart of Software ” in 2004. The book outlined three Core Concepts:

  • The software development team should work in close co-operation with the Business department or Domain Experts.
  • The Architects/Developers and Domain Experts should first make the Strategic Design: Finding the Bounded Context and related Core Domain and Ubiquitous Language, Subdomains, Context Maps.
  • The Architects/Developers should then make the Tactical Design to decompose the Core Domain into fine-grained Building blocks: Entity, Value Object, Aggregate, Aggregate Root

A detail discussion of Domain-Driven Design is out of the scope of this post but you should read either the original DDD book Domain Driven Design: Tackling Complexity in the Heart of Software (Blue Book) of Eric Evans or a bit modern DDD book Implementing Domain Driven Design (Red Book) of Vaughn Vernon . If a large system is divided into Core Domain and Sub-domains and the Core Domain and Sub-domains are then mapped to one or more Microservices, then we will get the ideal loosely coupled Microservices.

Database per Microservice:After splitting the Complex application into Micro-Service Modules, the next challenge arises, what to do with the Database? Shall we share the database among Microservices or not. The answer to the question is the double edge sword. On the one hand, sharing the database among microservices will lead to strong coupling among the Microservices which is exactly the opposite of the goal of Microservices Architecture. Even a small change in a database will need synchronization among teams. Also, managing Transaction and Locking of a Database in one service is challenging enough. But managing Transaction/Locking among multiple distributed Microservices is a daunting task. On the other hand, if every Microservice has own database/private tables, then exchanging data between Microservices opens the pandora’s box of challenges. As a result, many prominent Software Engineers have advocated for a shared database among Microservices as a pragmatic solution. However, in my opinion, Microservice is all about sustainable and long term software development. As a result, every Microservice should have its Database (or Private Tables).

Micro Frontends:Unfortunately, most of the Backend developers have a backdated view about Frontend Development and think that Frontend Development is simple. As most Software Architects are Backend Developers, they have little regard for Frontend and Frontend is usually neglected in the Architecture Design. Very often in Microservice projects, backends are very finely modularized with their database but there is one Monolith Frontend. In the best case, they consider one of the hottest SPA (React, Angular, Vue) to develop the Monolith Frontend. The main problem of this approach is that Frontend Monolith is as bad as Backend Monolith as I have described previously . Also, when the Frontend needs to be modernized due to changes in Browser, then it requires a Big Bang modernization ( That is the reason why so many companies are still using the outdated Angular 1 framework ). The web is simple yet very powerful and inherently offers transclusion. There are many ways to develop SPA based Microfrontends: with iFrame, Web Components or via (Angular/React) Elements.

Continuous Delivery: One of the key USP of Microservice Architecture is that each Microservice can be deployed independently. If you have a system of e.g. 100 Microservices and only one Microservice needs to be changed, then you can update only one Microservice without touching the other 99. But deploying 100 Microservices independently without Automation (DevOps, CI/CD) is a daunting task. To take full advantage of this Microservice feature, one needs CI/CD and DevOps. Using Microservice Architecture without CI/CD, DevOps, Automation is like buying the latest Porsche and then drive it with hand-brake. It is no wonder that CI/CD is listed as one of the three prerequisites to use Microservice Architecture by Microservice Expert Martin Fowler .

Observability: One of the main drawbacks of Microservice Architecture is that Software Development became simple at the expense of Operations. With one Monolith, it is much simpler to monitor the application. But having many microservices run on containers, observability of the whole system became very crucial and complicated. Even Logging became complicated to aggregate logs from many containers/machines into a central place. Fortunately, there are already many Enterprise grade solutions in the market. For example, ELK/Splunk offers Logging for Microservices. Prometheus/App Dynamics offers industry-grade monitoring. Another very crucial observability tool in the Microservice world is Tracing. Often one API request to a microservice leads to several cascaded calls to other microservices. To analyze the latency of a Microservice system, it is necessary to measure the latency of each individual Microservice. Zipkin/Jaeger offers excellent tracing support for Microservices.

Unified Tech Stack: Microservice Architecture tells us that for a Microservice, take the programming language and framework best suitable for that microservice. This statement should not be taken literally. Sometime, a microservice may need a new Tech Stack e.g. for CPU heavy/high-performance tasks, programming language like C++/Rust may be chosen. If a Microservice works with Machine learning, maybe Python is a better choice. But using different programming languages/frameworks without any solid reason can lead to too many programming languages and frameworks without any real benefit. Think about the scenario where one microservice is developed using Spring Boot + Kotlin+ React + MySQL, the other one is with JakartaEE + Java + Angular + PostgreSQL, the next one with Scala + Play Framework + VueJS + Oracle then it will need a lots of effort to maintain the different programming language, databases, frameworks without too much gain.

Asynchronous Communication:Once the “ Database per Microservice ” option is taken, the next question arose, how to share data between the Microservices? Typically, one Microservice cannot work along. All the Microservices work together to fulfill the Business goal and to work together, they need to exchange data or trigger other Microservices to do a task. The easiest way to communicate between Microservices is via Synchronous REST API which is pragmatic but a short term solution. If Service A calls Service B, Service B calls Service C, Service C calls service D Synchronously, then latencies added up. Also as Microservices are mostly distributed systems, they could fail. Often Synchronous Microservices lead to failure cascading i.e. Failure in one Service can lead to failure in other services. Synchronous Communication between Microservices also leads to tight coupling between Microservices. For a long term solution, Microservices should communicate Asynchronously. There are many ways for Asynchronous communication between Microservices: via Message Queue e.g. Kafka, via asynchronous REST (ATOM) or CQRS.

Microservice First:Many experts argue that for greenfield (new) projects, it is better to start with a loosely coupled Monolithic Architecture as Microservice Architecture needs lots of initial effort to set up the operations. In their opinion, once the Project became mature enough, the “nicely” designed Monolith can easily be transformed into Microservices. However, in my opinion, this approach will fail in most cases. In practice, the modules inside Monolith will be tightly coupled which will make it difficult to transform it into Microservices. Also once an application is in production, it will be much more difficult to transform it into Microservices without breaking the application down. So, my advice will be to start with Microservices if there is a plan to use Microservice Architecture eventually.

Infrastructure over Libraries:During the early days of Microservice Software development, Netflix used mainly Java programming to develop Microservices. They also developed many libraries ( Netflix OSS Stack including Hystrix, Zuul ). Many companies follow through Netflix and started to use the librariesNetflix OSS. Later, many companies (including Netflix) found that Java is not the de facto language to develop Microservices due to its Bulky size and Cold-start problems. Netflix later moved on Polyglot Microservice paradigm and decided not to develop the Netflix OSS further which lead the follower companies into trouble. So, instead of investing heavily in a language-specific library (e.g. Java based Netflix OSS), it is wiser to use frameworks (e.g. Service Meshes, API gateway).

Organizational Considerations:Almost 50 years ago (1967), Melvin Conway gave an observation that the Software Architecture of a company is limited by Organizational Structure ( Conway’s Law ). Although the observation is 50 years old, MIT and Harvard Business School have recently found that the law is still valid in modern days. If an organization plans to develop Microservice Architecture, then it should make the team size accordingly (two “American” Pizza team: 7±2 person). Also, the team should be cross-functional and ideally will have Frontend/Backend Developer, Ops Engineering and Tester. Microservice Architecture will only work if the higher Management also changes their viewpoint and vision accordingly.

If you found this helpful, please share it on your favorite forums (Twitter, Facebook, LinkedIn). Comments and constructive criticisms are highly appreciated. Thanks for reading!


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK