5 ms·
Microservices shift complexity from code to operations - microservices don't remove complexity - they spread it wider, making the whole more complex.
by andrewstuart 5y ago
Microservices shift complexity from code to operations - microservices don't remove complexity - they spread it wider, making the whole more complex.
- deleted 5y ago[deleted]
- FridgeSeal 5y agoIt’s about trade offs I think. Monolith can Microservices are so often presented as “x is better than y”, but it should be “which is more applicable for the team size, product and operational concerns”. Monoliths are a great choice for certain team sizes and applications, want stricter isolation and blast-radius between different teams and products and need to scale different things differently? Micro services are probably a better choice.
- ironmagma 5y agoExamining behavior in the limit (a la physics) is interesting. Imagine a system where every function call goes out to a separate process. Suddenly you have a lot of processes waiting around to be called. Debugging requires special tools. Profiling becomes a nightmare. Even determining if the system is fully running becomes difficult. What have you gained?
- whimsicalism 5y ago> What have you gained? Separation of responsibilities? Easier to analyze because you only have so many inputs and outputs to a simpler system? Debugging something that touches a lot of paths in a monolith can be quite nightmarish as well.
- bcrosby95 5y agoMost comments about this assumes a poorly designed monolith and a well designed set of microservices. A microservices architecture can be a rats nest too. I guess what it means is that even if you can build a well modularized system, it will only stay well modularized if you use a network call to enforce it. Well, at least for most companies. Conceptually, there's nothing keeping you from designing your codebase to work as both microservices or direct calls. I've certainly done it before - each service defined a Java interface, and codegen could hook that up as either a direct call or to route over some kind of layer.
- whimsicalism 5y agoOr something that can be spun up as a service or imported as a library
- ironmagma 5y ago> you only have so many inputs and outputs to a simpler system? Doesn't a function only have so many inputs and outputs too? Scope capturing/global variables aside.
- whimsicalism 5y ago> Doesn't a function only have so many inputs and outputs too? Scope capturing/global variables aside. Sure, and a microservices architecture to me implies a larger movement towards function-esque, idemopotency, analyzability and away from global state. To me, monolithic architecture implies global shared state that is difficult to reason about.
- ironmagma 5y agoIt’s been mentioned elsewhere in this thread, but the lack of microservices doesn’t imply a global shared state. There’s a big difference between a large service that has well isolated modules, and a large service where all the state is contained in one struct, for example. I feel this issue is pitched as a false dichotomy.
- throwaway894345 5y agoAlso, security. Each component has an identity and it’s own set of permissions so the custom emoji widget doesn’t have access to the payments system or the health data.
- ironmagma 5y agoThis would be true in a monolith as well unless configured otherwise. Functions don’t just start talking to each other; you have to explicitly connect them via a function invocation. I’m not sure how an architecture would change that.
- throwaway894345 5y agoIt’s pretty straightforward. In a monolith everything is in the same memory space, so the payment system credentials and routines are available to the whole monolith. In a microservice architecture, one service can’t access the memory or routines of other services.
- ironmagma 5y agoOne function cannot access the memory space of another function any less explicitly than one process can access the memory of another process. Either way, you are just picking different contract enforcement mechanisms. The only way this would be helpful is if your whole goal is to make something (breaking the contract) as hard to do as possible. And in that case, I really have to ask, who are your teammates that you trust them so little as to literally enforce separation this way? No healthy organization should have to resort to this kind of civil war.
- throwaway894345 5y ago> One function cannot access the memory space of another function any less explicitly than one process can access the memory of another process. You're mistaken. The operating system largely prevents cross-process memory access. Of course, CPU vulnerabilities can circumvent these protections, but even then your micro services can run on distinct machines while monoliths can't. > The only way this would be helpful is if your whole goal is to make something (breaking the contract) as hard to do as possible Yeah, that's the idea. "defense in depth". > And in that case, I really have to ask, who are your teammates that you trust them so little as to literally enforce separation this way? No healthy organization should have to resort to this kind of civil war. (1) not all attackers are internal (2) some attackers are internal and many very profitable organizations do restrict employee access to secrets (and in many cases this is required by compliance).
- BackBlast 5y agoIf I'm in Java, JavaScript, or Python and there is a code fault, the system provides me a stack trace of the call structure that lead to the error. If I catch the error I can output more related data as I deem necessary. This comes effectively, out of the box. How do I do a similar stack trace in microservices to understand the path that led to this state? I've used microservices at a couple of companies and their methods were effectively, look at the request id and trace it through this mass of log files for each microservice we are running. It was terrible and could take hours to compile the same information. What tooling exists to solve this problem with microservices? Genuinely want to know.
- whimsicalism 5y ago> If I'm in Java, JavaScript, or Python and there is a code fault, the system provides me a stack trace of the call structure that lead to the error. If I catch the error I can output more related data as I deem necessary. This comes effectively, out of the box. Sure, if you are not writing a program using event-driven async style. Every monolith I've worked with has been in async style pretty much. With global state in the monolith, this can become quite difficult to reason about. By contrast, with microservices, you can analyze the service as performing a small function with a single input and output without global state dependencies. This can be easier to debug.
- BackBlast 5y agoIt seems to me that you are comparing apples and oranges. If your code has no relevant state or coupling, a pure function. Sure, you can look at it in isolation. You could do the same in a monolith. I've worked on plenty of monoliths with async style code and have found the stack traces to be plenty helpful. It's never been an issue. At least in JavaScript you retain all relevant scoped data and can dump it all if you like. Debugging gets much more interesting when there are no obvious such errors, yet error conditions are present. I'm still not seeing any equivalent microservice tooling.
- edude03 5y agoMinor nit: functions as a service are almost exactly this - and they (from a technical perspective) don’t wait to be called, they pop into existence just in time. Arguably though it’s not special tools is just different tools. You usually can’t run a debugger live in production but with tools like distributed tracing and service meshes you get really close
- Kalium 5y agoI agree that microservices shift complexity, but I'm not sure that this inherently results in an overall increase in complexity. For example, using highly automated ops tools like autoscaling and load balancing can enable smooth handling of problems that can be challenging to handle in code.
- candiddevmike 5y agoInstead of shuffling data between things via shared memory/function args, you're doing it over the network. This will always be more complicated.
- Kalium 5y agoYes, it shifts communication to over the network, but this comes with the benefit of making system boundaries much clearer. It's been my experience that this can allow different parts to evolve separately and make the choices best for their own needs, which can sometimes result in a paradoxical reduction of complexity as one all-in-one system turns into a series of simpler tools. Suddenly the part of the system that does background ETL work and the part of the system that serves up the admin panel can use different tools. I will agree that networks are inherently complicated, but your system or systems probably use networks anyway. Using them internally often forces you to grapple with the complexity you were already facing. Plus, it's been my experience that networks are easier for most to reason about than shared memory and mutexes. Let's not forget providing an easy set of dials to turn to scale a given part of the system. That's a point of complexity, but it can be an immensely useful one. Complexity is not always the enemy - a power drill is more complex than a manual screwdriver and this complexity is pretty useful.
- candiddevmike 5y agoGiven the trade off of synchronous vs asynchronous, I hope most folks try their damnedest to use the former before having to use the latter.
- QuercusMax 5y ago
- throwaway894345 5y agoMicroservices probably do increase the overall amount of complexity in a sense, but the idea is to trade a little bit of complexity in order to decouple teams. i.e., each team can own its service from soup to nuts without having to coordinate with a bunch of other teams. To put it differently, there’s a small increase in technical complexity in exchange for a significant decrease in organizational complexity. That said, if you go out of your way to retain that organizational complexity (e.g., by dividing your services in a way that doesn’t resemble your org chart) then you’re going to have a bad time with microservices. Similarly, if you don’t have organizational complexity (e.g., you only have one or two teams) then microservices are probably the wrong way to go.
- twblalock 5y agoThe operations needed to keep a large monolith buildable when a lot of different teams work on it are also highly complex, and increase in complexity relative to the number of contributors to the codebase. It becomes a massive coordination problem at scale. Microservices decouple teams, so they can get their work done without stepping on each other's toes.
- christophilus 5y agoEh. Properly segmented monoliths are just fine. And are probably much simpler to deploy.
- hw 5y agoUntil there needs to be a change in the interface. Now you have N other services to deploy to and coordinate
- TameAntelope 5y agoMore people can do operations, and more operations work is parallelizable, so yeah it's a tradeoff but there is upside to that tradeoff.
- mrbungie 5y agoWe're going to need some evidence or at least more development on these ideas.
- TameAntelope 5y agoWe? I'm sorry I don't understand.