4 ms·
A few ways, the easiest being to scale up the whole monolith with more instance. Another way is run multiple "services" using the same codebase, so you have wor
by jacobr1 4y ago
A few ways, the easiest being to scale up the whole monolith with more instance. Another way is run multiple "services" using the same codebase, so you have workload segmentation, either via synchronous network calls, or async worker systems.
- MuffinFlavored 4y agodevil's advocate: > A few ways, the easiest being to scale up the whole monolith with more instance as far as I know, there's no way to granularly scale up a monolith. if the monolith has 20 or 50 or 100 modules and you need 1 or 2 of them scaled, you have to scale up the entire thing which is huge, expensive, etc. > Another way is run multiple "services" using the same codebase, so you have workload segmentation, either via synchronous network calls, or async worker systems. this is interesting. a monolith with some form of IPC? why not do microservices at that point? that sounds like microservices-ish?
- jacobr1 4y ago> you have to scale up the entire thing which is huge, expensive, etc. Yes, yet people still do it that way. This is tradeoff against the costs of microservices. I'm not saying it is worth it, but yes, sometimes you can just inefficiently throw hardware resources at scaling problems. > this is interesting. a monolith with some form of IPC? why not do microservices at that point? that sounds like microservices-ish? Because you are incrementally changing an existing monolith, but still getting some of the benefits of scaling distinct workloads independently. If you do this right, it does lend it self to reworking the new "service" to be become its own microservice. Or you can just keep going with the shared codebase.
- JAlexoid 4y ago>I'm not saying it is worth it, but yes, sometimes you can just inefficiently throw hardware resources at scaling problems Microservice scaling is also an inefficient hardware scaling option.
- MuffinFlavored 4y agois this a common nomenclature/design? how does a monolith that makes IPC/RPC calls to submodules not basically microservices?
- __jem 4y agoyes, it's very common design. sometimes called a "distirbuted monolith." it's not microservices because the number of additional services is usually small, and the codebase is still tightly coupled to itself (even if well factored in terms of modules). i.e., everything is still tested together, and there's still a single monolithic build and deployment process, and no team can go off and decide to write a service in a different language.
- MuffinFlavored 4y agoso for example in the context of Java, you have one main App/main() entry, probably bounding to a port (let's say 80 serving HTTP requests) acting as a router it brokerages them to subclasses/handlers for CRUD/RPC/plumbing to database/other services then in a separate process App/main() you have a cron job or a queue of some sort you bundle these together as a monolith into one main()?
- __jem 4y agoIn the case of Java, imagine we have a big Maven project that has a bunch of different well factored modules that form the "libraries" of our application. At first, in our Maven project we also have a single module which is the deployable for "the monolith" -- it consumes all the other "lib" modules and gets packaged into a fat jar. We deploy a few instances of the monolith fronted by a load balancer. There's not much scaling logic here -- when we see p75 request latency reach a certain threshold, we add another monolith instance. A while later, we realize that the /foo route is getting a ton of spikey traffic, which makes it hard to scale. So, in the load balancer, we set up a new pool that just targets /foo, and in our Maven project we create a new module that will be the deployable for this pool. Now, /foo still requires most of our libs, so the jar we're bundling is still "the monolith" in essence, but maybe it doesn't require a few dependencies, and so is a little slimmer. We deploy that and everything is scaling great! Then, we discover that in our main monolith, the background threads we were using to send emails are getting really clogged up, which is adversely effecting performance. We decide we want to move this work to an external persistent queue, like Kafka. Now, for our consumer, we create one more Maven module for a new jar. This time, we're lucky. Emails only need 2 of our libraries and so this is actually a pretty small deployable, but it's still being built from the same core set of libraries as the monolith.
- zeroonetwothree 4y agoThe way it usually works, if 1 of your 100 modules needs to be scaled, it probably means the overall monolith only needs a small amount of extra resources, since that module is only using 1% of the total. So it's not like you need to double the instances of the whole thing. The benefit though is you get a bit of 'free' scaling. Most of the modules don't even have to consider scaling at all, as long as they are growing ~average or slower. So this saves a lot of operational burden for many teams. Conversely with microservices every team has to consider scaling, no matter how simple their service is. (If you do have 1 module out of 100 that takes up 40% of the resources, then it may be appropriate to split it up. Monolith doesn't literally mean "exactly one service", after all, just a small number of big ones.)
- MuffinFlavored 4y ago> The way it usually works, if 1 of your 100 modules needs to be scaled, it probably means the overall monolith only needs a small amount of extra resources, since that module is only using 1% of the total. So it's not like you need to double the instances of the whole thing. I could be wrong but doesn't monolith usually refer to one really heavy app? As soon as you go from needing 1 instance to 2 (because 1 of the 100 inner "modules" needs to be scaled), I would guess most of the time there's a high expense (lots of memory) in duplicating the entire monolith? Unless you can scale threads or something instead of the entire process... Or if the entire process doesn't initiate 100 modules as soon as it is started (although I imagine it would in most cases)
- treis 4y agoYou do lose some memory to holding unnecessary code and whatever data caching that a module does. But it's not generally very much and large data caching can be pushed to Redis. If you're not buying your servers by the rack or data center it's ultimately negligible compared to development cost.
- highspeedbus 4y ago>doesn't monolith usually refer to one really heavy app? No. Backend Server clusters are around almost as long as the internet exists. >I would guess most of the time there's a high expense (lots of memory) in duplicating the entire monolith? That's right, but there's a gotcha. Everytime you split your monolith into parts, that doesn't mean that each part will consume 1/n of original monolith startup resource. There will be a floor of memory usage. Consider 1 monolith that eats up 1GB to startup vs 4 microservices that uses 512MB each. Right from start you doubled the wasted memory from 1GB to 2GB. That only gets worse the more services are created. Another problem is that microservice/cloud folks loves to create anemic machines. Usually setting up 512MB RAM and half a core cpu to a service that needs 380mb minimum :) Thats 75% overhead and 25% of working memory. It's bonkers.
- __jem 4y ago> as far as I know, there's no way to granularly scale up a monolith. if the monolith has 20 or 50 or 100 modules and you need 1 or 2 of them scaled, you have to scale up the entire thing which is huge, expensive, etc. not necessarily. yes, you do pay for executable bloat and some memory overhead from loading code into memory, but the argument here is that you can still deploy a "Service B" from the same deployable that only services certain kinds of requests in order to scale parts of the application horizontally. > this is interesting. a monolith with some form of IPC? why not do microservices at that point? that sounds like microservices-ish? no, because again, you're still deploying the same single codebase, it's just the instance on the other end of the queue is configured just to consume and process messages.