Load Balanced web infrastructure using HAProxy and Apache

Web infrastructure


In order to serve a big number of users for our web applications we need to have a load balanced, highly available and scalable infrastructure for our web layer, application layer and database layer, several software are used to achieve these objectives, here in this article we will demonstrate how to create a web cluster with a load balancer in front of it to serve a big number of users.

Used software: haproxy , apache .

Introduction

Before I start talking about the used software and how we will use them here. I will demonstrate some of the main concepts mentioned above: load balanced, highly available and scalable.

Load balanced: No single server can handle the load generated by many users around the world trying to access a web site, so multiple servers are deployed to serve client requests but clients need a single endpoint to access the web site you cannot ask a client to try multiple endpoints until one of them can serve you in a timely manner here comes the role of a load balancer it provides a single endpoint for clients to connect to it when they want to access a web site and also it distributes requests to multiple servers so no single server is overloaded with client requests and client requests are served as quickly as possible by a server that is not overloaded, haproxy is considered one of the best load balancers in the market we will use it here.

Highly available: We want our apps to be up and running (available) all the time and to achieve this we must use multiple servers to run our apps on them and our apps must be fault tolerant which means that if one server fails other servers can take its place immediately and continue to serve client requests as normal.

Scalable: Multiple users will use our apps at the same time, no fixed number of servers can handle this load at the same time so we need to be able to scale up and down the number of servers at anytime to be able to serve and increasing number of users, stateless apps can be scaled easily however statefull apps are harder to scale depending on the used storage medium for their state.


Haproxy can be used to load balance multiple web servers, here we will install it and configure it with two apache servers each one of them serving a different page depending on the server used to send the response.

Hint: This article assumes that the user has access to three ubuntu servers running on the cloud or as virtual machines on your local work station.

Haproxy

Haproxy is free and open source very fast and reliable solution offering high availability, load balancing and proxying for TCP and HTTP based applications, it can be used to load balance a cluster of web servers also if the applications we are running do not use HTTP protocol we can still load balance them at the transport layer for example we can load balance a cluster of mysql servers using haproxy as long as every read/write query can be executed on any node in the cluster which is the case if we are using percona, galera or NDB cluster however if we are using group replication where reads are executed on slaves and writes are executed on masters we need to use a protocol aware proxy such as proxysql.

Installation

Haproxy is part of default ubuntu repositories it can be installed using a simple command:

sudo apt-get install haproxy

Configuration

After haproxy is installed we need to configure it, first make sure haproxy starts when the server boots by changing the value of ENABLED to “1” in this file /etc/default/haproxy

Now we need to edit haproxy main configuration file, before we do that we can take backup of the default configuration file so we can revert our changes at anytime, to take backup execute this command

sudo cp /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg.old


Now write the following in /etc/haproxy/haproxy.cfg

defaults
	mode http
	timeout connect 2500
 	timeout server 2500
	errorfile 503 /etc/haproxy/errors/503.http

frontend www-http
	bind 0.0.0.0:80
	default_backend www-backend

backend www-backend
    balance roundrobin
	server web1 192.168.100.11:80 check
	server web2 192.168.100.12:80 check


Replace 192.168.100.11 and 192.168.100.12 with your web servers IP addresses.

The previous configuration file has three sections:

defaults: Here we default values for many configuration options, we are defining here three options: mode, timeout connect, timeout server, errorfile 503. mode is used to specify HTTP or TCP load balancing, timeout connect specifies the maximum timeout in milliseconds when trying to connect to any backend server, timeout server specifies the maximum timeout in milliseconds when waiting for a response from a backend server, errorfile 503 is used to select a web page to send when the server wants to send a 503 error, this error code means the backend server did not send a response within timeout server value so no need to wait any further for the response.

frontend: This section defines the frontend of our proxy where client requests will be received, we have two options here bind: to tell which ip address to bind to it and port using 0.0.0.0 means bind to all IP addresses, the default_backend option defines the default group of backend servers to serve requests comming to this frontend.

