Building Microservices: Designing Fine-Grained Systems
Rate it:
Open Preview
Read between August 6 - September 13, 2022
1%
Flag icon
Microservices are independently releasable services that are modeled around a business domain.
2%
Flag icon
From the outside, a single microservice is treated as a black box. It hosts business functionality on one or more network endpoints (for example, a queue or a REST API, as shown in Figure 1-1), over whatever protocols are most appropriate.
2%
Flag icon
Independent deployability is the idea that we can make
2%
Flag icon
a change to a microservice, deploy it, and release that change to our users, without having to deploy any other microservices.
2%
Flag icon
If you take only one thing from this book and from the concept of microservices in general, it should be this: ensure that you embrace the concept of independent deployability of your microservices. Get into the habit of deploying and releasing changes to a single microservice into production without having to deploy anything else. From this, many good things will follow.
2%
Flag icon
To ensure independent deployability, we need to make sure our microservices are loosely coupled: we must be able to change one service without having to change anything else. This means we need explicit, well-defined, and stable contracts between services.
2%
Flag icon
By modeling services around business domains, we can make it easier to roll out new functionality and to recombine microservices in different ways to deliver new functionality to our users.
2%
Flag icon
Arguably, with microservices we have made a decision to prioritize high cohesion of business functionality over high cohesion of technical functionality.
2%
Flag icon
Don’t share databases unless you really need to. And even then do everything you can to avoid it. In my opinion, sharing databases is one of the worst things you can do if you’re trying to achieve independent deployability.
3%
Flag icon
Derza Arsad
Most old software
3%
Flag icon
In my experience, a distributed monolith has all the disadvantages of a distributed system, and the disadvantages of a single-process monolith, without having enough of the upsides of either.
4%
Flag icon
Understanding the tools that are available to help you get the most out of this architecture is going to be a key part of making any implementation of microservices a success.
4%
Flag icon
I strongly advocate the implementation of a log aggregation system as a prerequisite for adopting a microservice architecture.
4%
Flag icon
Be cautious about taking on too much new technology when you start off with microservices. That said, a log aggregation tool is so essential that you should consider it a prerequisite for adopting microservices.
4%
Flag icon
These systems allow you to collect and aggregate logs from across all your services, providing you a central place from which logs can be analyzed, and even...
This highlight has been truncated due to consecutive passage length restrictions.
5%
Flag icon
Microservices allow us to better align our architecture to our organization, helping us minimize the number of people working on any one codebase to hit the sweet spot of team size and productivity.
6%
Flag icon
I feel that microservice architectures are often a bad choice for brand-new products or startups.
7%
Flag icon
By keeping the number of assumptions small, it is easier to ensure that we can change one module without impacting others.
7%
Flag icon
We want related behavior to sit together, and unrelated behavior to sit elsewhere.
7%
Flag icon
A structure is stable if cohesion is strong and coupling is low.
7%
Flag icon
Cohesion applies to the relationship between things inside a boundary (a microservice in our context), whereas coupling describes the relationship between things across a boundary.
7%
Flag icon
Domain coupling describes a situation in which one microservice needs to interact with another microservice, because the first microservice needs to make use of the functionality that the other microservice provides.
7%
Flag icon
Temporal coupling has a subtly different meaning in the context of a distributed system, where it refers to a situation in which one microservice needs another microservice to do something at the same time for the operation to complete.
8%
Flag icon
One of the ways to avoid temporal coupling is to use some form of asynchronous communication, such as a message broker.
8%
Flag icon
“Pass-through coupling”9 describes a situation in which one microservice passes data to another microservice purely because the data is needed by some other microservice further downstream.
8%
Flag icon
The major issue with pass-through coupling is that a change to the required data downstream can cause a more significant upstream change. In our example, if Shipping now needs the format or content of the data to be changed, then both Warehouse and Order Processor would likely need to change.
8%
Flag icon
One way to hide this detail would be to have Warehouse take in the required information as part of its contract, and then have it construct the Shipping Manifest locally, as we see in Figure 2-6.
8%
Flag icon
One final approach that could help reduce the pass-through coupling would be for the Order Processor to still send the Shipping Manifest to the Shipping microservice via the Warehouse, but to have the Warehouse be
8%
Flag icon
totally unaware of the structure of the Shipping Manifest itself.
8%
Flag icon
Common coupling occurs when two or more microservices make use of a common set of data.
8%
Flag icon
A potential solution here would be to ensure that a single microservice manages the order state.
9%
Flag icon
The easy fix here is to have the Warehouse send requests to the Order service itself, where we can vet the request but
9%
Flag icon
also hide the internal detail, making subsequent changes to the Order service much easier.
9%
Flag icon
Ubiquitous language refers to the idea that we should strive to use the same terms in our code as the users use.
9%
Flag icon
By working the real-world language into the code, things became much easier.
9%
Flag icon
We want to treat aggregates as self-contained units; we want to ensure that the code that handles the state transitions of an aggregate are grouped together, along with the state itself. So one aggregate should be managed by one microservice, although a single microservice might own management of multiple aggregates.
9%
Flag icon
In Figure 2-13, we have changed things to make the relationship explicit. Rather than a vanilla ID for the customer reference, we instead store a URI, which we might use if building a REST-based system.
9%
Flag icon
Bounded contexts hide implementation detail. There are internal concerns—for example, the types of forklift trucks used are of little interest to anyone other than the folks in the warehouse. These internal concerns should be hidden from the outside world, which doesn’t need to know, nor should it care.
10%
Flag icon
The aggregate is a self-contained state machine that focuses on a single domain concept in our system, with the bounded context representing a collection of associated aggregates, again with an explicit interface to the wider world.
10%
Flag icon
one microservice can manage one or more aggregates, but we don’t want one aggregate to be managed by more than one microservice.
11%
Flag icon
Volatility-based decomposition has you identify the parts of your system going through more frequent change and then extract that functionality into their own services, where they can be more effectively worked on.
11%
Flag icon
It therefore follows that we must take into account the existing organizational structure when considering where and when to define boundaries, and in some situations we should perhaps even consider changing the organizational structure to support the architecture we want.
12%
Flag icon
Prematurely decomposing a system into microservices can be costly, especially if you are new to the domain. In many ways, having an existing codebase you want to decompose into microservices is much easier than trying to go to microservices from the beginning for this very reason.
13%
Flag icon
We can mitigate the likely impact of this increase in latency by allowing for SKUs to be looked up in the Catalog microservice in bulk, or perhaps even by caching the required album information locally.
14%
Flag icon
We could use a soft delete in the Album table so that we don’t actually remove a record but just mark it as deleted. Another option could be to copy the name of the album into the Ledger table when a sale is made, but we would have to resolve how we wanted to handle synchronizing changes in the album name.
14%
Flag icon
Unfortunately, as we’ll cover in depth in “Database Transactions”, distributed transactions are not only complex to implement, even when done well, but they also don’t actually give us the same guarantees that we came to expect with more narrowly scoped database transactions.
14%
Flag icon
With a reporting database, we instead create a dedicated database that is designed for external access, and we make it the responsibility of the microservice to push data from internal storage to the externally accessible reporting database, as seen in Figure 3-8.
14%
Flag icon
When I make an in-process call, the underlying compiler and runtime can carry out a whole host of optimizations to reduce the impact of the call, including inlining the invocation so it’s as though there was never a call in the first place.
14%
Flag icon
A developer needs to be aware if they are doing something that will result in a network call;
14%
Flag icon
With communication between microservices, however, the microservice exposing an interface and the consuming microservices using that interface are separately deployable microservices.
« Prev 1 3 4