3 ms·
yes, it's very common design. sometimes called a "distirbuted monolith." it's not microservices because the number of additional services is usually small, and
by __jem 4y ago
yes, 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.
- MuffinFlavored 4y agoso you end up with a monolith that might have a config flag or something to determine its purpose when it comes online, and then it can go down a few different code paths. pretty cool. is this something that is done on the fly and then later you don't let that code pattern stay alive (aka, is it not a smell/bandaid)? my concern would be if you accidentally create bugs by basically creating new mini-monolith flavors as the modules were never expected (in the beginning of their creation) to run in a "partial" context
- sally_glance 4y agoI was part of a project that did exactly this - same monolithic code base with config flags that transformed it into web server, worker or scheduler. It allows scaling all parts separately, but I can confirm it's easy to introduce bugs if you're not careful. Since you're sharing the same DB, migrations also need to be backwards-compatible. A cool side-effect is that you can usually run the whole thing in one app for development by just enabling all profiles - as opposed to some microservice architectures where you need dozens of containers and DBs for replicating inter-service bugs.