5 ms·
In practice micro services mean that you turn a function or method call into a network request. This doesn't really limit communication bottlenecks. It is often
by jules 10y ago
In practice micro services mean that you turn a function or method call into a network request. This doesn't really limit communication bottlenecks. It is often more difficult to argee on a network interface than on a simple function or object interface. It's also more difficult to change. You introduce a whole new set of failure modes due to going over the network. Debugging is more difficult since you now can no longer step through your program in a debugger but rather have an opaque network request that you can't step into. You can no longer use editor/IDE features like go to definition. It becomes harder to do integration tests. Version control becomes harder if the different services are in different repositories. A network request is much slower than a function call. You no longer have the advantage of a garbage collector for logical values that now cross network boundaries, and rather need to manually free them. Deployment is more difficult. The list is much longer than this, but I'd be interested in the counter-list: what are the advantages of micro-services?
- totally 10y agoYes, but there's another dimension here. If another team breaks your build in a monolithic repo, you may or may not be able to resolve this quickly. You're in a contract with them about the state of the repo and thus your service. With microservices, the production version of their service would conceivably be stable. It moves the contract from the repo to the state of production services.
- wtbob 10y ago> If another team breaks your build in a monolithic repo, you may or may not be able to resolve this quickly. With a monolithic repo done right, the other teams broke their build of their branch, and it's up to them to resolve it. You, meanwhile, are perfectly happy working on your branch. When their changes are mergeable into trunk, then they may merge them, not before — and likewise for you. With multiple repos, they break your build, but don't know it. You don't know it either, until you update your copies of their repos — and now you have to figure out what they did, and why, and how to update your logic to handle their new control flow, and then you update again and get to do it again, until finally you ragequit and go live in a log cabin with neither electricity nor running water.
- vonmoltke 10y ago> With multiple repos, they break your build, but don't know it. You don't know it either, until you update your copies of their repos — and now you have to figure out what they did, and why, and how to update your logic to handle their new control flow, and then you update again and get to do it again, until finally you ragequit and go live in a log cabin with neither electricity nor running water. I don't see how this is a problem if you are pushing frequently and have a CI system. You know within minutes if the build is broken. If it broke, don't pull the project with the breaking changes. My point is, I don't think one approach is inherently better than the other. Both require effort on the part of the teams to manage changes (or a CM team), and both require defined processes.
- sanderjd 10y ago> If it broke, don't pull the project with the breaking changes. I agree with the overall sentiment of your comment, but the quoted part is where I've seen trouble brew. The tendency is to be conservative about pulling updates to dependencies, which can easily get you into a very awkward state when a critical update eventually sits on top of a bunch of updates you didn't take because they broke you. It is usually better to be forced to handle the breakage immediately, one way or another.
- totally 10y ago> With a monolithic repo done right. Yes, that's the contract that you need to have with other teams. And it's the contract that is automatically enforced with microservices.
- cookiecaper 10y agoI just want to add one disadvantage before I give some advantages. There's a lot of operational complexity involved in routing, monitoring, and keeping every instance of every microservice running. That complexity also makes debugging in production much more difficult, as one must track a relay of network requests through many separate layers to find the point where it actually got stuck. As for advantages, microservices tend to keep code relatively simple and free from complex inheritance schemes. There's rarely a massive tangled-up engine full of special cases in the mix, as there often is in monolithic apps. This substantially decreases technical debt and learning curve, and can make it simple to understand the function an isolated microservice performs. There is the obvious advantage that if you have disparate applications executing nearly-identical logic to read or write data to the same location, and the application platforms can't execute the same library code, you can centralize that logic into an HTTP API, which reduces maintenance burden and prevents potentially major bugs. My opinion is that adopting microservices as a paradigm leads to a slow, difficult-to-debug application, primarily because people take the "micro" in microservices too seriously. One shouldn't be afraid to split functionality out into an ordinary service after it's been shown to be reasonable to do so.
- mseebach 10y agoI think that your comment is actually a pretty good test for when not to spin out a micro service. If you expect to need to step into a function call when debugging, then it's too tightly coupled to spin out. You should be able to look at the arguments to the call and the response and determine if it's correct (and if not, now you have isolated a test case to take to the other service and continue debugging there). If the interface will change so often that you expect it will be a problem that it's in a separate repository, if you expect that you will always need to deploy in tandem, then it's too tightly coupled to spin out. The advantage of micro services is the separation in fact of things that are separate in logic. The complexity of systems grows super-linearly, so it's easier to reason about and test several smaller systems with clear (narrow) interfaces between them than one big. It's easier to isolate faults. It's harder to accidentally introduce bugs in a different part of the system when the system doesn't have a different part. If done right, scaling can be made easier. But these are hard architectural questions, there's no clear-cut rule for when you should spin off a new service and when you should keep things together. Someone else mentioned separating the shopping app from the payment system for an ecommerce business, which even has security benefits. I think that's an excellent example. Edit: Another clear benefit is that you can choose different languages, libraries, frameworks and paradigms for different parts of the code. You can write your boring CRUD backend admin app in Ruby on Rails, your high-performance calculation engine in Rust and your user-facing app in Node.js (so the front- and backend an share Javascript validation code).
- wtbob 10y ago> You introduce a whole new set of failure modes due to going over the network. A thousand times yes. Distributed systems are hard. > Debugging is more difficult since you now can no longer step through your program in a debugger but rather have an opaque network request that you can't step into. Yes. Folks underestimate how difficult this can be. In theory it should be possible to have tooling to fix this, but I've not seen it in practice. > You can no longer use editor/IDE features like go to definition. Not a problem with a good editor. > Version control becomes harder if the different services are in different repositories. No organisation should have more than one regular-use repo (special-use repos, of course, are special). Multiple repos are a smell.
- jshmrsn 10y ago> No organisation should have more than one regular-use repo (special-use repos, of course, are special). Multiple repos are a smell. Mind elaborating on this?
- dietrichepp 10y ago> No organisation should have more than one regular-use repo (special-use repos, of course, are special). Multiple repos are a smell. I would modify this slightly. Larger organizations with independent teams may want to run on per-team repos. Conway's law is an observation about code structure but it sometimes also makes good practice for code organization. And of course, sometimes the smell is "this company is organized pathologically". Another problem is that large monolithic repositories can be difficult to manage with currently available software. Git is no panacea and Perforce isn't either.
- pc86 10y ago> No organisation should have more than one regular-use repo Flat out wrong for any organization with multiple products. Which, let's be honest, is most of them.
- dietrichepp 10y agoI guess Facebook, Twitter, and Google are doing things "flat out wrong", then. Yes, that's a weak argument (argument from authority) but it is true that monolithic repositories have major advantages even for organizations with multiple products. Common libraries and infrastructure are much easier to work with in monolithic repositories. My personal take on it, at this point, is that much of our knowledge of how to manage projects (things like individual project repos, semantic versioning, et cetera) is centered on the open-source world of a million mostly-independent programmers. Things change when you work in larger organizations with multiple projects. You even start to revisit basic ideas like semantic versioning in favor of other techniques like using CI across your entire codebase.
- marcosdumay 10y agoThat's true, but... You don't debug distributed systems by tracing into remote calls and jumping into remote code. You debug it by comparing requests and responses (you use discrete operations, right) with the specified requests and responses, and then opening the code that has a problem¹. It calls for completely different tooling, not for a "better debugger". 1 - Or the specs, because yes, now that your system is distributed you also have to debug the specs. Why somebody would decide on doing that for no reason at all? Yet lots of people do.