microservices

Pros

Pro and con:

talk-what-i-wish-i-had-known-before-scaling-uber#stability-of-service-leave-alone

At 5:38 A surprising benefit of microservices is that you never touch them. You can leave many of them alone after deploying them. That sounds good, but the flip side, which he talks about at 39:30, is that when someone needs to make a cross-cutting change, they might be forced to update six month old code on a service that hasn't changed to keep up with the rest of the services (since it was working fine)

 
blog-post-why-microservices-work-for-us#visibility

But a major benefit of running microservices is largely absent from today's discussions: visibility.

When we're getting paged at 3am on a Tuesday, it's a million times easier to see that a given worker is backing up compared to adding tracing through every single function call of a monolithic app.

 

can ease upgrades (like from Rails 3 to Rails 4) because of the size of each application is smaller blog-post-microservices-at-karma

can leave older APIs running for a long time, and upgrade them when we have meaningful changes to make blog-post-microservices-at-karma

Allows developers to use multiple languages and frameworks (right tool for the right job)

don't have to keep a bigger problem in our heads... can only think about what the service provides.

thanks to queues, a broken service can pick up where it left off once it's back online blog-post-microservices-at-karma (aren't there problems with that?)

change cycles are not tied together as they would be in a monolith

can scale just the parts of the application that require greater resources

each service provides a firm module boundary

codifies an explicit Published Interface - from blog-post-martin-fowler-on-microservices

smaller granularity of services can make it easier to create the personal relationships between service developers and their users - from blog-post-martin-fowler-on-microservices

We have seen projects where a good team, with a strong desire for modularity, has built a monolithic architecture that has decayed over the years. Many people believe that such decay is less likely with microservices, since the service boundaries are explicit and hard to patch around (but they are waiting for the data to come in). - from blog-post-martin-fowler-on-microservices

Another key advantage of the microservices architecture is that a service can be individually scaled based on its resource requirements. Rather than having to run large servers with lots of CPU and RAM, microservices can be deployed on smaller hosts containing only those resources required by that service. blog-post-aws-using-containers-to-build-a-microservices

"you can make damn sure that you're never passing mutable data across module boundaries, things like that." - Martin Fowler in blog-post-avdi-on-microservices

Application segmentation makes it so you can have certain things remain unchanged for a while (an OK place to have technical debt) blog-post-you-are-thinking-about-tech-debt-wrong

talk-kill-microservices-before-it-is-too-late#throw-away

At 14:40 - because it's small enough you can just throw it away and restart if you have to

 
talk-technical-overview-of-kubernetes#microservices-and-team-growth

At 21:30 - Microservices facilitate team growth. By standing up an interface, then you can have a team (even a remote one) work on the problem.

 
book-designing-data-intensive-applications#different-teams-work-on-different-things

Location: 13,572 The advantage of such a service-oriented architecture over a single monolithic application is primarily organizational scalability through loose coupling: different teams can work on different services, which reduces coordination effort between teams (as long as the services can be deployed and updated independently).

 

Cons

talk-what-i-wish-i-had-known-before-scaling-uber#fragment-culture

Having microservices with multiple languages fragments the culture. People say "oh I am a go programmer, oh I'm a java a programmer."

 
talk-what-i-wish-i-had-known-before-scaling-uber#trade-complexity-for-politics

At 9:01, you might trade complexity for politics. Basically, you build a new service because you don't want to deal with talking to other people about how bad the old code is.

 

Pro and con:

talk-what-i-wish-i-had-known-before-scaling-uber#stability-of-service-leave-alone

At 5:38 A surprising benefit of microservices is that you never touch them. You can leave many of them alone after deploying them. That sounds good, but the flip side, which he talks about at 39:30, is that when someone needs to make a cross-cutting change, they might be forced to update six month old code on a service that hasn't changed to keep up with the rest of the services (since it was working fine)

 
podcast-bikeshed-39-ok-with-instability#microservice-errors

At 39 - with microservices you have to monitor more error conditions (like HTTP error conditions)

 
talk-what-i-wish-i-had-known-before-scaling-uber#keep-your-biases

At 9:30 with multi-language microservices you get to keep your biases. If you like a specific language, you can use it, and interface with other people using other languages.

 

