Linux:Powerful Server Administration
上QQ阅读APP看书,第一时间看更新

Load balancing with Nginx

When an application becomes popular and the number of requests increases beyond the capacity of a single server, we need to scale horizontally. We can always increase the capacity (vertical scaling) of a server by adding more memory and processing power, but a single server cannot scale beyond a certain limit. While adding separate servers or replicas of the application server, we need a mechanism which directs the traffic between these replicas. The hardware or software tool used for this purpose is known as a load balancer. Load balancers work as transparent mechanisms between the application server and client by distributing the requests between available instances. This is a commonly used technique for optimizing resource utilization and ensuring fault tolerant applications.

Nginx can be configured to work as an efficient Layer 7 as well as Layer 4 load balancer. Layer 7 is application layer of HTTP traffic. With Layer 4 support, Nginx can be used to load balance database servers or even XMPP traffic. With version 1.9.0, Nginx has enabled support for Layer 4 load balancing in their open source offerings.

In this recipe, we will learn how to set up Nginx as a load balancer.

Getting ready

You will need access to a root account or an account with sudo privileges.

You will need a minimum of three servers, as follows:

  • An Nginx server, which will be set as a load balancer
  • Two or more application servers with a similar code base set up on all

How to do it…

Follow these steps to set load balancing with Nginx:

  1. I assume that you already have Nginx installed. If not, you can refer to the Installing Nginx with PHP_FPM recipe of this chapter.
  2. Now, create a new configuration file under /etc/nginx/sites-available. Let's call it load_balancer:
    $ sudo nano /etc/nginx/sites-available/load_balancer
    
  3. Add the following lines to this load_balancer file. This is the minimum configuration required to get started with load balancing:
    upstream backend {
     
    server srv1.example.com;
     server srv2.example.com;
     server 192.168.1.12:8080;
     # other servers if any
    }
    server {
     listen 80;
     location / {
     proxy_pass http://backend;
     }
    }
    
  4. Enable this configuration by creating a symlink to load_balancer under sites-enabled:
    $ sudo ln -s /etc/nginx/sites-available/load_balancer /etc/nginx/sites-enabled/load_balancer
    
  5. You may want to disable all other sites. Simply remove the respective links under sites-enabled.
  6. Check the configuration for syntax errors:
    $ sudo nginx -t
    
  7. Now, reload Nginx for the changes to take effect:
    $ sudo service nginx reload
    
  8. Yes, you are ready to use a load balancer. Open your favorite browser and point it to the IP of your Nginx server. You should see the contents of example.com or whatever domain you have used.

How it works…

We have created a very basic configuration for a load balancer. With this configuration, Nginx takes the traffic on port 80 and distributes it between srv1.example.com and srv2.example.com. With an upstream directive, we have defined a pool of servers that will actually process the requests. The upstream directive must be defined in a HTTP context. Once the upstream directive is defined, it will be available for all site configurations.

Note

All configuration files defined under sites-available are combined in the main configuration file, /etc/nginx/nginx.conf, under the HTTP directive. This enables us to set other directives in site-specific configurations without specifying the HTTP block.

When defining servers under an upstream directive, you can also use the IP address and port of the application server. This is an ideal configuration, especially when both the load balancer and the application servers are on the same private network, and this will help minimize the communication overhead between Nginx and backend servers.

Next, under the server block, we have configured Nginx to proxy_pass all requests to our backend pool.

While setting backend servers, we have not explicitly specified any load balancing algorithm. Nginx provides various load balancing algorithms that define the server that will receive a particular request. By default, Nginx uses a round-robin algorithm and passes requests to each available server in sequential order. Other available options are as follows:

  • least_connection: This passes the request to the host with the fewest active connections.
  • least_time: Nginx chooses the host with the lowest latency. This option is available with Nginx plus.
  • ip_hash: A hash of clients' IP addresses, and is used to determined the host to send the request to. This method guarantees that requests with the same IP address are served by the same host, unless the selected host is down.

Hash uses a user defined key to generate a hash value and then uses the hash to determine the processing host.

There's more…

Nginx provides various other load balancing features, such as weighted load balancing, active and passive health checks, backup servers, and session persistence. With the latest commits to the open source version, it now supports TCP load balancing as well. These settings can be updated at runtime with the help of HTTP APIs. The following are a few examples of different load balancing configurations:

  • Set server weights:
    upstream app-servers {
     server srv1.example.com weight 3;
     server srv2.example.com;
    }
    
  • Health checkups and backup servers:
    upstream app-servers {
     server srv1.example.com max_fails 3 fail_timeout 10;
     server srv2.example.com fail_timeout 50;
     192.168.1.12:8080 backup;
    }
    
  • Session persistence with cookies:
    upstream app-servers {
     server srv1.example.com;
     server srv2.example.com;
     sticky cookie srv_id expires=1h domain=.example.com path=/;
    }
    

Check the Nginx load balancing guide for various other load balancing options and their respective details.

See also