Load Balancing with Nginx
One of the most important steps to keep your website seamlessly working for the users to provide better user experience is Load Balancing. This practice is used to balance the load on multiple backend servers based on the number of connections, server load, IP, etc. or with the default round robin algorithm.
How to add/edit a domain configuration in nginx?
The default configuration file for Nginx is /etc/nginx/nginx.conf. You can add domains to this configuration but it will become harder to manage. So, it is recommended to add another configuration file (in /etc/nginx/sites-available
directory) and add a new domain to it.
1. Start by creating a new configuration file in sites available directory. Name the configuration file with the domain name in it for quick identification:
$ sudo touch /etc/nginx/sites-available/example-domain.com.conf
2. Open the configuration for your website (for my examples, I'll just use the domain.com virtual host):
$ sudo vi /etc/nginx/sites-available/example-domain.com.conf
How to setup Nginx Load Balancer?
The nginx upstream module will be required to set up a round-robin load balancer. The upstream module, which looks like this, must first be included in the Nginx configuration:
For instance, we have 4 backend servers at IPs 157.19.33.1
, 157.19.33.2
, 157.19.33.3
, 157.19.33.4
each running on port 80
. So first we add an upstream block inside http block, to group these servers which can be referenced by other directives. We can name the upstream block, i.e backend.
http{
...
upstream backend {
server 157.19.33.1;
server 157.19.33.2;
server 157.19.33.3;
server 157.19.33.4;
}
...
}
The round-robin load balancer forwards a client request to each server in turn as it moves down the list of group servers. The load balancer loops back and continues down the list once it reaches the bottom.
Below this upstream block, we need to add our server block that directs requests to these backend servers, by referring to the upstream block in the proxy_pass directive.
We must add our server block, which routes requests to these backend servers, underneath this upstream block. By using the proxy_pass
directive.
server {
listen 80;
server_name domain.com;
location / {
proxy_pass http://backend;
}
}
By further modifying the server block, we get the following configuration which uses a round-robin algorithm to load balance.
http {
upstream backend {
server 157.19.33.1;
server 157.19.33.2;
server 157.19.33.3;
server 157.19.33.4;
}
server {
listen 80;
server_name domain.com;
location / {
proxy_pass http://server;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $proxy_protocol_addr;
proxy_set_header X-Forwarded-For $proxy_protocol_addr;
proxy_read_timeout 600s;
}
}
}
Nginx Load balancing methods
1. Least Connection
Another simple technique is load balancing depending on the number of connections. This approach, as its name suggests, sends requests to the server that is currently hosting the fewest active connections. It functions better in applications where requests could occasionally take longer to finish than round-robin would.
Add the parameter least_conn
to your upstream section as shown in the example below to enable the least connections balancing approach.
upstream backend {
least_conn;
server 157.19.33.1;
server 157.19.33.2;
server 157.19.33.3;
server 157.19.33.4;
}
2. Using Weight
We can set the percentage of traffic that should be sent to each server using a number with Nginx. Giving specific weight to particular machines is one method to start allocating users to servers with higher accuracy.
upstream backend {
server 157.19.33.1 weight=1;
server 157.19.33.2 weight=6;
server 157.19.33.3;
server 157.19.33.4 weight=3;
}
3. Hash
Visitors are directed back to the same VPS each time they visit thanks to IP hash, which enables servers to respond to clients based on their IP addresses (unless that server is down). A server ought to be listed as down if it is known to be idle. Then, all IPs that were meant to be routed to the unavailable server are sent to a different one.
upstream backend {
ip_hash;
server 157.19.33.1;
server 157.19.33.2;
server 157.19.33.3 down;
server 157.19.33.4;
}
4. Max Fails
By default in a round-robin algorithm, Even if the virtual private servers are not responding, nginx will still send requests to them. By making unresponsive servers inactive for a predetermined period of time, Max Fails can automatically stop this from happening.
The max failures are affected by two variables: max_fails
and fail_timeout
. The term "max_failures
" designates how many unsuccessful attempts there should be to connect to a server before it is deemed inactive. The amount of time that the server is deemed to be down is specified by the fail_timeout
setting. New attempts to contact the server will begin when the timer expires. 10 seconds are the default timeout value.
upstream backend {
server 157.19.33.1 down;
server 157.19.33.2 weight=5;
server 157.19.33.3 max_fails=3 fail_timeout=5s;
server 157.19.33.4 weight=2;
}
Finally, save the configuration file and exit the text editor.
Verify our configuration, then launch Nginx.
It is a recommended practice to test new configurations before loading them to the production server because a single syntax mistake will prevent the Nginx service from running, which will prevent users from accessing your website. You can use the following command to do so.
$ sudo nginx -t -c /etc/nginx/sites-available/example-domain.com.conf
Enable the site if no issues were discovered. In order to accomplish this, we must build a symbolic link between the site configuration file and the sites-enabled directory using the following command:
$ sudo ln -s /etc/nginx/sites-available/example-domain.com.conf /etc/nginx/sites-enabled/example-domain.com.conf
Finally, Start/Restart/Reload the server to load the changes:
$ sudo systemctl restart nginx
or
$ sudo service nginx restart