Or reinvention of microservices :)
While developing node.js back-end application you have to get rid of blocking i/o events in all possible ways. But what to do, if your application does have feature that is blocking by its own nature? In my case it was rendering. So, when render was running for 2-3 seconds (yep, thats really tiny render) all the API events were waiting. Which is not really pleasant.
The solution is simple - divide and conquer. In other words to move the blocking feature outside the API server. Basically, to make a copy of the server and remove all the functionality except rendering, meanwhile in the original server code - to remove only the render feature. So, it would split into two server applications: one for rendering, another for everything else. Wow! So microservice! 🐶
Now we can run these apps on different physical machines or on one machine using the different ports.
For sake of backward compatibility for outdated clients and web application we had to leave one endpoint to handle both requests. This is the job for the reverse proxy.
api.example.com/render/ -> localhost:3001 api.example.com/* -> localhost:3000
As application runs in an AWS cloud the first try was to use an application load balancer. It's pretty simple to configure and provides conditional routing. You just need to create two target groups and route your traffic on this targets. Also if you use ssl certificates issued by Amazons ACM thats perfectly fits. But in my case it was on overkill, load to handle was really low and monthly price of $38 for the stuff I can get for free with a simple apache configuration or express-http-proxy make me to do it on my own.
So, how to set up reverse proxy with apache.
At first you need to have an Apache installed on your web server machine. For example thats how it's usually installed on Ubuntu:
sudo apt-get install apache2 sudo a2enmod proxy sudo a2enmod proxy_http sudo systemctl restart apache2
Put your ssl certificates on the server instance where apache is installed, if you have them. If they're issued by ACM there is no option to export them, so my advise is to buy ssl certificates somewhere else or use letsencrypt to get them for free!
Now in the directory
etc/apache2/sites-available create config file with similar contents:
<IfModule mod_ssl.c> <VirtualHost *:443> ProxyPreserveHost On ServerName api.example.com ProxyPassMatch ^/render$ http://localhost:3001 ProxyPassReverse ^/render$ http://localhost:3001 ProxyPass / http://localhost:3000/ ProxyPassReverse / http://localhost:3000/ SSLCertificateFile /etc/ssl/example.com/fullchain.pem SSLCertificateKeyFile /etc/ssl/example.com/privkey.pem </VirtualHost> </IfModule>
This configuration handles signing of https traffic by selected ssl certificates in directives
The proxy functionality is handled by directives
ProxyPassReverse which have pretty self-explanatory syntax.
Now when configuration file is saved it's a good time to check its syntax.
If all tests are passed we can enable it and reload apache configurations.
a2ensite exampe_conf_filename sudo systemctl reload apache2
The render and api instances not necessarily should be on a localhost, they may use a dedicated hosts of different size and configurations. But in this article we're looking how to avoid blocking at first, and not how to build microservices.