microservices

Pros

Pro and con: link not tracked

link not tracked

can ease upgrades (like from Rails 3 to Rails 4) because of the size of each application is smaller link not tracked

can leave older APIs running for a long time, and upgrade them when we have meaningful changes to make link not tracked

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 link not tracked (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 link not tracked

smaller granularity of services can make it easier to create the personal relationships between service developers and their users - from link not tracked

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 link not tracked

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. link not tracked

"you can make damn sure that you're never passing mutable data across module boundaries, things like that." - Martin Fowler in link not tracked

Application segmentation makes it so you can have certain things remain unchanged for a while (an OK place to have technical debt) link not tracked

link not tracked

link not tracked

link not tracked

Cons

link not tracked

link not tracked

link not tracked

link not tracked

Pro and con: link not tracked

link not tracked

link not tracked

"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." link not tracked

"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." link not tracked

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. link not tracked

Because services will be spread across multiple hosts, it can be difficult to keep track of which hosts are running certain services. link not tracked (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. link not tracked (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. link not tracked (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 link not tracked

when your components are services with remote communications, then refactoring is much harder than with in-process libraries - from link not tracked

applications need to be designed so that they can tolerate the failure of services (additional complexity in the design) - from link not tracked

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." - link not tracked

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) link not tracked

have to build the entire app with the assumption that everything will fail at some point link not tracked

"The developers on these projects understood the importance of testing, but were unable to effectively utilize existing tooling to do the job." link not tracked

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 link not tracked

requires evolution mechanisms in the service contracts (API versioning?) (which can involve some coordination) see link not tracked

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 link not tracked (sounds like it would affect emergent design)

In the case of collaborating services, one of the stickiest points is evolution. - from link not tracked

harder to do transactions - consistency may only be eventual consistency and problems are dealt with by compensating operations (what are those compensating operations?) - from link not tracked

choreography and event collaboration leads to emergent behavior (which can sometimes be bad emergent behaviour) - from link not tracked

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 link not tracked

"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." link not tracked

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? link not tracked

Thoughts

link not tracked

link not tracked

link not tracked

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 link not tracked

A microservice is easily defined as a task and might consist of two containers — one running the service endpoint code, and another a database. link not tracked

It is this isolation between containers running on the same host that makes deploying microservice code developed using different languages and frameworks very easy. link not tracked

(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 link not tracked

"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 link not tracked

"but they (the Guardian) prefer to add new features by building microservices that use the monolith's API" - from link not tracked

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 link not tracked

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 link not tracked (sounds a bit like what Fred George was talking about link not tracked )

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 link not tracked

Service boundaries reinforced by team boundaries from link not tracked

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 link not tracked)

To actually route to the client-facing microservices (from link not tracked) "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 link not tracked: "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 link not tracked: 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 link not tracked: 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 link not tracked

Helps to have a link not tracked (TODO find other references to this concept and centralize)

Other reading

link not tracked

link not tracked

link not tracked

Talks

link not tracked


link not tracked

link not tracked

tag--pub-to-codedtested