35,99 €
Explore the concepts and tools you need to discover the world of microservices with various design patterns
Microservices are a hot trend in the development world right now. Many enterprises have adopted this approach to achieve agility and the continuous delivery of applications to gain a competitive advantage. This book will take you through different design patterns at different stages of the microservice application development along with their best practices.
Microservice Patterns and Best Practices starts with the learning of microservices key concepts and showing how to make the right choices while designing microservices. You will then move onto internal microservices application patterns, such as caching strategy, asynchronism, CQRS and event sourcing, circuit breaker, and bulkheads. As you progress, you'll learn the design patterns of microservices.
The book will guide you on where to use the perfect design pattern at the application development stage and how to break monolithic application into microservices. You will also be taken through the best practices and patterns involved while testing, securing, and deploying your microservice application. At the end of the book, you will easily be able to create interoperable microservices, which are testable and prepared for optimum performance.
This book is for architects and senior developers who would like implement microservice design patterns in their enterprise application development. The book assumes some prior programming knowledge.
Vinicius Feitosa Pacheco has been working as a software engineer since 2007. He has diverse experience with high-performance and high-availability software architectures, with an emphasis on microservices, and is passionate about teaching and talking about them. In the last 4 years, he has worked as an instructor in the field of software engineering techniques (including design patterns) and programming languages, such as Python, Java, and Go. He has been a speaker at large conferences such as PyCon Argentina, Pycon Colombia, EuroPython, RubyConf Brazil, the MobileConf, and QConSP.Sie lesen das E-Book in den Legimi-Apps auf:
Seitenzahl: 361
Veröffentlichungsjahr: 2018
Copyright © 2018 Packt Publishing
All rights reserved. No part of this book may be reproduced, stored in a retrieval system, or transmitted in any form or by any means, without the prior written permission of the publisher, except in the case of brief quotations embedded in critical articles or reviews.
Every effort has been made in the preparation of this book to ensure the accuracy of the information presented. However, the information contained in this book is sold without warranty, either express or implied. Neither the author, nor Packt Publishing or its dealers and distributors, will be held liable for any damages caused or alleged to have been caused directly or indirectly by this book.
Packt Publishing has endeavored to provide trademark information about all of the companies and products mentioned in this book by the appropriate use of capitals. However, Packt Publishing cannot guarantee the accuracy of this information.
Commissioning Editor: Merint MathewAcquisition Editor: Alok DhuriContent Development Editor: Akshada IyerTechnical Editor: Adhithya HaridasCopy Editor: Safis EditingProject Coordinator: Prajakta NaikProofreader: Safis EditingIndexer: Francy PuthiryGraphics: Jisha ChirayilProduction Coordinator: Aparna Bhagat
First published: January 2018 Production reference: 1290118
Published by Packt Publishing Ltd. Livery Place 35 Livery Street Birmingham B3 2PB, UK.
ISBN 978-1-78847-403-0
www.packtpub.com
To my mother, Vera Feitosa, for her sacrifices and for exemplifying the power of determination.
To my wife, Paola Katherine, for being my loving partner throughout our joint life journey.
To my friend and teacher, Claudio Cardozo, who gave me the opportunity to start my career and taught me how to win.
Mapt is an online digital library that gives you full access to over 5,000 books and videos, as well as industry leading tools to help you plan your personal development and advance your career. For more information, please visit our website.
Spend less time learning and more time coding with practical eBooks and Videos from over 4,000 industry professionals
Improve your learning with Skill Plans built especially for you
Get a free eBook or video every month
Mapt is fully searchable
Copy and paste, print, and bookmark content
Did you know that Packt offers eBook versions of every book published, with PDF and ePub files available? You can upgrade to the eBook version at www.PacktPub.com and as a print book customer, you are entitled to a discount on the eBook copy. Get in touch with us at [email protected] for more details.
At www.PacktPub.com, you can also read a collection of free technical articles, sign up for a range of free newsletters, and receive exclusive discounts and offers on Packt books and eBooks.
Vinicius Feitosa Pacheco has been working as a software engineer since 2007. He has diverse experience with high-performance and high-availability software architectures, with an emphasis on microservices, and is passionate about teaching and talking about them. In the last 4 years, he has worked as an instructor in the field of software engineering techniques (including design patterns) and programming languages, such as Python, Java, and Go. He has been a speaker at large conferences such as PyCon Argentina, Pycon Colombia, EuroPython, RubyConf Brazil, the MobileConf, and QConSP.
Alexander Sofras is a software architect living in picturesque Surrey, England. He has been programming for most of his life, working on independent games, academic computer vision projects, and financial analytics software. Most recently, he has helped deliver a market-leading business intelligence platform to investment banks worldwide and maintains that interest with a passionate support of blockchain technology. When not working, he enjoys catching up with old friends, going to the theater, painting, and gaming.
If you're interested in becoming an author for Packt, please visit authors.packtpub.com and apply today. We have worked with thousands of developers and tech professionals, just like you, to help them share their insight with the global tech community. You can make a general application, apply for a specific hot topic that we are recruiting an author for, or submit your own idea.
Preface
Who this book is for
What this book covers
To get the most out of this book
Download the example code files
Download the color images
Conventions used
Get in touch
Reviews
Understanding the Microservices Concepts
Knowing the application
Domain-driven design
Single responsibility principle
Explicitly published interface
Independently deploy, upgrade, scale, and replace
Independent deployment
Upgrade
Scale
The x-axis
The y-axis
The z-axis
Replace
Light weight communication
Synchronous
Asynchronous
Potentially heterogeneous/polyglot
Documentation of communication
Endpoints for web applications
Endpoints for mobile applications
Caching at the client level
Throttling for your client
Identifying anemic domains
Identifying the fat domains
Identifying microservice domains for the business
From domain to entity
Summary
The Microservice Tools
Programming languages
Proficiency
Performance
Development of practicality
Ecosystem
Scalability cost
Making choices for our application
Java
C#
Python
JavaScript
Go
Microservice frameworks
Python
Go
Logs
Handlers
Middleware
Tests
Package manager
Golang ORMs
Binary communication – direct communication between services
Understanding the aspect
Tools for synchronous communication
MessagePack
gRPC
Apache Avro
Apache Thrift
Direct communication alerts
Message broker – Async communication between services
ActiveMQ
RabbitMQ
Kafka
Caching tools
Memcached
Redis
Fail alert tools
Performance
Build
Components
Implementation gaps
The databases
Locale proof performance
Apache Benchmark
WRK
Locust
Summary
Internal Patterns
Developing the structure
Database
Programming language and tools
Project structure
The models.go file
The app.go file
The main.go file
Caching strategies
Applying cache
Caching first
Enqueuing tasks
Asynchronism and workers
CQRS – query strategy
What is CQRS?
Understanding CQRS
Advantages and disvantages of implementing CQRS
Event sourcing – data integrity
State mutation
Understanding event sourcing
Summary
Microservice Ecosystem
Separating containers
Layered services architecture
Separating UsersService
Creating Dockerfile
Using the containers
Storage distribution
Depreciating data
Regionalizing data
Bulkheads – using the ecosystem against failures
Designing for redundancy
Partitioning by criticality
Designing with isolation
Fail fast
Circuit breaker
Summary
Shared Data Microservice Design Pattern
Understanding the pattern
Breaking a monolithic application into microservices
Defining priorities
Setting deadlines
Defining the domain
Making experiments
Defining standards
Creating a prototype
Sending to production
Developing new microservices
Writing the microservice configuration file
Creating our model
Exposing the microservice data
Preparing the app to run
Creating the Dockerfile
Dependencies with requirements.txt
Data orchestration
Consolidating responses
Microservice communication
Storage sharing anti-pattern
Best practices
Testing
Pros and cons of the shared data pattern
Summary
Aggregator Microservice Design Pattern
Understanding the pattern
Applying CQRS and event sourcing
Separating the database
Writing the CommandStack container
Creating the news databases
Writing the QueryStack container
Refactoring the microservices
Selecting our requirements
Configuring the framework
Configuring the container
Writing the models
Creating the service
Preparing the database containers to work together
Microservice communication
Building the orchestrator
Preparing the microservice container
Writing the dependencies
Writing the configuration file
Writing the server access
Creating the orchestration controller
Applying the message broker
Making the containers work together
Updating the proxy/load balancer
Pattern scalability
Bottleneck anti-pattern
Best practices
Applying tests
Functional test
Writing the functional test
Integration test
Writing the integration tests
Pros and cons of aggregator design pattern
Pros of aggregator design pattern
Cons of aggregator design pattern
Summary
Proxy Microservice Design Pattern
The proxy approach
Dumb proxy
Smart proxy
Understanding our proxy
Proxy strategy to orchestrator
Microservice communication
Pattern scalability
Best practices
Purest pattern
Looking at the bottleneck
Caching in the proxy
Simple response
Pros and cons of proxy design pattern
Summary
Chained Microservice Design Pattern
Understanding the pattern
Data orchestration and response consolidation
Microservice communication
Pattern scalability
Big Ball of Mud anti-pattern
Best practices
Purest microservices
Requesting consistent data
Understanding chain in depth
Paying attention to the communication layer
Understanding the pros and cons of chained design pattern
Summary
Branch Microservice Design Pattern
Understanding the pattern
Data orchestration and response consolidation
Microservice communication
Pattern scalability
Best practices
Domain definition
Respect the rules
Attention to physical components
Keep it simple
Pros and cons of the branch design pattern
Summary
Asynchronous Messaging Microservice
Understanding the pattern
Domain definition – RecommendationService
Data definition – RecommendationService
Coding the microservice
Microservice communication
Applying the message broker and queues
Preparing the pub/sub structure
Pattern scalability
Process sequence anti-pattern
Best practices
Application definition
Don’t try to create responses
Keep it simple
Pros and cons of the asynchronous messaging design pattern
Summary
Microservices Working Together
Understanding the current application status
The public facing layer
The internal layer
Understanding general tools
Communication layer and accreditation between services
Understanding the data contract between services
Applying binary communication
Pattern distribution
Fail strategies
API integration
Summary
Testing Microservices
Unit tests
Preparing the containers for the integration test
Integration tests
End-to-end tests
Release pipelines
Signature tests
Monkey tests
Chaos Monkey
Summary
Monitoring Security and Deployment
Monitoring microservices
Monitoring a single service
Monitoring multiple services
Looking at the logs
Learning from the errors in the application
The metrics – Understanding the numbers
Security
Understanding JWT
Single Sign-On
Security of data
Defense for malicious requests – Identifying attacks
Explaining the interceptor
Web container
The API gateway
Deployment
Continuous integration/continuous delivery/continuous deploy
The blue/green deployment pattern and Canary releases
Multiple service instances per host
Service instance per host
Service instance per VM
Service instance per container
Summary
Other Books You May Enjoy
Leave a review - let other readers know what you think
Microservices is a software architecture strategy that has been in use for some years, with the goal of making services more scalable. Monolithic applications are losing ground to service-oriented projects, owing to the need for today's businesses to grow rapidly and dynamically. By designing this new architectural model, object-oriented principles, standards, decoupling, and responsibilities have become fundamental beyond automated testing.
Knowledge of microservices will enable you to create maintainable and scalable applications. By the end of this book, you will be fully capable of creating interoperable microservices, testable and prepared for a great performance.
This book is intended for readers who have experience with web development but want to improve their development techniques to create more maintainable and scalable applications. Readers are not expected to have development experience using microservices. The concepts and standards demonstrated in this book enable the reader to develop applications that are simple to understand and support a high volume of access.
Chapter 1, Understanding the Microservices Concepts, gives you an overview of microservice concepts. This chapter will help you to understand the concepts behind the architecture, for example, the client-first approach and domain definition.
Chapter 2, The Microservice Tools, takes you through the most common tools to be applied to microservices. Once you know your customers and how to define the domains of your application, it's time to make technical decisions—which programming language to use, which framework is appropriate, and how to validate whether your microservice template is functional or not.
Chapter 3, Internal Patterns, introduces you to internal microservice application patterns. We will address topics such as caching strategies, workers, queues, and asynchrony.
Chapter 4, Microservice Ecosystem, covers how to create a group of resilient and scalable microservices from a monolithic application. The chapter also focuses on how to separate microservices correctly in their respective containers and explains the distribution of the storage layer.
Chapter 5, Shared Data Microservice Design Pattern, covers a special case. Normally, microservices are totally independent in business, testing, communications, connections, and storage, but not in this pattern. The shared pattern is a special pattern for migration concepts, from monolithic to microservices; overall, it's a pattern for transitioning.
Chapter 6, Aggregator Microservice Design Pattern, covers the most simple and typical pattern, which basically consists of applying data orchestration to microservices.
Chapter 7, Proxy Microservice Design Pattern, covers the proxy pattern, which is very similar to the aggregator pattern. When thinking of the structure, it's used when it isn't necessary to join data to send it to the end user. Understanding the differences between the proxy pattern and the aggregator pattern, as well as the correct request redirection for the responsible microservice, is the goal of this chapter.
Chapter 8, Chained Microservice Design Pattern, covers the chained pattern, where the information that will be sent to the client can be consolidated into a chain. Explaining information consolidation is the main objective of this chapter.
Chapter 9, Branch Microservice Design Pattern, covers the branch pattern, which is a mix of the aggregator and chain patterns. It's normally used when, in the backend, a microservice doesn't have all the data to complete a task or should directly notify another microservice. This chapter explains when this pattern composition is useful and the ways in which it could be good for the business.
Chapter 10, Asynchronous Messaging Microservice, explains one of the most complex patterns: applying asynchronism at the microservice level. This chapter is about how microservices can communicate asynchronously using messaging tools.
Chapter 11, Microservices Working Together, is a conclusion on patterns. After learning all about the microservice patterns, we will see how to put all the microservices to work together.
Chapter 12, Testing Microservices, explains the most plausible possibilities for testing and how to make this part, which is so important, simple.
Chapter 13, Monitoring Security and Deployment, covers what is necessary and best practices to maintain microservices in production.
Having some knowledge of OOP and package structure in Go (golang) will make reading this book more interesting.
You can download the example code files for this book from your account at www.packtpub.com. If you purchased this book elsewhere, you can visit www.packtpub.com/support and register to have the files emailed directly to you.
You can download the code files by following these steps:
Log in or register at
www.packtpub.com
.
Select the
SUPPORT
tab.
Click on
Code Downloads & Errata
.
Enter the name of the book in the
Search
box and follow the onscreen instructions.
Once the file is downloaded, please make sure that you unzip or extract the folder using the latest version of:
WinRAR/7-Zip for Windows
Zipeg/iZip/UnRarX for Mac
7-Zip/PeaZip for Linux
The code bundle for the book is also hosted on GitHub athttps://github.com/PacktPublishing/Microservice-Patterns-and-Best-Practices. We also have other code bundles from our rich catalog of books and videos available athttps://github.com/PacktPublishing/. Check them out!
We also provide a PDF file that has color images of the screenshots/diagrams used in this book. You can download it here: https://www.packtpub.com/sites/default/files/downloads/MicroservicePatternsandBestPractices_ColorImages.pdf.
There are a number of text conventions used throughout this book.
CodeInText: Indicates code words in text, database table names, folder names, filenames, file extensions, pathnames, dummy URLs, user input, and Twitter handles. Here is an example: "The config.py file is where the settings for each development environment exist."
A block of code is set as follows:
class TestDevelopmentConfig(TestCase): def create_app(self): app.config.from_object('config.DevelopmentConfig') return app def test_app_is_development(self): self.assertTrue(app.config['DEBUG'] is True)
When we wish to draw your attention to a particular part of a code block, the relevant lines or items are set in bold:
@patch('views.rpc_command')
def test_sucess(self,
rpc_command_mock
): """Test to insert a News."""
Any command-line input or output is written as follows:
$ docker-compose -f docker-compose.yml up --build –d
Bold: Indicates a new term, an important word, or words that you see onscreen. For example, words in menus or dialog boxes appear in the text like this. Here is an example: "The following screenshot represents the interface of DATADOG:"
Feedback from our readers is always welcome.
General feedback: Email [email protected] and mention the book title in the subject of your message. If you have questions about any aspect of this book, please email us at [email protected].
Errata: Although we have taken every care to ensure the accuracy of our content, mistakes do happen. If you have found a mistake in this book, we would be grateful if you would report this to us. Please visit www.packtpub.com/submit-errata, selecting your book, clicking on the Errata Submission Form link, and entering the details.
Piracy: If you come across any illegal copies of our works in any form on the Internet, we would be grateful if you would provide us with the location address or website name. Please contact us at [email protected] with a link to the material.
If you are interested in becoming an author: If there is a topic that you have expertise in and you are interested in either writing or contributing to a book, please visit authors.packtpub.com.
Please leave a review. Once you have read and used this book, why not leave a review on the site that you purchased it from? Potential readers can then see and use your unbiased opinion to make purchase decisions, we at Packt can understand what you think about our products, and our authors can see your feedback on their book. Thank you!
For more information about Packt, please visit packtpub.com.
In the programming world, design patterns are very common. This is no different when it comes to web development. With the internet popularity and then after Web 2.0, many patterns developed for the web were widely disseminated with the intention of making the development more dynamic and simple for new features.
Patterns such as MVC (Model-View-Controller), HMVC (Hierarchical Model View Controller), and MTV (Model Template View), among others, inspired the creation of various frameworks such as Django, Ruby on Rails, Spring MVC, and CodeIgniter, for example.
All these frameworks are excellent for creating web applications quickly and without great concern for application architecture. This is because much of the work is done by the framework. All these patterns were thought to be only applied to a web application with all the required business rules. Typically, these applications, where all business rules are on the same code base, are called monoliths.
For years, the monoliths absolutely reigned in the web development ecosystem. Many companies looking for space in the market validated products by creating software on these full-stack frameworks. Many monolithic software applications went to the internet and, over time, a word has emerged as a problem for these monolithic applications: success.
Success is a very problematic word for monolithic applications because of the following difficulties:
Maintenance on the same code base can be complicated due to merges that are difficult to apply
Implementing new features is increasingly complex and may take longer than expected
Application scalability
Deploying new features without impacting what is already online is challenging
Architectural changes are always very complex
These are just some examples of the kinds of problems that may exist in a monolithic application. These difficulties are a good motivation to migrate monolithic application architecture to microservices. Increasingly, adopting microservices has been the path taken by the software engineering industry and most companies, where the word success has meant trouble for the provision of practice and scalable business. The advantages of the microservices architecture are many:
An exclusive business domain for each microservice, facilitating the implementation of new features
Better definition of business without cyclic dependency between them
Independent deployment
Simplicity to identify errors
Technological independence among microservices
Independence between teams
Implementation of isolation
Possible scalability for
specific
microservice
Showing you how to make the transition from a monolithic application to microservices, applying appropriate patterns, and showing you possible implementation misconceptions, is the aim of this book. All modifications will be applied to the same project, a news portal that has interactivity, a recommendation system, authentication, and an authorization system. Throughout the book, you will be shown every step of this migration when applying design patterns, and both internal and external migrations when it comes to the communication layer between microservices. Of course, to get to that point, you first need to understand some important concepts to efficiently implement the microservices.
It is time to get to know the application that will be used throughout the book. This application will be the source of all explanations of concepts and all practical code that will be developed in the book. The base system is a news portal that consists of, basically, three areas:
News
: This is the news itself.
Recommendations
: These are responsible for storing user preferences and thus are able to offer specific news to users or even compose a completely unique home page according to the user profile.
User
: This is the basic registration information of a user.
All the application's business is on the same source code, that is, a monolithic software. The application was developed on the Django Framework, using PostgreSQL as a database, and Memcached as cache, which is only applied to the database layer.
With this structure, if there is an overload on the level of recommendations, all the applications must be scaled, and not only the part referring to the recommendations, because the application is monolithic. Another problem is that if one commits and incurs a problem, it propagates errors in segments that have no relationship with deficiency in the composition of domains. Something expensive for the application changes in the stack. If you want to change the type of cache used, then all other caches will be lost.
The OOP concepts can be applied to the design of microservices, not only in the internal design of the application but also in the architecture and the business division. When it comes to Domain-Driven Design (DDD), it is no different.
DDD came from the book Domain-Driven Design written by Eric Evans. The Evans book is a large catalog of patterns, coming from over 20 years of the author's experience developing software using OOP. It is very important to note that OOP is not only inheritance, interfaces, or anything else of the type. OOP's main ideas are as follows:
Code alignment with the business
Favoring of reuse
Minimal coupling
Evans's book is divided into four parts:
Putting the domain model to work
Model building blocks-driven design
Refactoring to deeply understand the model
Strategic design
All the preceding parts can be applied to microservices. Model building blocks-driven design and refactoring to deeply understand the model internally applies to microservices, that is, the code itself. The others can be applied either internally in the software, but can also be used to design microservices and their signatures.
The first part is emphatic about the need to use ubiquitous language for communication between those responsible for the business, and the engineering team responsible for the development. This language consists of terms that are part of everyday conversations between business experts and development teams. Everyone should use the same terms in spoken language, the source code, and the signing of microservices. This means that when the business specialist says, The home page should seek breaking news with the title and description the ubiquitous language applied in the code will be represented as follows:
Microservice news
Endpoint recent news
Payload with attribute title and description
This type of communication will mitigate errors in understanding requirements and maintain the general knowledge about application unison. Another important point is that, with the ubiquitous language, identifying areas is simpler because, as interactions have standardized terms, a word may indicate something new.
The fourth part will clarify the boundaries of a microservice and ease of management between the parties. Besides having a ubiquitous language used in the development of a consistent and adequate microservice, some strategies are necessary for dealing with complex systems, where multiple pieces of software (developed by several teams) interact. Delimit the context in which each team works and what is the degree of interaction between these teams and these contexts? Of the many tools that the DDD provides us, three are more prominent for efficient microservices:
Context maps
: These are the communication paths between microservices with appropriate interactions between microservices teams. After the analysis of the areas are already defined, the team can choose to be dependent on another team for domain language.
Anti-corruption layer
(
ACL
): This is the function that translates foreign concepts for an internal model to provide loose coupling between the domains.
Interchange context
: This provides an environment for both teams and discusses the meaning of each foreign
term
and translates the languages of microservices.
Thinking about the application we are working on, the DDD would be very useful for avoiding misunderstandings in the interpretation of how microservices should work. A common misconception in news systems is about the terms user and author; both are users of the system, one as a player and another as publisher, but if a product owner says, "The user published bad news" we have a problem in communication between product teams and development teams. This may result in an inconsistent microservice within the business itself. Another problem is that the phrase spoken earlier by the product owner suggests an unwanted feature, which is a user who can publish materials. DDD is just thinking about defining the microservice domain and standardizing terms to generate consistent internal models and an API with solid meaning. The difference in meanings or representations for the same attribute is known as a semantic gap, and is exactly what we are dealing with throughout the chapter.
Besides the aspects mentioned previously, helping to create microservices intact, there is a feature of DDD which undoubtedly is the most important when it comes to designing microservices. The concept of bounded contexts is essential to determine the range of a microservice and in the end, the responsibility that the microservice has. The most important thing is understanding that without these, coupling limits will be high and concepts such as single responsibility can never be achieved.
Another principle that is applied to microservices and comes from the OOP world is specifically the letter S in SOLID. What could be thought before the class level should now be through the application level, so that microservices can be really micro in terms of what really matters at the domain level.
The microservice domain cannot be large; on the contrary, it must be limited. The limits that were cited in DDD return to be applied now and with more intensity. Precisely, the limits in the microservice domain is what will make this application sensitive to changes and open to the perception of possible errors.
It is a very common difficulty in maintaining pure microservices in their domains. The natural tendency, either by habit or ignorance, is to try to group all the business rules or similar codes in the same microservice, without even understanding whether they are part of the same domain.
To illustrate, think of the application on which we are working, our news portal. News and recommendations virtually work together all the time. Recommendations always put together some news that has some of the related labels. At first, it makes sense, because as the recommendations are always related to the news, apparently this does not cause a problem and, moreover, could reduce problems such as network latency. The main concept could be represented by the following diagram:
However, creating a microservice containing news and recommendations will generate unnecessary and very expensive engagement for future changes. In a simple demonstration exercise, we can think of a number of business changes with which this engagement would generate problems.
A new business requirement arose. Those responsible for thinking about the product had an idea to use recommendations to compose a personal home page according to the news that stands out most in our portal. So, the recommendations aren't just connected to the news anymore, but to the user too. With this new requirement, some problems relating to the coupling done previously will emerge at the level of deployment, scalability, and maintenance features code.
Based on the new requirement mentioned previously, it is clear that news and recommendations work together, but they are totally different domains from each other. Identifying areas to apply the principle of sole responsibility for each microservice is crucial to application architecture. The following diagram shows the main idea of the microservice distribution:
Working together and in concert, Home requests information either from News or Recommendation. There are some forms of data orchestration that we will come to later in the book, but now it is important to understand that Home can consult separate services and compose the received data conveniently.
The separation of News and Recommendation results in an application where the deploy becomes a simpler, more consistent code base and the fully defined and specific business domain for a purpose.
The published interface is a term that usually generates a lot of confusion with the public interface. It is critical to understand the difference between the two terms: microservices and distributed source systems.
Think of a microservice. All internal microservice code will be used and shared among the development team; class methods are abstractions or attributes and can all be part of the public interface between teams. This is because of the convenience to notify and make changes in the event of possible refactoring. There is no point in generating a lot of bureaucracy at the development level, just for the features to gain speed in the implementation.
When it comes to the published interface, however, it is different. The published interface is what the microservice developers release. The published interface is what will be consumed by the internet. A good example is theSingle Sign-On(SSO) API.Imagine that APIs suffer sudden changes to implement new features such as security and that these changes do not have a good system of alerts for all customers of these APIs. It is simply not appropriate to use this SSO service, because of updates, the API client suffers from incompatibilities.
Published interfaces should have more control and be more resilient to refactoring. Usually, they apply only to external application clients. The less possible changes in the level of the signatures, the better. The following diagram shows the possibility of maintaining the published interface signature:
Some concepts are important for published interfaces, such as:
Published versioned interfaces
: An efficient version control to indicate when something, deprecated is key. Not only that, but it will also indicate what the new version is and when the deprecated version will be deactivated permanently.
Small published interfaces
: A large payload is much more susceptible to change than a more specialized payload. Applying the concepts of DDD on these payloads is very healthy.
Published external interfaces
: Do not create the concept of published interfaces for internal development teams. This creates a slow process of change and implementation features.
It is common to think of the concept of public interface versus published interface as something similar to the public versus private OOP, but they are actually different. The published interface does not mean depriving the client of resources, but rather directing the customer to consume adequate resources resiliently.
Discussing this topic is very interesting and relevant to the microservices ecosystem. Deploy, upgrade, replace, and scale are great advantages that microservices have over monolithic systems, when it comes to most aspects of their functions.
A standard aspect of the professional software development world is version control. This is because developers are pretty much working on features and maintenance of legacy code in the same application, at the same time.
In the end, a landmark (tag) is created in the application and this landmark is sent to production; this process is called deployment. At that same point, some problems may arise.
Let's consider a situation; in our news portal, one developer is working on an important feature for recommendations while another developer is working on fixing bugs. Both commit to hitting the same target. At the time of deployment, there is a major problem. The bug in news was not fixed successfully, which prevented the new feature from going into production. Software can be thoroughly tested, and even though much attention is given to each task, the unforeseen can still happen.
When it comes to microservices, this kind of problem is reduced drastically. Rethink the same scenario.
On our news portal, one developer is working for a few weeks on an important feature for the Recommendations microservice and another developer is working on a bug in the news microservice. Both commit to hitting the same target, each in their respective microservice; however, we still encounter a problem during deployment. The bug in news was not fixed successfully, which prevents the new version of the news microservice from going into production, but the Recommendations microservice is perfect and the new feature goes into production without any problems.
This is perhaps one of the main positive points when it comes to independent deployment. Of course, the complexity of maintaining the operation of multiple machine instances generates more complexity, but if you think about it, in a world of cloud computing, the complexity of multiple instances would be the same even though the application was monolithic, as the need for scalability is always real.
Later in the book, we see some patterns of deployment; we just focus on reducing complexity and practicality to perform deploys continuously.
There is an item that is mandatory for microservices to really be microservices; this item is an independent upgrade. Some rules must be followed to upgrade as independently as possible:
Never share libraries between microservices
: This means that each microservice has a stack that is totally independent of any other microservice. Sharing libraries is an error that generates high coupling and problems at the time of deployment. The microservices can start with the same stack, although it is usually best to analyze the domain and the data structure to see if the stack proposal is compatible or not. However, starting with the same stack does not mean keeping concurrent versioning. Another aspect that needs attention is to completely avoid creating business components on specific versions of a library stack. This approach prevents any technological developments in the microservice and means that, for example, security patches cannot
be applied.
Strong delimitation of microservice domains
: We have already talked about bounded contexts, but it is worth reiterating again. The microservice limits are essential to determine whether the domain really is compatible with microservices architecture, or whether what is being designed is only a monolithic part decoupled from the rest. The loose coupling is what defines a microservice subject to upgrades and changes in the level of business without major conflicts with the ecosystem, in which the microservice is inserted.
Establish a client-server relationship between microservices
: This means that each microservice is a separate application and has complete autonomy over itself. When a microservice depends on another microservice's business resolutions, we have an alert point. The microservices can communicate with each other freely to ask for information, but never to solve business issues. When a microservice sends a message to another and is waiting
for the answer to complete a task, there is an error. This error is critical and will result in scalability and transactional issues.
When a microservice sends a message to another, there is a very strong idea there: asynchrony. As one microservice server performs tasks and provides information, another client microservice requests information. When the two faces—server and
client—are intrinsically linked to a microservice, there is a design error.
Deploy in separate containers
: This approach not only facilitates the independent structure of a microservice, but also ensures that a fault in one microservice is totally individual, without disrupting an entire microservice pool. When we speak of separate containers, we are not necessarily talking about virtualization. The containers in question can be physical; it is a matter of the strategy and resources of a company, but the fact is that it is not healthy to keep more than one microservice in a container. It is important to remember that failures will occur, and when they occur, it is important to be prepared to mitigate the failures. Microservices as a group in a single container means that there will be a failure when a cyclomatic microservices burst occurs.
Separate containers are also essential for upgrading tools that are part of the stack, but that are not properly coded, such as databases and caches.
Scalability of speech is a common approach; see The Scale Cube which is discussed in the book The Art of Scalability from Martin L. Abbott and Michael T. Fisher. The concepts of the Scale Cube are fully applicable to microservices, and web applications in general, that need to be scalable:
The concept of a scale cube shows that there are basically three forms of scalability: x-axis, y-axis, and z-axis. To better understand each of these three approaches, we will use some diagrams.
On the x-axis, this strategy targets the horizontal scalability with the same application server replicated n times in full and in a balanced order of 1/n.
The problem with this strategy is that resources such as databases and caches will be required, since the number of applications that accesses these features gradually increases, as necessary, to scale. For this strategy, caches require more memory and databases need a pool of greater connections, something that does not always result in a benefit:
In this strategy, a verb or route is used by the balancer to identify where to go with the request. The following image represents the y-axis:
The principle does not seem to be very scalable, but it is exactly the junction with the y-axis and x-axis that is used to scale microservices.
This join between y-axis and x-axis allows us, occasionally, to bring scalability to just part of the microservices. In the following diagram, it can be seen that News was the most scaled microservice, followed by Recommendations, but Users have no major changes. This type of scalability technique greatly reduces the drawbacks of shared resource access, as each microservice structure manages and uses only its own resources, such as caches and databases. Take a look at the following diagram:
The z-axis is very similar to the x-axis when it comes to scalability structure, as it distributes exactly the same code on each server. The big difference is that each server responds to a specific subset of data. In this strategy, the search is providing not only scalability regarding the application, but also the data you use.
The following diagram shows a little example:
This strategy is not entirely ruled out when it comes to microservices, but its use is a little different. The applicability ends up not being on the verbs, but on geolocation. This means that, in a global application, the database of a microservice is distributed by region and is preferably available for this region, that is, people who access the website in Europe will, preferably, see the European news.
The definition of how microservices are scaled is directly linked to business strategy. From a technical point of view, the focus is to provide a flexible software strategy allowing changes as they certainly occur.
Updates to microservices are normal, but sometimes these updates may compromise the health of a microservice. New features can cause the microservice to absorb many responsibilities that go beyond the original domain idea.
A common mistake is adding new features and invalidating old ones without removing them completely. Some features of the development processes become more clear when a new microservice is created that is intended to replace an old one.
This process may seem more time consuming, however, it is very healthy for the application as a whole. Rethink whether old features still make sense, remove any zombie code which has no more relevance to the business, becoming consumers of resources and aggregators of complexity.
The replace process, when it comes to microservices, is very simple, as shown in the following diagram:
The concept applied to the replacement process is very simple. With control as the balancing layer, which will direct 90% of the requests for the old microservice and 10% for the new microservice, it is possible to monitor and analyze how mature a new application is and if no feature has been forgotten or has unwanted side effects.
