Microservices has become an increasingly popular subject over the last few years. As with any new architectural concept, there is plenty of room for misunderstanding. Even the term microservices is confusing. Newcomers are often unsure about the appropriate size of a microservice(hint: it's not actually about the size of the code base) and can get stuck on how to get started with this architectural style.
Service-oriented architectures are nothing new. Web services were being promoted by various companies in the 1990s as a solution to large, inflexible code bases. The promise was that web services would provide reusable capabilities that could be easily consumed by your code bases. Technologies such as SOAP and WSDL started gaining adoption, but never seemed to deliver on the ease of use promise. Meanwhile, open source languages such as PHP, Ruby, and Python with frameworks such as Symfony, Rails, and Django made developing monolithic web-centric code bases easier.
Fast forward a couple of decades and we started seeing a renewed interest in services. So, what's changed? For one, with the advent of rich web and mobile applications, every system is now a distributed system. Thanks to the advent of cloud computing, compute and storage resources are cheaper than they've ever been. Containers are changing the way we think about deploying and operating our services. Many consumer services are outgrowing their monolithic code bases, and teams are finding them hard to scale. Microservices can help with many of these challenges.
Microservices aren't a panacea. While they have many benefits(which we'll discuss later), they also introduce some specific challenges. Before deciding to make the move to microservices, it's important to have certain infrastructure and tooling in place. Martin Fowler has written about Microservices Prerequisites (https://martinfowler.com/bliki/MicroservicePrerequisites.html), as has Phil Calcado (http://philcalcado.com/2017/06/11/calcados_microservices_prerequisites.html). I won't repeat what others have written; instead, I will just say that it pays to have a certain amount of automation and monitoring in place before you start developing microservices. Your teams should be comfortable sharing on-call duties and you should have a system for managing alerts and escalations, such as PagerDuty (http://pagerduty.com/).
The various benefits of microservices are as discussed in the next sections.
In a monolithic code base, scaling is anall-or-nothing approach. Microservices make it easier to scale separate parts of your application based on their own needs. For example, you might have a particular part of your application that is in the critical path of every user request(that is, authentication/authorization services), whereas other parts are only used by a subset of your users(that is, search or messaging). Different traffic patterns will translate to different scaling needs and different techniques that should be used to scale a service. A service that requires a read for every request from a user should use a data store that makes reads cheap. Services that do not need to provide strongly consistent results can take advantage of extensive caching.
When teams of engineers are working on separate code bases with separate deployments, they are able to make a lot of decisions independently, without the need to coordinate with other teams in the organization. This means that engineers are free to commit code, design their own code review processes, and deploy to production without always needing to coordinate. In a monolith, it's not uncommon for engineers to have to get their changes into a queue that is then deployed at a set time with changes from other teams. If something goes wrong(poison deploys are one of the most common causes of outages), then the whole change set gets rolled back, delaying work by multiple teams. Microservices help you avoid this by allowing teams to move with more autonomy.
When a monolith fails, it tends to fail completely. A database is unavailable, and then the application tries to use stale connections in a connection pool, eventually the threads or processes serving requests lock up, and users are left with a white screen of death or a inoperable mobile application. Microservices allow you to decide on a case-by-case basis how a failure in a particular part of your application should be treated. If your service cannot reach a database, perhaps it's better to return a stale cache, or an empty response. If your service has to throw up its hands and start returning HTTP 503 responses, upstream services can respond by applying back pressure, allowing the service to catch up. Microservices give you much more freedom to isolate failures in your system, resulting in a happier experience for your users.
This book will serve as a handy reference for many of the subjects that will come up as you develop microservices. We'll start with recipes that will help you make the transition from a monolith to a suite of microservices. Subsequent chapters will address specific areas or challenges that come up when choosing how best to architect and manage your microservices. Recipes that cover code will include working, simple, tested examples that you can use in your own applications. My hope is that this book will help you think about, plan, and execute the development of microservice-based applications. Enjoy!
If you are a developer who would like to build effective and scalable microservices, then this book is for you. Basic knowledge of the microservices architecture is assumed.
Chapter 1, Breaking the Monolith, shows how to make the transition from monolith to microservices, with the recipes focused on architectural design. You'll learn how to manage some of the initial challenges when you begin to develop features using this new architectural style.
Chapter 2, Edge Services, teaches you how to use open source software to expose your services to the public internet, control routing, extend your service's functionality, and handle a number of common challenges when deploying and scaling microservices.
Chapter 3, Inter-Service Communication, discusses recipes that will enable you to confidently handle the various kinds of interactions we're bound to require in a microservice architecture.
Chapter 4, Client Patterns, discusses techniques for modeling dependent service calls and aggregating responses from various services to create client-specific APIs. We'll also discuss managing different microservices environments and making RPC consistent with JSON and HTTP, as well as the gRPC and Thrift binary protocols.
Chapter 5, Reliability Patterns, discusses a number of useful reliability patterns that can be used when designing and building microservices to prepare for and reduce the impact of system failures, both expected and unexpected.
Chapter 6, Security, includes recipes that will help you learn a number of good practices to consider when building, deploying, and operating microservices.
Chapter 7, Monitoring and Observability, introduces several tenants of monitoring and observability. We'll demonstrate how to modify our services to emit structured logs. We'll also take a look at metrics, using a number of different systems for collecting, aggregating, and visualizing metrics.
Chapter 8, Scaling, discusses load testing using different tools. We will also set up auto-scaling groups in AWS, making them scalable on demand. This will be followed by strategies for capacity planning.
Chapter 9, Deploying Microservices, discusses containers, orchestration, and scheduling, and various methods for safely shipping changes to users. The recipes in this chapter should serve as a good starting point, especially if you're accustomed to deploying monoliths on virtual machines or bare metal servers.
This books assumes basic knowledge of microservices architectures. Other instructions are mentioned in the respective recipes as needed.
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/Microservices-Development-Cookbook. We also have other code bundles from our rich catalog of books and videos available athttps://github.com/PacktPublishing/. Check them out!
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: "Open the newly created service object in the app/services/attachments_service.rb
file and move the responsibility for uploading the file to theAttachmentsService#upload
method."
A block of code is set as follows:
class AttachmentsService def upload(message_id, user_id, file_name, data, media_type) message = Message.find_by!(message_id, user_id: user_id) file = StorageBucket.files.create( key: file_name, body: StringIO.new(Base64.decode64(data), 'rb'), public: true )
Any command-line input or output is written as follows:
brew install docker-compose
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: "Installing and managing a Kubernetes cluster is beyond the scope of this book. Luckily, a project called Minikube allows you to easily run a single-node Kubernetes cluster on your development machine."
In this book, you will find several headings that appear frequently (Getting ready, How to do it...).
To give clear instructions on how to complete a recipe, use these sections as follows:
This section tells you what to expect in the recipe and describes how to set up any software or any preliminary settings required for the recipe.
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.