5 ms·
Microservices are advertised as a means to modularization, but it's what programming language modules are for - they are defined on source code level and can be
by aartur 11y ago
Microservices are advertised as a means to modularization, but it's what programming language modules are for - they are defined on source code level and can be freely used in different runtime components without network/ops/version-management headaches. When you have your module defined that way, you can think of exposing it as a microservice because this may make sense for your use case.
Imagine that each Python module runs as a microservice. For many modules this would lead to huge performance degradation, for example a regexp module can be called thousands times per second, the running time of a call is usually short and replacing an in-process call with a network call will give 100-1000x slowdown.
But if you take a different use case of the same module - complex regexps running on large texts, potentially causing out-of-memory errors, then packing the module into a microservice can make sense - separate processes can have large caches, an out-of-memory error terminates an instance of a microservice only and not the calling process.
Generally I think the advice should be to always use source code modules in the first place, and create microservices using these modules for specific use cases only involving runtime needs like caching, fault tolerance, scalability.
- pjmlp 11y agoYeah, which just goes to show how microservices advocates understand programming.
- sre_ops 11y ago> magine that each Python module runs as a microservice. For many modules this would lead to huge performance degradation, for example a regexp module can be called thousands times per second, the running time of a call is usually short and replacing an in-process call with a network call will give 100-1000x slowdown. This is absolutely irrelevant. If your call budget is 400ms then extra 4ms that it takes fetching a data from a micro service is negligible. Make 400ms 4ms and you are done.
- raverbashing 11y agoYou're right, but sometimes modules != services Your database is a service. You can't use multiple dbs depending on the situation. If it can be replaced by multiple instances of the same module than yes, creating a microservice is probably stupid
- togusa 11y agoMost of the runtime needs in this space can be managed with circuit breakers without having to provide separate processes or memory spaces, be they temporal or resource based. For example your regex, could be given 20ms to run and use a maximum of 8Mb of heap before it is interrupted. This can happen on a single thread and drop back to the caller if an exception is thrown. I'd love to see a language feature which defines the maximum stack and heap for a particular scope i.e. in C#: Breaker.Heap(8.MiB(), () => { Breaker.Time(200.Milliseconds(), () => { // risky operation }); }); (we already do the time breaker, but not the heap) Edit: correct calling convention. Edit 2: add missing extension method brackets
- aartur 11y agoInteresting. Is the circuit breaker a feature of .NET running on Windows? To my knowledge, it can't be implemented on Linux + Java or Python (a thread can't be terminated from outside, and some syscalls involve a whole process).
- eonwe 11y agoI think this can be mostly implemented in Java with bytecode re-writing which will check for the conditions on time to time. Stopping the thread can still leave some of the stuff in indeterminate state if the thread has some resources it needs to release manually.
- togusa 11y agoIt's a library I wrote. The time breaker is actually quite complicated. It is a wrapper that sets up some global parameters on the thread for timeouts on async/await calls and handles the timeout conditions. It integrates with our own async wrappers for external http calls, message delivery, query execution etc. It only enforces that all aggregate async calls will complete or fail by the end of the timeout period. Realistically this is usually around the 500-800ms space as load spikes can break everything otherwise.
- Too 11y ago.net has a public thread.abort function which allows this, it will result in a interruptedexception on the aborted thread. I think there are ways to do this in java and python also although I know the official stance on thread.abort from the python maintainers is no way in hell.
- liotier 11y ago> Microservices are advertised as a means to modularization, but it's what programming language modules are for - they are defined on source code level and can be freely used in different runtime components without network/ops/version-management headaches. When you have your module defined that way, you can think of exposing it as a microservice because this may make sense for your use case. Yes yes yes ! If your architecture and data model are funked up, then it doesn't matter how you implement them - you are screwed. On the other hand, proper modeling with separation-of-concern and well-defined interfaces will let you implement as anything you need, be it microservices or function calls inside a monolith.
- StavrosK 11y agoVery true, but I've heard modularization touted as a benefit of microservices many times, as if it's exclusive. You can get modularization as a first-class feature in your favorite language, and almost for free!
- SixSigma 11y agoWhat you're describing is an operating system. Replace Microservices with Microkernel and you can read the Torvalds-Tannebaum debate instead [1] http://www.oreilly.com/openbook/opensources/book/appa.html http://www.oreilly.com/openbook/opensources/book/appa.html
- dmux 11y ago>they are defined on source code level and can be freely used in different runtime components... To me, components and services are two completely separate abstractions. A component is a collection of code -- a module -- that can be duplicated and used in numerous different systems (much like a 5 ohm resistor). Updating a module in one system doesn't affect any other external system. Services on the other hand I think of as multi-tenant systems that are used to provide common functionality that is likely to change.