Scaling Your Org with Microservices [slides]
bridgetkromhout.com
bridgetkromhout.com
Before this comment pool spirals into that, I'll just leave this: It all depends on your project.
Did you have a bad time with microservices? Maybe the implementation was wrong. Maybe the project doesn't fit the model. Heck, maybe the project would STILL be screwed under a monolithic approach. There are so many variables to what classifies a success/failure in the microservice world (like most other things in software development, actually).
What's important is to not have a polarising opinion: "microservices suck", "microservices should be used for everything". Analyse your requirements. Imagine your professional project a few years down the line. Educate yourself on the subject (there are books on the subject!). Make. Sure. It. Fits.
I've personally had successes and losses with microservices, just like I had successes and losses with other architectural styles.
Of course if I go to an interview I'll say I built microservices because it's a buzzword/checkbox.
I think "microservices" is a sane architectural pattern for some applications. The problem is that people polarize into one extreme or the other, and many attempts at a microservice implementation that I see would more rightly be classified "nanonservices"; things are broken up, almost at random, into tiny, disjunct, co-dependent pieces. This is a total nightmare scenario, and a monolith would undoubtedly be better.
I developed a dozen microservices to mimic aspects of their existing applications and used Kafka as a message bus. The services rarely spoke directly to each other, but instead listened to events fired into the message bus and updated accordingly.
My biggest takeaway - the client should not use microservices, but could learn some other lessons from the prototype. Microservices make many things harder and the only benefit to them, in my opinion, is they can scale well. But if you're not working at Netflix scale, they're more trouble than they're worth.
What I did recommend: - Build new applications API-first. By that, I mean your front end UI (assuming you have one) communicates to your backend via an API that can be exposed to the world. And assume it WILL be exposed to the world.
- Avoid bloat in your applications. Stop adding every possible feature to your existing app, and pay attention to when it's getting too big. This is mostly a gut/intuition feel, but you can tell it's a problem when your developers start to look like a deer in headlights when you discuss a new feature.
- (optional) Do create an enterprise message bus, and each application can fire events into the bus. This will help future-proof your organization, as new applications can be built to listen for events without having to understand the other systems.
Everything seems so hard. To follow and debug requests for example. How do you do that in a good way? Running a local microservice application is another.
Maybe microservices is good for very large corporations, but even then I am not really convinced since it seems easier just to learn one bigger codebase that is structured well rather than digging in to many different ones that may be writter in different languages etc.
The hype is so big and the benefits are very unclear. At least to me it seems like there are only negative aspects of doing microservices.
You should not be doing microservices unless you need that scalability. If you don't, regular SOA or even modular monoliths work fine. Microservices live in the place where those break down in scaling. That's a very extreme place, and so microservices are an extreme response.
As an example, let's take scaling services over a hybrid cloud. You have your own metal for the baseline request volume, with the capability to provision more capacity from a public cloud. A modular monolith is obviously out of the picture at this point. You would have two separate monolith instances, and would have to consider how and when to pass work between them... Possible, but at that point you're basically inventing a service architecture within a monolith, so why not just move to SOA? If you already have a SOA system, you still have work: Which services to deploy to the cloud, when to deploy them, how to recover and load balance to them, etc. Specific answers to these decisions are what led to what we consider modern microservices: What to deploy is the smallest unit possible, so that you can keep scaling as fine-grained as possible. Every request is routed through a discovery and load-balancer to any and all available instances.
Designing good API's is important for all software, but is critical to making microservices work well; and it is not always obvious how to do this well. I can understand why so many people say you should start with a monolith and then break it up into microservices: With the monolith you have already accumulated a ton of domain knowledge so you can break apart the service-boundaries much easier. However, it can still be tricky to do this because not ever module in your monolith should be a service, infact it is likely that most will not. Microservices are a different level of encapsulation than a module. Sometimes microservices should done one thing well and with authority, sometimes they should do many things within the same domain/context, sometimes they should do an entire class of things to their data source, etc. Designing good API's forces you to understand how execution and data will flow through your system and how you can effectively and cleanly delineate between them.
IMO, the most important thing for a microservice, regardless of its size, complexity or role within your system, is it's API. When you have a well defined API you can encapsulate and abstract that entire service from the rest of your system, which is a wonderful thing. This microservice can now be deployed, updated, scaled, refactored or even rewritten entirely without any of the other services in the system even noticing. It brings a tremendous amount of freedom to managing your software platform. You no longer need to worry about things that don't concern your service, just fulfill your APIs and life is good!
[1] https://stackoverflow.com/questions/25501098/difference-betw...
* Single business function. Microservices don't have to be small, but all their calls should facilitate s single business function.
* Automated deployment. Services are deployed and undeployed live based on load.
* Unknown targets. Services are allocated and deployed to machines at runtime. The machine itself may even be allocated on demand. So service discovery is absolutely required.
* Stateless. Services instances can be spun down at any moment, so they can't be holding transaction state.
So many names for the same thing (that hardly anyone can agree on what exactly it is).
No wonder the doctors and lawyers and accountants take all the money.
I stopped working there (partly because they wouldn't hire anyone to work on the monolith) and afaik the monolith is still in production (or at least the majority of it) since the microservices took so long time to develop I guess someone pulled funding.
I have to say my experience with microservices is a bit limited, but every time I have seen someone do it I just think it is too complicated for very little gain. It takes massive resources to develop it and I am not convinced it's the design that makes it scale better.
If your cluster of 7 database servers is still too slow when you increase it to 9, you probably need to take a look into database optimization, not microservices. If any of those numbers look laughable to you, you should laugh about microservices too.
If you look at something like Spring Boot, you will find that an individual service instance is a stand-alone application server. That is what is duplicated when a new service instance is created.
Performance is highly application specific. It may be any combination of [throughput, latency, responsivity] x [maximum, minimum, average, some cut over a distribution, instantly measure on some important time]. And there are probably more possibilities, those are just the usual ones.
Microservices can make any one of them better, very likely at the cost of making other ones worse.
Docker compose running some integration tests with the builds helps some of the integration burden.
I think there are two groups or organizations that benefit from microservices:
- actual scaling is required
- "we are too stupid or politically entrenched to maintain a modular code base without them, so we try (and most likely fail) to enforce modularity with microservices"
Of course, group 2 will only further entrench themselves.
Same for Hadoop over SQL or node over Java.
Your comment reflects that perfectly.
You (and others) have cleanly expressed the downsides, so here's my version of why microservices are valuable:
- Code is forced to have well defined APIs; you can't reach into a library's internals and rip out what you need when that library is implemented as a separate process.
- You can scale only the parts that need to be scaled, when they need to be scaled.
- You aren't tied to any single language for your application.
- Horizontal scaling is easier than vertical scaling, beyond a certain point.
- You gain a lot of extra fault tolerance.
Of course, all of these benefits only come when the microservices are implemented well; however when they are done well, scaling and reliability are easy. Since both scaling and reliability directly impact the end user experience, they will be given more weight than the microservice tech debt.
That is incorrect. Microservices do not force you to write good code. I have seen microservices done poorly where each microservice duplicates code from the others, and APIs are not well defined. For example project A has folders "api" "api2", project B has folder called "api", there's another project just called "api" which also has logic mixed in unrelated to APIs. Files named "server" that actually implement a client, etc.
It doesn't matter if your API is an http endpoint or a local function call, if you suck at naming things, your API will suck.
> You gain a lot of extra fault tolerance.
Also not true as a "fact of matter". You have to account for API requests between your own infrastructure failing. Adding more system boundaries reduces fault tolerance.
> Since both scaling and reliability directly impact the end user experience, they will be given more weight than the microservice tech debt.
But your competitor's monolith might run on one server. They might implement reliability with a passive failover server, and they might forgo the tech debt & focus on adding new features, which also directly impact the end user experience. Those features will be harder to shoe-horn into your micro-services if you get the boundaries wrong. All of the sudden you have a scalable "reliable" system no one uses, because your competitor has more features.
> all of these benefits only come when the microservices are implemented well
All of those benefits apply to writing good code in general (microservices or not). The only valid benefit you listed specific to microservices is scaling is easier. But you can still scale a monolith. Just deploy all code to all servers, but only run certain things on each tier of services. So again, you don't really need microservices to do that.
In the AWS case microservices are combined with other paradigms like Serverless and event driven computing. I would judge all these together and consider the overall benefits you gain from fully managed services, built-in autoscaling, independent parallel development and deployment of microservices, etc. Personally I would not go back to the old ways.
I'm assuming you mean "requests that involve multiple microservices"? And the answer there is simple for following - the first one involved tags the request and passes that tag on to all the subrequests. Easy to correlate across your logs. Debugging can be done in a similar way with a header saying "dump debug for this request" that's passed between services.
But you would have to create a development environment running the complete micro-services environment on a single machine. Or setup distributed/cloud logging & debug against production. Which is generally easier to do if you use a monolith. Admittedly tools like docker compose and vagrant can help with this.
One word: CORBA
Those who forget history are doomed to repeat it
It's more a problem that developers that try to scale orders of magnitude too early normally not knowing what they are doing; and developers that do not know what they are doing normally do not design clean interfaces.
At work we have a huge monolith and several smaller services. Working on the former it's never nice and my productivity is a fraction of what I can do when working on the smaller and saner projects.
I wouldn't always use a microseconds architecture. I think the best approach is to start with a modular monolith till it reaches a critical size.
Is there a way to organize a large program (let's say in Java) that allows one to easily extract specific components and move them to their own service as needed? I'm thinking along the lines of local message passing between Java "components" (not packages). With a message system in place, you could easily move a service wherever so long as it's able to communicate.
Such a great quote. The longer I only do management-only work, the more anxiety creeps in silently about not being able to do these things on my own, not being competent enough, being a fake etc. The moment I decide to solve some problem for myself all is cool again - and I'm more trustworthy for the team as well. The problem is that such an approach tends to create conflict of interest - as a manager you shouldn't interfere too much and allow the team to solve the problems. Maybe the notion of manager is a problem in itself. It's a tempting perspective, but as far as I remember Google thought so as well and at some point they had to step back and reintroduce classic managers again ( https://hbr.org/2013/12/how-google-sold-its-engineers-on-man... ).
"Hard things are HARD", etc. plus a bunch of memes and my little pony pictures.
Monolithics are good because you get a "stack trace" of an error! That stack trace is so much better than all that Ziplin stuff that barely work and takes so much longer to just see what caused the error!
I guess I would take the recent honeycomb outage as an example since charity majors in on the slides. When reading through the post mortem (which I liked a lot) the one question I never had answered was what are they doing to make sure 1 customer can't take down the entirety of their service? Assuming that failure is going to happen (via code bugs or bad actor customers)how do we better isolate individual customers from one another while still enjoying the benefits of mulitenancy? As we as an industry become more comfortable with microservices we must also learn how to better serve customers and mitigate failures by isolating and limiting blast radius, as well as deploying software in safer and saner ways.