As I started building Docker service container images for Magento 2 CE development I got interested in the concept of dynamic service load balancing on a single host. Having already created a dynamic load balancer using NGINX I wanted to do the same for Magento 2 using Varnish.
My Magento 2 service container images include REDIS services for the Magento session and system cache and a Varnish service for the full page cache. Varnish is an HTTP accelerator designed for content-heavy dynamic web sites and is the recommended full page cache system for Magento 2.
Varnish is configured via the Varnish Configuration Language (VCL) config file. By configuring multiple backend servers in VCL and grouping them into a director we can create a Varnish load balancer.
Varnish Magento 2 load balancing VCL[text] backend magento2_php_apache_1 { .host = "x.x.x.2"; .port = "80"; .probe = {.request = "GET /healthcheck.php HTTP/1.1" "Host: magento2.gaiterjones.com" "Connection: close" "Accept: text/html";.timeout = 1s;.interval = 30s;.window = 10;.threshold = 8;} } backend magento2_php_apache_2 { .host = "x.x.x.8"; .port = "80"; .probe = {.request = "GET /healthcheck.php HTTP/1.1" "Host: magento2.gaiterjones.com" "Connection: close" "Accept: text/html";.timeout = 1s;.interval = 30s;.window = 10;.threshold = 8;} } backend magento2_php_apache_3 { .host = "x.x.x.10"; .port = "80"; .probe = {.request = "GET /healthcheck.php HTTP/1.1" "Host: magento2.gaiterjones.com" "Connection: close" "Accept: text/html";.timeout = 1s;.interval = 30s;.window = 10;.threshold = 8;} } backend magento2_php_apache_4 { .host = "x.x.x.11"; .port = "80"; .probe = {.request = "GET /healthcheck.php HTTP/1.1" "Host: magento2.gaiterjones.com" "Connection: close" "Accept: text/html";.timeout = 1s;.interval = 30s;.window = 10;.threshold = 8;} } backend magento2_php_apache_5 { .host = "x.x.x.9"; .port = "80"; .probe = {.request = "GET /healthcheck.php HTTP/1.1" "Host: magento2.gaiterjones.com" "Connection: close" "Accept: text/html";.timeout = 1s;.interval = 30s;.window = 10;.threshold = 8;} } sub vcl_init { new cluster1 = directors.round_robin(); cluster1.add_backend(magento2_php_apache_1); cluster1.add_backend(magento2_php_apache_2); cluster1.add_backend(magento2_php_apache_3); cluster1.add_backend(magento2_php_apache_4); cluster1.add_backend(magento2_php_apache_5); } [/text]
Scale Manager
I use a service container called php-apache to run the Magento core code. Docker compose allows you to scale containers on a single host, so for example with the command
docker-compose scale php-apache=5
I can quickly scale the Magento2 php-apache service up to 5 containers, that is 5 instances of the php-apache service running the Magento2 core php code and apache web server.
The scale manager service monitors docker processes and detects when the php-apache service is scaled up or down. When a change is detected it dynamically creates the VCL configuration required to tell Varnish about the changes and applies these to the Varnish server.
Magento 2 Scale Demo
In the video below I start with one running instance of the Magento 2 service, I then scale the service up to 5 and using the scale demo page (which is not cached by Varnish) on my Magento 2 dev site to analyse the scale manager output data and display the running Magento 2 service containers.
As I refresh the page the Magento 2 container rendering the page is highlighted in yellow. you can see how Varnish round robins between the 5 available containers. Finally I scale the service back down and manually update the Varnish server config via the command line php script on the manager.
Another way to see the round robin connection distribution from varnish is to load up a phpinfo() page, you will see the SERVER_ADDR variable changing with each container that processes the request.
Would you actually run 5 Magento 2 php-apache services? Good question! For true resilience and load balancing you would need multiple hosts and a Docker swarm. Multiple service containers on a single host do at least provide a simple level of redundancy and host server load balancing, I would definitely consider using it in production especially with a multi core server.
Many thanks to Fabrizio Balliano for the inspiration and assistance.
See this post for instructions on how to deploy this Magento 2 development environment.
Felipe says:
Great post. However, when I clear the cache or flush the cache to see my changes made in the store code even with apache scaled to 5 I have to wait for around 40s. Why does it take that long?
My store is in development mode