backend: Here we define all the backend servers that will serve client requests, each server is defined using the server directive followed by a name for the server and the server’s IP address. We also specify the load balancing algorithm using the balance option, here we select roundrobin.


Now after we changed haproxy configuration file, we must restart it for changes to take effect with this command

sudo systemctl restart haproxy


If we try to put the IP address of the load balancer using a web browser we get an error because the backend servers are not configured yet.

Apache

Apache web server is the most popular web server software since April 1996, it was started in 1995 and celebrated its 20th anniversary in February 2015. Apache is well known for its high performance, it can also execute and serve PHP scripts right from within its own process and not use an external server such as PHP-FPM as other web server software, this makes it better in serving dynamic content than its main competitor Nginx.

Apache uses XML for its configuration files, each site served by apache has its own configuration file located in the sites-enabled folder, it also has sites-available folder which lists sites defined in apache but not currently enabled, to enable a site just create a symlink for it in sites-enabled folder that points to its configuration file in sites-available folder, you can use a2ensite tool for this purpose.

Installation

Apache can be installed on Ubuntu server easily using this command

sudo apt-get install apache2

Configuration

Each site in apache has a configuration file in /etc/apache2/sites-available, the files here define sites for apache but not all these sites are already enabled and can be served by apache only sites defined in /etc/apache2/sites-enabled can be served by apache.

We need to install apache on two servers and create one site on each server, the process will be described on the first server and similar commands can be used on the second one.

Copy apache default configuration file to create a template for a new site

sudo cp /etc/apache2/sites-available/000-default.conf /etc/apache2/sites-available/example.com.conf

Put the following content in the new file

<VirtualHost *:80>
        ServerName example.com
        ServerAdmin mohsen47@hotmail.co.uk
        DocumentRoot /var/www/html/example.com
        ErrorLog ${APACHE_LOG_DIR}/example.com_error.log
        CustomLog ${APACHE_LOG_DIR}/example.com_access.log combined
</VirtualHost>

Now we will describe each option used:

ServerName: defines the name of the site, it is the same as DNS name used for the server, example.com must resolve to the IP address of server where haproxy is installed.

ServerAdmin: The email address of the server’s administrator who can be called in case of errors.

DocumentRoot: defines the folder where the site’s files will be served, if we browse to example.com/first.html the file located at /var/www/html/example.com/first.html will be returned in the response.

ErrorLog: This defines the path used to store error logs for the site, this is located at /var/log/apache2/example.com_error.log

CustomLog: This defines the path used to store the site’s access log, every user who opens the site will be logged here.

Now it is time to enable the new site and restart apache for changes to take effect

sudo a2ensite example.com.conf
sudo systemctl restart apache2

Now create the folder for the new site and index.html file

sudo mkdir /var/www/html/example.com
sudo nano /var/www/html/example.com/index.html

Type the following in the file

<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title>s1</title>
  </head>
  <body>
    Server 1 here
  </body>
</html>


Now repeat the same steps for the second server but change the contents of the index.html file to include the name of the second server.

Now after configuring the apache2 servers and also your haproxy server we can start testing the setup but we need to define the example.com domain locally so we can access the site using DNS address.

We can use the hosts file on your local machine to give an IP address for example.com domain, if you are using Windows navigate to this folder C:\Windows\System32\drivers\etc here there is a file called hosts open it and add the following line to it

11.11.11.11 example.com # Repalce 11.11.11.11 with the public IP address of haproxy server


If you are using Linux or MacOS on your local machine, the file can be located in /etc/ folder.

Now open your browser and request the example.com domain, you will notice that haproxy balances the requests between the two servers using roundrobin algorithm, it might use one server for most of the requests but if you use another browser or refresh quickly you will get response from both severs.
Try to shutdown one server and haproxy will stop sending requests to it and only use the other healthy server.

Conclusion

In this article we learned how to create a small web cluster to balance the load between multiple servers so we can serve an increasing number of simultaneous users, also it is highly available if one server fails other servers can be used to serve clients, the same setup with few modifications can be used for web applications, we will explore this more in the future.