Building Microservices: Designing Fine-Grained Systems
Rate it:
Read between April 25 - November 21, 2021
3%
Flag icon
microservice as something that could be rewritten in two weeks, a rule of thumb that makes sense for his particular context.
3%
Flag icon
All communication between the services themselves are via network calls, to enforce separation between the services and avoid the perils of tight coupling.
3%
Flag icon
The golden rule: can you make a change to a service and deploy it by itself without changing anything else?
3%
Flag icon
With a system composed of multiple, collaborating services, we can decide to use different technologies inside each one. This allows us to pick the right tool for each job, rather than having to select a more standardized, one-size-fits-all approach that often ends up being the lowest common denominator.
4%
Flag icon
By splitting out core parts of its system, Gilt was better able to deal with its traffic spikes, and today has over 450 microservices, each one running on multiple separate machines.
4%
Flag icon
Unfortunately, this means that our changes build up and build up between releases, until the new version of our application hitting production has masses of changes.
4%
Flag icon
smaller teams working on smaller codebases tend to be more productive.
5%
Flag icon
Teams using microservice approaches are comfortable with completely rewriting services when required, and just killing a service when it is no longer needed. When a codebase is just a few hundred lines long, it is difficult for people to become emotionally attached to it, and the cost of replacing it is pretty small.
6%
Flag icon
Technically, it should be possible to create well-factored, independent modules within a single monolithic process. And yet we rarely see this happen. The modules themselves soon become tightly coupled with the rest of the code, surrendering one of their key benefits.
7%
Flag icon
Our software isn’t constrained by the same physical rules that real architects or engineers have to deal with, and what we create is designed to flex and adapt and evolve with user requirements.
7%
Flag icon
In our industry, this view of the architect leads to some terrible practices. Diagram after diagram, page after page of documentation, created with a view to inform the construction of the perfect system, without taking into account the fundamentally unknowable future.
7%
Flag icon
Thus, our architects need to shift their thinking away from creating the perfect end product, and instead focus on helping create a framework in which the right systems can emerge, and continue to grow as we learn more.
7%
Flag icon
Erik Doernenburg first shared with me the idea that we should think of our role more as town planners than architects for the built environment.
7%
Flag icon
architects have a duty to ensure that the system is habitable for developers
8%
Flag icon
Rules are for the obedience of fools and the guidance of wise men.
8%
Flag icon
Principles are rules you have made in order to align what you are doing to some larger goal, and will sometimes change. For example, if one of your strategic goals as an organization is to decrease the time to market for new features, you may define a principle that says that delivery teams have full control over the lifecycle of their software to ship whenever they are ready, independently of any other team.
9%
Flag icon
Written documentation is good, and useful. I clearly see the value; after all, I’ve written this book. But developers also like code, and code they can run and explore. If you have a set of standards or best practices you would like to encourage, then having exemplars that you can point people to is useful. The idea is that people can’t go far wrong just by imitating some of the better parts of your system.
10%
Flag icon
In our desire to create reusable code, we can introduce sources of coupling between services.
10%
Flag icon
Other teams I have spoken to have simply treated the service template as a shared binary dependency, although they have to be very diligent in not letting the tendency for DRY (don’t repeat yourself) result in an overly coupled system!
10%
Flag icon
Sometimes technical debt isn’t just something we cause by taking shortcuts. What happens if our vision for the system changes, but not all of our system matches? In this situation, too, we have created new sources of technical debt.
11%
Flag icon
If one of the architect’s jobs is ensuring there is a technical vision, then governance is about ensuring what we are building matches this vision, and evolving the vision if needed.
11%
Flag icon
A model I greatly favor is having the architect chair the group, but having the bulk of the group drawn from the technologists of each delivery team — the leads of each team at a minimum. The architect is responsible for making sure the group works, but the group as a whole is responsible for governance.
11%
Flag icon
Think about teaching children to ride a bike. You can’t ride it for them. You watch them wobble, but if you stepped in every time it looked like they might fall off, then they’d never learn, and in any case they fall off far less than you think they will! But if you see them about to veer into traffic, or into a nearby duck pond, then you have to step in. Likewise, as an architect, you need to have a firm grasp of when, figuratively, your team is steering into a duck pond. You also need to be aware that even if you know you are right and overrule the team, this can undermine your position and ...more
11%
Flag icon
To summarize this chapter, here are what I see as the core responsibilities of the evolutionary architect: Vision Ensure there is a clearly communicated technical vision for the system that will help your system meet the requirements of your customers and organization Empathy Understand the impact of your decisions on your customers and colleagues Collaboration Engage with as many of your peers and colleagues as possible to help define, refine, and execute the vision Adaptability Make sure that the technical vision changes as your customers or organization requires it Autonomy Find the right ...more
12%
Flag icon
loose coupling and high cohesion.
12%
Flag icon
When services are loosely coupled, a change to one service should not require a change to another.
12%
Flag icon
We want related behavior to sit together, and unrelated behavior to sit elsewhere.
12%
Flag icon
we want to find boundaries within our problem domain that help ensure that related behavior is in one place, and that communicate with other boundaries as loosely as possible.
12%
Flag icon
Domain-Driven Design
12%
Flag icon
Each bounded context has an explicit interface, where it decides what models to share with other contexts.
13%
Flag icon
we have the option of using modules within a process boundary to keep related code together and attempt to reduce the coupling to other modules in the system. When you’re starting out on a new codebase, this is probably a good place to begin. So once you have found your bounded contexts in your domain, make sure they are modeled within your codebase as modules, with shared and hidden models.
13%
Flag icon
When starting out, however, keep a new system on the more monolithic side; getting service boundaries wrong can be costly, so waiting for things to stabilize as you get to grips with a new domain is sensible.
13%
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.
13%
Flag icon
When you start to think about the bounded contexts that exist in your organization, you should be thinking not in terms of data that is shared, but about the capabilities those contexts provide the rest of the domain.
13%
Flag icon
I have seen too often that thinking about data leads to anemic, CRUD-based (create, read, update, delete) services. So ask first “What does this context do?”, and then “So what data does it need to do that?”
14%
Flag icon
onion architecture, as it had lots of layers and made me cry when we had to cut through it.
14%
Flag icon
Implementing Domain-Driven Design
15%
Flag icon
The DB is effectively a very large, shared API that is also quite brittle.
16%
Flag icon
Database integration makes it easy for services to share data, but does nothing about sharing behavior.
16%
Flag icon
These two different modes of communication can enable two different idiomatic styles of collaboration: request/response or event-based.
16%
Flag icon
With orchestration, we rely on a central brain to guide and drive the process, much like the conductor in an orchestra. With choreography, we inform each part of the system of its job, and let it work out the details, like dancers all finding their way and reacting to others around them in a ballet.
16%
Flag icon
The downside to this orchestration approach is that the customer service can become too much of a central governing authority. It can become the hub in the middle of a web, and a central point where logic starts to live.
17%
Flag icon
In general, I have found that systems that tend more toward the choreographed approach are more loosely coupled, and are more flexible and amenable to change. You do need to do extra work to monitor and track the processes across system boundaries, however. I have found most heavily orchestrated implementations to be extremely brittle, with a higher cost of change. With that in mind, I strongly prefer aiming for a choreographed system, where each service is smart enough to understand its role in the whole dance.
17%
Flag icon
Synchronous calls are simpler, and we get to know if things worked straightaway. If we like the semantics of request/response but are dealing with longer-lived processes, we could just initiate asynchronous requests and wait for callbacks.
17%
Flag icon
You need to think about the network itself. Famously, the first of the fallacies of distributed computing is “The network is reliable”
20%
Flag icon
we have a large amount of help out of the box by using HTTP,
20%
Flag icon
HTTP, while it can be suited well to large volumes of traffic, isn’t great for low-latency communications when compared to alternative protocols that are built on top of Transmission Control Protocol (TCP) or other networking technology.
21%
Flag icon
Consumption of the payloads themselves requires more work than is provided by some RPC implementations that support advanced serialization and deserialization mechanisms. These can become a coupling point in their own right between client and server, as implementing tolerant readers is a nontrivial activity (we’ll discuss this shortly), but from the point of view of getting up and running, they can be very attractive.
21%
Flag icon
Do be wary, though, about the world of middleware, of which the message broker is just a small part.
21%
Flag icon
keep your middleware dumb, and keep the smarts in the endpoints.
« Prev 1 3 6