"We are concerned that some teams are rushing in to adopting microservices without understanding the changes to development, test, and operations that are required to do them well." blog-post-microservice-envy

"When you use microservices you have to work on automated deployment, monitoring, dealing with failure, eventual consistency, and other factors that a distributed system introduces." blog-post-microservice-premium

Because microservices are often deployed across multiple hosts, and often scale up and down based on load, service discovery is needed in order for one service to know how to locate other services. blog-post-aws-using-containers-to-build-a-microservices

Because services will be spread across multiple hosts, it can be difficult to keep track of which hosts are running certain services. blog-post-aws-using-containers-to-build-a-microservices (Linux containers can help mitigate this challenge)

Also, even though each host may not be as powerful as the host running the monolithic application, as the microservices architecture scales out, the number of hosts will grow faster than it will with a monolithic architecture. blog-post-aws-using-containers-to-build-a-microservices (Linux containers can help mitigate this challenge)

If services are implemented in different programming languages, this means the deployment of each service will require a completely different set of libraries and frameworks, making deployment to a server complex. blog-post-aws-using-containers-to-build-a-microservices (Linux containers can help mitigate this challenge)

If the components do not compose cleanly, then all you are doing is shifting complexity from inside a component to the connections between components. Not just does this just move complexity around, it moves it to a place that's less explicit and harder to control. - from blog-post-martin-fowler-on-microservices

when your components are services with remote communications, then refactoring is much harder than with in-process libraries - from blog-post-martin-fowler-on-microservices

applications need to be designed so that they can tolerate the failure of services (additional complexity in the design) - from blog-post-martin-fowler-on-microservices

