One thing that I’m currently working on at QuoteOnSite is achieving SOA, whilst ensuring that we don’t go above & beyond with the budget, for obvious reasons. But based on experience & research, it turns out that PM2 & Node seems to be a perfect combination, as we only need a single virtual machine in order to test this approach. 🚀
Using PM2 is a lot more simplistic from an application developer’s perspective compared to the likes of setting up a K8s cluster, just taking into consideration all the ways in which you can setup a K8s cluster is practically insane. Personally I think that just comparing the many different security policies alone is an awesome subject matter! 😅 – But it might not be the most practical subject to address for any SME or start up.
In all honesty, I decided it might be best to apply a hybrid approach to building a monolithic application (kinda), whilst adopting some microservice-esque architecture. A simple example being how we could completely isolate a service at a process level. All of these services would run under the same npm packaged application, that’s one neat thing about this in my opinion is that you could even argue that this would make life a lot easier for a DevOps engineer too. 👨💻
In my personal opinion the true beauty of using something like PM2 is that it’s just an awesome stepping stone, sure you could evolve to that state & leave it there. But I like the idea of slowly, but surely evolving our architecture further, where the ultimate goal is to evolve it to the point where each service has a singleton architecture in place, where one domain area is isolated on it’s own VM, each service has its own codebase, etc. The ultimate goal would probably be to eventually setup a K8s cluster & have each service running as its own pod. But let’s not get ahead of ourselves aye, there’s nothing wrong with baby steps! 👣
Rather than go on & on, I thought that I’d very quickly share some code, starting with a relatively simplistic function that I’ve called
createService, which as you may very well have guessed will spin up the fundamentals that’s needed to develop & create a service.
Now obviously what I’ve done isn’t 100% a hard & fast right way to do it, e.g. with rate limiting, you may want to leave this to other layers of your tech stack. Personally I like to build my stacks to cater for redundancy, e.g. in the case of rate limiting, if the WAF & whatever else sits in front of the application, the application itself is designed with security in mind to some degree or another! 😅
But carrying on, I’ve decided to create the authentication & authorisation bits as shared dependencies, whilst I was working for Admiral, I actually did a bit of a deep dive into whether this domain area should be its own dedicated service or a shared dependency. As a result, I just thought that it would be easier & less resource expensive to cover this domain area as a shared dependency amongst all services, as I’m using express, I decided to simply create it as some middleware! 🧪- Not to mention that it makes the over all setup somewhat less chatty. 🦜
Looking at the folder structure of this server side application, as it’s running on a single server, it currently looks something like this, obviously the plan is to start building more & more services, but it’s a matter about balancing out my time right now! But this is what we have so far:
Obviously I can’t give away too much, but you can see that I’ve separated it out relatively simplistically, where the
index.js file that you can see there, it essentially acts like an API gateway, where all services require the front end application to go through that gateway. It’s not like I’ve not implemented the necessary security processes in place or anything like that, as I’ve said, I like to implement the likes of security at every layer! But with an approach like this, I just find it to be that bit cleaner! 🤘
Having used PM2 to isolate each service at the process level, you can see that this is pretty much all that’s required, obviously there are more services that are in the actual code base, but for an example this should be okay, I can’t share too much! 😉
PM2 vs Docker
I decided to go with PM2 to start with, as one of the core constraints to this project is budget, I don’t want to go on a big spending spree & pay for a multi node K8s cluster, it’s honestly that simple. Sure, you could argue that using Docker on the single VM could achieve something very similar to PM2, but it boils down to simplicity there, rather than having multiple containers running on the same machine, this essentially runs as if it’s a single Node.js application. That means that we can even simplify the CI/CD process, big time, whether this includes big time quality analysis, as it’s a single code base & a single project, it lends it self well there. Sure, if the budget wasn’t such a concern, then I’d probably go with a more singleton approach where each service has it’s own dedicated codebase & each service has it’s own pipeline, etc. It makes sense, but again, with a tight budget, you can’t realistically go for an implementation like that.
Due to the time of writing this, I’m going to rush this conclusion & the fact that I’m being told by the boss (my partner, not my actual boss) that I need to go to bed, as opposed to writing some awesome code! 🙄😅 – If you decide to use Node, then it’s a safe bet that you can use the likes of PM2 to build SOA from day 0, if you can’t use K8’s or Docker Swarm for whatever reasons, then it’s a pretty damn solid alternative! 🤘
From a cost perspective, using something like PM2 means that you can isolate our different services all on a single virtual machine, without having to worry about setting up the necessary infrastructure for the likes of a K8’s cluster. I don’t dislike K8’s at all, I absolutely love K8’s, but I can also appreciate that it might not be the most cost effective solution, especially when you’re looking at an architecture that can evolve as time goes on. 🛰