Let's Balance the load Part 3 - L7
Creating a L7 Load Balancer
At L7 level we use reverse proxies to expose our services to the clients and these reverse proxies forwards the traffic to the actual servers based on various load balancing algorithms.
Different Mecahnisms for Load Balancing in Nginx
Nginx has 3 mechanisms for Load balancing:
- Round Robin
- Least Connections
- IP Hash
Let’s go over them one by one to see how we can set them up.
Round Robin
This is the default load balancing mechanism used by Nginx. In Round Robin, requests to the application servers are distributed in a round-robin fashion.
1
2
3
4
5
6
7
8
9
10
11
12
13
upstream myapp1 {
server 192.168.1.1;
server 192.168.1.2;
server 192.168.1.3;
server 192.168.1.4;
}
server {
listen 80;
location / {
proxy_pass http://myapp1;
}
}
Update
myapp1
with your actual server address.
Least Connections
In order to use Least Connections, you need to specify the least_conn
directive in your Nginx configuration. In Leas Connections mechanism, the next request is assigned to the server with the least number of active connections.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
upstream myapp1 {
least_conn;
server 192.168.1.1;
server 192.168.1.2;
server 192.168.1.3;
server 192.168.1.4;
}
server {
listen 80;
location / {
proxy_pass http://myapp1;
}
}
IP Hash
Finally in IP Hash, a hash-function is used to determine what server should be selected for the next request typically client’s IP address is used for hashing. We can enable this by using ip_hash
directive in the upstream configuration.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
upstream myapp1 {
ip_hash;
server 192.168.1.1;
server 192.168.1.2;
server 192.168.1.3;
server 192.168.1.4;
}
server {
listen 80;
location / {
proxy_pass http://myapp1;
}
}
Configuring Nginx as a Reverse Proxy
Most of the L7 load balancers are build on top of some sort of Proxies. We will use Nginx as our proxy for this example. We will use Docker to deploy our Nginx proxy and configure it for load balancing.
1
2
3
# On 10.10.10.1
docker pull nginx
docker run -it --rm -d -p 8080:80 --mount type=bind,source="$(pwd)"/nginx.conf,target=/etc/nginx/conf.d/default.conf,readonly --name load-balancer nginx
Here
nginx.conf
in thepwd
is the configuration file for Nginx which has the configuration for load balancing. Please create this file with one of the configurations mentioned above.
Testing
To test the load balancer you can host Nginx on those servers with custom html file.
Let’s create a simple HTML file for each server. For example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to Server 1!</h1>
</body>
</html>
Change the server number for every server to know which server html file is coming from.
Start Nginx server on each server:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# On 192.168.1.1
docker pull nginx
docker run -it --rm -d -p 80:80 --mount type=bind,source="$(pwd)"/server1-index.html,target=/usr/share/nginx/html/index.html,readonly --name server1 nginx
# On 192.168.1.2
docker pull nginx
docker run -it --rm -d -p 80:80 --mount type=bind,source="$(pwd)"/server2-index.html,target=/usr/share/nginx/html/index.html,readonly --name server2 nginx
# On 192.168.1.3
docker pull nginx
docker run -it --rm -d -p 80:80 --mount type=bind,source="$(pwd)"/server3-index.html,target=/usr/share/nginx/html/index.html,readonly --name server3 nginx
# On 192.168.1.4
docker pull nginx
docker run -it --rm -d -p 80:80 --mount type=bind,source="$(pwd)"/server4-index.html,target=/usr/share/nginx/html/index.html,readonly --name server4 nginx
Now try to load the website using ip address of the load balancer machine.
1
curl http://10.10.10.1:8080/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to Server 1!</h1>
</body>
</html>
Running the curl command again results in response from another server:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to Server 2!</h1>
</body>
</html>
Conclusion
- We implemented a basic L7 load balancer using
nginx
. - The load balancer can distribute incoming traffic based on different algorithm.
- The actual web server sees that all the traffic is coming from the same IP address i.e. the IP of the load balancer (
10.10.10.1
). - Optionaly the
X-Forwarded-For
header may have the IP address of the original client.