each microservice will eventually naturally align with a team, for better or for worse (see Conway's Law)

"creating and maintaining the documentation required to fully describe the request-response formats of each component can be a heavy burden to bear." - blog-post-incremental-migration-to-microservices

testing can be difficult. "Instead, we focus on making each component as good as possible, and see what happens when we put them together." (also monitoring machines and business becomes key) blog-post-microservices-at-karma

have to build the entire app with the assumption that everything will fail at some point blog-post-microservices-at-karma

"The developers on these projects understood the importance of testing, but were unable to effectively utilize existing tooling to do the job." blog-post-testing-rails-service-oriented-architecture

Possibly latency between the services (though somewhat mitigated in something like a VPC)

Remote calls are more expensive than in-process calls, and thus remote APIs need to be coarser-grained, which is often more awkward to use. from blog-post-martin-fowler-on-microservices

requires evolution mechanisms in the service contracts (API versioning?) (which can involve some coordination) see blog-post-consumer-driven-contracts

If you need to change the allocation of responsibilities between components, such movements of behavior are harder to do when you're crossing process boundaries. from blog-post-martin-fowler-on-microservices (sounds like it would affect emergent design)

In the case of collaborating services, one of the stickiest points is evolution. - from blog-post-tolerant-reader

harder to do transactions - consistency may only be eventual consistency and problems are dealt with by compensating operations (what are those compensating operations?) - from blog-post-martin-fowler-on-microservices

choreography and event collaboration leads to emergent behavior (which can sometimes be bad emergent behaviour) - from blog-post-martin-fowler-on-microservices

requires very sophisticated monitoring and logging setups for each individual service such as dashboards showing up/down status and a variety of operational and business relevant metrics. Details on circuit breaker status, current throughput and latency are other examples we often encounter in the wild. - from blog-post-martin-fowler-on-microservices

"And we've pushed their interconnections and dependencies out from a realm where our tools could visualize them as tangled webs, into a realm where our tools can give us no insight whatsoever. We've moved our diagnostics from tests into distributed log files. And we've almost certainly introduced new implied temporal dependencies that didn't exist before." blog-post-avdi-on-microservices

Have to give failure scenarios in the services a lot of thought. What do you do while one of the services you rely on is down? How many retries do you do? How do you catch up? podcast-bike-shed-episode-14-dhh

Thoughts

"The fact that modern orchestration and tooling makes it easier to have more granular services changes the equation for how you factor the services, to be sure, but it's an evolution not a revolution." (#)

blog-post-real-world-microservices#tough-to-stage-and-canary-deep-services

I'll show you how some of the hardest operational problems in microservices—staging and canarying of deep services—can be solved by introducing the notion of routing to the RPC layer.

 

A use case they called for was this: they wanted to parse git diffs, but the existing Ruby library wasn't very good and there was a great Haskell one, so they put an HTTP wrapper around the Haskell one and then just used it from their Ruby codebase podcast-bike-shed-episode-9-monorails

A microservice is easily defined as a task and might consist of two containers — one running the service endpoint code, and another a database. blog-post-aws-using-containers-to-build-a-microservices

It is this isolation between containers running on the same host that makes deploying microservice code developed using different languages and frameworks very easy. blog-post-aws-using-containers-to-build-a-microservices

(in contrast to SOA) Microservices architecture may often make use of a message bus, but there is no logic in the messaging layer whatsoever—it is purely used as a transport for messages from one service to another blog-post-aws-using-containers-to-build-a-microservices

"The traditional integration approach is to try to deal with this problem using versioning, but the preference in the microservice world is to only use versioning as a last resort. We can avoid a lot of versioning by designing services to be as tolerant as possible to changes in their suppliers." - from blog-post-martin-fowler-on-microservices

"but they (the Guardian) prefer to add new features by building microservices that use the monolith's API" - from blog-post-martin-fowler-on-microservices

The key property of a component is the notion of independent replacement and upgradeability - which implies we look for points where we can imagine rewriting a component without affecting its collaborators - from blog-post-martin-fowler-on-microservices

Microservice applications put a lot of emphasis on real-time monitoring of the application, checking both architectural elements (how many requests per second is the database getting) and business relevant metrics (such as how many orders per minute are received) - from blog-post-martin-fowler-on-microservices (sounds a bit like what Fred George was talking about talk-micro-service-architecture-fred-george )

How do you aid service contracts in evolving independently?

"The biggest issue in changing a monolith into microservices lies in changing the communication pattern. A naive conversion from in-memory method calls to RPC leads to chatty communications which don't perform well. Instead you need to replace the fine-grained communication with a coarser-grained approach." from blog-post-martin-fowler-on-microservices

Service boundaries reinforced by team boundaries from blog-post-martin-fowler-on-microservices

Should try to have highly cohesive service boundaries

must be independently deployable by fully automated deployment machinery

built once, well tested at the public API (integration) level (from a comment on blog-post-organizing-microservices-in-single-git-repo)

To actually route to the client-facing microservices (from blog-post-microservices-at-karma) "Every microservice has its own URL. In your example, we would have a users.mysite.com/users/1 and an orders.mysite.com/orders/1 or something."

a microservice works best when it has one, and only one, responsibility

Two ways to communicate: HTTP requests, and a message queue.

Have to handle service to service authentication and authorization when backend services need to talk to each other. Either have app-specific API tokens for each backend service or have a trusted set of internal IP addresses (the Karma guys say "Everything is inside VPC anyway")

Karma guys use the gem Faraday to connect to other microservices

There is a difference between services that are primarily HTTP-oriented (since they require immediate action) and queue-oriented (because they can work asynchronously)

From a comment on blog-post-microservices-at-karma: "tag every initiating request with a unique ID Clients create their own and the first part of the backend adds to it to make it unique across the system. That idea accompanies every part of fulfilling the request so that all logging for a specific request can be gathered and analyzed for performance and resolving issues. Additionally it provides a portable mechanism to track task completion and do realtime reporting." - the karma guys say they added an extension to the Faraday gem with "request tagging".

From a comment on blog-post-microservices-at-karma: Aside from having request tagging, each service should have exceptionally good state information which you can dig into after-the-fact to see what went wrong. For example, they say that a service should mark what request it got and when, "Then it processes it and stores the result (succeeded or failed)."

From a comment on blog-post-microservices-at-karma: If there is some data that is needed in more than 1 service, there will be one service that is the owner of the data and exposes it over an API.

More of a way of thinking about splitting up work for different teams to be able to work on stuff than for good software podcast-bike-shed-episode-14-dhh

Helps to have a correlation-id (TODO find other references to this concept and centralize)

Other reading

blog-post-breaking-apart-a-monolith

blog-post-service-disoriented-architecture