Basic Web Load Balancing in Under 10 Minutes

If you’ve got a limited budget and need a reverse proxy for a web farm, nginx is most likely going to fit the bill. Nginx gives you the ability to do SSL offloading, simple caching (if you want to get a little deeper you can get into advanced caching with Memcached, Varnish, Redis, and the likes), rewrites/redirects/force ssl, customized error pages, and when teamed up with another simple set of services like keepalived and monit you can even get some pretty high performance, high availability load balancing. In this guide I’m only going to cover the basics of setting up a simple, single host, nginx proxy using proxy_pass. I’m an Ubuntu 12.10 LTS (correction: 12.04 is LTS but I use 12.10, thanks @paulgear1) user at the moment, so for anything OS specific (installation and config file location) keep that in mind.

First, start off by installing nginx.

apt-get install nginx

If you’re only going to be using this system as a proxy, there isn’t really anything that needs to be added to the main config file. To keep things clean though, create a directory to hold the proxy site config files.

mkdir /etc/nginx/proxy

Now add a line to /etc/nginx/nginx.conf under the http directive so that on reloads nginx will ingest the config files from your new folder.

include /etc/nginx/proxy/*.conf;

Before we can do anything on the virtual host side, you need to define your upstream servers. These are your backend hosts, where your sites live, that the http/s requests will be forwarded on to from the new proxy. Lets define them in the conf file /etc/nginx/proxy/upstream.conf and add a few options.

upstream backend-techvangelist {
  server www1.https://www.techvangelist.net;
  server www2.https://www.techvangelist.net:9090 weight=3;
  server www3.https://www.techvangelist.net weight=6;
  server www4.https://www.techvangelist.net down;
}

Reviewing the config above you can see that on the backend I have 4 web servers hosting whatever site I will be proxying, www1, www2, www3, and www4. Now that I have defined backend-techvangelist I can reference that in later configs when using proxy_pass. The rest of the config shows a few more things that you may or may not need. The server www4 is down for an extended period and marked as such. We mark it down because nginx will continue polling the server and trying to send requests to it unsuccessfully, not great for your clients or your logs. The weight parameter is just that, the weight of the server in a weighted round robin load balance (default is 1). The config above means that www3 will get 6 requests out of every 10, www2 will get 3 of the remainder, and www1 will only get 1. This is useful if you have varying performace profiles of your backend hardware. The last piece in there is that www2 is listening on port 9090. There are a few other parameter and directives that can be used, but for time and simplicity sake I’m going to cover them in a later post.

Now let’s create the first site to be proxied. Open a new file in the /etc/nginx/proxy folder for editing using vim, or any other editor if you’re uncomfortable with that kind of power. You should name the conf file after the site for easy accounting/auditing and so the person who inherits the server doesn’t hate you.

vim /etc/nginx/proxy/https://www.techvangelist.net.conf

First thing needed is the server directive to define the settings for your site. The rest of the config will fall in underneath that.

server {
  listen 80; # Server will listen on all IPs on port 80, can also specify IP:Port or *:Port
  server_name https://www.techvangelist.net; # Obvious line is obvious
  access_log /var/log/nginx/proxy/techvangelist_access.log; # Per site proxy access logs
  error_log  /var/log/nginx/proxy/techvangelist_error.log;  # Per site proxy error logs

  location / { # This defines the site root
    proxy_pass http://backend-techvangelist;
    proxy_set_header Host $http_host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-NginX-Proxy true;
}

What you’ve done in this piece of the config is define that anything coming into the proxy server requesting the site http://https://www.techvangelist.net, port 80 on any IP address, will be forwarded to the upstream cluster defined as backend-techvangelist. The http request headers will be altered to add the X-Real-IP field and assign the requesting client’s IP address, the X-Forwarded-For and X-NginX-Proxy fields are also added to the headers. The reason to add these header altering/adding directives is so that the backend server log the requests as coming from the client, not the proxy. If you don’t have it that way, good luck on getting any sort of analytics out of your web sites.

That’s really it. Give it a config test by issue the command.

/etc/init.d/nginx configtest

If everything worked out, start it up or reload the config.

/etc/init.d/nginx {start|reload}

Leave a Reply

Your email address will not be published. Required fields are marked *