You can set up a load balancer for your web servers with the help of Apache2.
A web server will have to act as a load balancer, which then distributes the web user requests to other servers in a "cluster". These servers in the cluster are mirrors of your web server.
The "cluster" contains all the web servers that will wait for distributed requests from the load balancer.
You need to enable the following modules on the server, which was chosen to be the load balancer.
a2enmod mod_proxy mod_proxy_balancer mod_proxy_http mod_cache mod_disk_cache mod_deflate mod_rewrite mod_headers lbmethod_byrequests
These modules will set up the proxy module, which is needed for the load balancer. But also other modules that are needed to process the HTTP headers and data.
This is an example on how you can set up a load balancer in Apache2, that distributes requests to three servers. These three servers are part of our cluster "mycluster".
Add this to a vhost file. This is how the load balancer would be configured in an SSL vhost:
<IfModule mod_ssl.c>
<VirtualHost *:443>
#Server name / domain name of your load balancer - this should be your domain name of your web site
ServerName my-load-balancer-server-name
DocumentRoot /var/www/
# Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
# error, crit, alert, emerg.
# It is also possible to configure the loglevel for particular
# modules, e.g.
#LogLevel info ssl:warn
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
RewriteEngine on
#Settings of the load balancer behaviour
ProxyRequests Off
ProxyPreserveHost Off
SSLProxyEngine On
#Deactive check if the SSL certificate is valid. If you did activate these two commands and you use Let's Encrypt certificate, then this could cause SSL handshake errors.
SSLProxyCheckPeerCN off
SSLProxyCheckPeerExpire off
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
#Settings of the load balancer
ProxyPass /balancer-manager !
ProxyPass / balancer://mycluster/ stickysession=BALANCEID nofailover=On
#The different domain names of our servers in the cluster are accessed through the same URL.
ProxyPassReverse / https://1.domain.tld/
ProxyPassReverse / https://2.domain.tld/
ProxyPassReverse / https://3.domain.tld/
#The servers that are in our cluster "mycluster" - Settings for the distribution of requests among servers
<Proxy balancer://mycluster>
BalancerMember https://1.domain.tld route=httpOne status=-SE timeout=30 retry=60
BalancerMember https://2.domain.tld route=httpTwo status=-SE timeout=30 retry=60
BalancerMember https://3.domain.tld route=httpThree status=-SE timeout=30 retry=60
#ProxySet lbmethod=bybusyness failontimeout=on
ProxySet lbmethod=byrequests failontimeout=on
</Proxy>
#Restrict access to the GUI of the load balancer - User accounts are defined in /etc/apache2/.htpasswd
<Location /balancer-manager>
SetHandler balancer-manager
AuthType Basic
AuthName "Please enter your username and password"
AuthUserFile /etc/apache2/.htpasswd
require valid-user
</Location>
</VirtualHost>
</IfModule>
This vhost is trimmed and shows only the settings of the load balancer. In this example the load balancer distributes the requests by the number of requests (lbmethod=byrequests). The load balancer checks for 30 seconds, if the server is reachable. If a server is not reachable (causes: error, etc.), then the load balancer distributes the request to another server. The load balancer will check, if the server is available again after 60 seconds.
If the load balancer should distribute by how the server is busy with requests, then you have to use the method "lbmethod=bybusyness". This method needs the module "lbmethod_bybusyness".
Other distribution methods:
https://httpd.apache.org/docs/2.4/mod/mod_proxy_balancer.html