4 ms·
Network calls are a powerful thing to introduce. It means that you have an impassable boundary, one that is actually physically enforced - your two services hav
by insanitybit 3y ago
Network calls are a powerful thing to introduce. It means that you have an impassable boundary, one that is actually physically enforced - your two services have to treat each other as if they are isolated.
Isolation is not anything to scoff at, it's one of the most powerful features you can encode into your software. Isolation can improve performance, it can create fault boundaries, it can provide security boundaries, etc.
This is the same foundational concept behind the actor model - instead of two components being able to share and mutate one another's memory, you have two isolated systems (actors, microservices) that can only communicate over a defined protocol.
- nicoburns 3y ago> Network calls are a powerful thing to introduce. It means that you have an impassable boundary, one that is actually physically enforced - your two services have to treat each other as if they are isolated. That is not too true at all. I've seen "microservice" setups where one microservice depends on the state within another microservice. And even cases where service A calls into service B which calls back into service A, relying on the state from the initial call being present. Isolation is good, but microservices are neither necessary nor sufficient to enforce it.
- insanitybit 3y agoWell, I'd say you've seen SoA setups that do that, maybe. But those don't sound like microservices :) Perhaps that's not a strong point though. Let me be a bit clearer on my point because I was wrong to say that you have to treat a service as being totally isolated, what I should have said that they are isolated, whether you treat them that way or not. There is a physical boundary between two computers. You can try to ignore that boundary, you can implement distributed transactions, etc, but the boundary is there - if you do the extra work to try to pretend it isn't, that's a lot of extra work to do the wrong thing. Concretely, you can write: rpc_call(&mut my_state) But under the hood what has to happen, physically, is that your state has to be copied to the other service, the service can return a new state (or an update), and the caller can then mutate the state locally. There is no way for you to actually transfer a mutable reference to your own memory to another computer (and a service should be treated as if it may be on another computer, even if it is colocated) without obscene shenanigans. You can try to abstract around that isolation to give the appearance of shared mutable state but it is just an abstraction, it is effectively impossible to implement that directly. But shared mutable state is trivial without the process boundary. It's just... every function call. Any module can take a mutable pointer and modify it. And that's great for lots of things, of course, you give up isolation sometimes when you need to.
- nicoburns 3y agoHmm... I guess I very rarely use shared mutable state in web services anyway. The last job I worked at, all state was either in the database (effectively another service anyway) or stored on the client (e.g. auth tokens). So anything that was mutating a function parameter would already be subject to extra scrutiny during code review (Why is it doing that? What scope / module boundary is the mutation limited to?).
- insanitybit 3y agoShared mutable state also goes beyond a mutable reference. If you call a function and that function throws an exception you are tying the caller/callee's states together. In a SoA the callee machine can literally blow up and your caller state is preserved. If your web service is generally low-state and these problems are manageable for the complexity scale you're solving for, microservices aren't really something to even consider - I mean, you basically have a microservice already, it's solving a single problem within a bounded context, give or take. It's just... one service and one context.
- deleted 3y ago[deleted]
- manicennui 3y agoIt is trivial to tightly couple two services. They don't have to treat each other as isolated at all. The same people who create tightly coupled code within a single service are likely going to create tightly coupled services.
- insanitybit 3y agoI think I've covered this in another comment just below the one you've replied to.
- crabbone 3y agoThe reality of this situation is that the tool everyone is using to build microservices is Kubernetes. It imposes a huge tax on communication between services. So your aspiration as to improving performance fly out of the window. On top of this, you need to consider that most of the software you are going to write will be based on existing components. Many of these have no desire to communicate over network, and your micro- or w/e size services will have to cave in to their demands. Simple example: want to use Docker? -- say hello to UNIX sockets. Other components may require communication through shared memory, filesystem, and so on. Finally, isolation is not a feature of microservices, especially if the emphasis is on micro. You have to be able to control the size and where you want to draw the boundary. If you committed upfront to having your units be as small as possible -- well, you might have function-level isolation, but you won't have class- or module- or program-level isolation, to put it in more understandable terms. This is where your comparison between the actors model and microservices breaks: first doesn't prescribe the size.
- insanitybit 3y agoMicroservices definitely predate k8s, but sure, lots of people use k8s. I don't know what penalty you're referring to. There is a minor impact on network performance for containers measured in microseconds under some configurations. Maybe Kubernetes makes that worse somehow? I think it does some proxying stuff so you probably pay for a local hop to something like Envoy. If Envoy is on your system and you're not double-wrapping your TLS the communication with it should stay entirely in the kernel, afaik. http://domino.research.ibm.com/library/cyberdig.nsf/papers/0929052195DD819C85257D2300681E7B/$File/rc25482.pdf http://domino.research.ibm.com/library/cyberdig.nsf/papers/0... In no way is this throwing out performance. It's sort of like saying that Kafka is in Java so you're throwing away performance when you use it, when there are massive performance benefits if you leverage partition isolation. > Many of these have no desire to communicate over network, and your micro- or w/e size services will have to cave in to their demands. Simple example: want to use Docker? -- say hello to UNIX sockets. Other components may require communication through shared memory, filesystem, and so on. I'm not sure what you're referring to. Why would that matter at all? I mean, ignoring the fact that you can easily talk to Docker over a network. > Finally, isolation is not a feature of microservices, Isolation is a feature of any process based architecture, whether it's SoA, actors, or microservices. > well, you might have function-level isolation, but you won't have class- or module- or program-level isolation, You get isolation at the service layer. I don't see why that would be contentious, it's obvious. If you're saying you want more isolation, ok, you can write your code to do that if you'd like. > first doesn't prescribe the size. Yep, the actor model is very low level. Microservice architecture is far more prescriptive. It's one of the reasons why I think Microservice architecture has been far more successful than actor based systems.
- collyw 3y agoIt's also something else that breaks. A lot more than function calls.
- insanitybit 3y agoSure, but breaking isn't always bad. I realize that sounds a bit crazy, but it's true. a) Intermittent failures force you to treat systems as if they can fail - and since every system can fail, that's a good thing. This is why chaos engineering is great. b) Failures across a network are the best kind - they're totally isolated. As I explain elsewhere, it's impossible to share state across a network, you can only send copies of state via message passing. These things matter more or less depending on what you're doing.