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! 🐶

Server split

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 SSLCertificateFile and SSLCertificateKeyFile.

The proxy functionality is handled by directives ProxyPassMatch and ProxyPassReverse which have pretty self-explanatory syntax.

Now when configuration file is saved it's a good time to check its syntax.

apachectl configtest

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.