HAProxy (High Availability Proxy)

HAProxy(High Availability Proxy) is an open source load balancer which can load balance any TCP service. It is particularly suited for HTTP load balancing as it supports session persistence and layer 7 processing.





HA Proxy Setup  :

I was working with Apache Webserver from very long but when I jumped into the world of NodeJS I started loving websockets. Soon I was planning to integrate my PHP applications with NodeJS. I was happy to use both, till I was not running both the applications on default web service port 80. But when I tried to configure Apache virtual hosting for proxying my request to NodeJS server port, it was not allowing my websocket communication to happen. I tried alot of modules but didn’t got success. And after alot of googling I found something which helped me to achieve what I need. Once I configured HAProxy on my system I was able to serve both applications, PHP and NodeJS through port 80 just by virtual hosting of HAProxy.


Setup

We are having a single linux machine with Public IP (Real IP). I am using Ubuntu 14.04
The public IP of the machine be 31.13.79.144

Requirements

We have to serve Multiple domains hosted on a single linux server. All domains have to be served using port 80 only. Each of them is running different webserver software, therefore Apache Virtual Hosting is useless in this case.
  1. www.example.com : Running on Apache Webserver
  2. admin.example.com : Running on Apache Webserver
  3. static.example.com : Running on NGINX Webserver
  4. api.example.com : Running on NodeJS

Procedure

1. Change Settings for Apache Webserver and setup for listening it to port higher than 5000 on local address 127.0.0.1

Tested on Apache/2.4.7 (Ubuntu 14.04)
Open your site configuration, by default it is located at
/etc/apache2/sites-available/000-default.conf
You will see something like this
**If you are using name based virtual hosting for apache, turn off name based virtual hosting and assign different for serving multiple virtual hosts
<VirtualHost *:80>
Servername www.example.com
DocumentRoot /var/www/html

<Directory /var/www/html>
AllowOverride All
Allow from all
Order Allow,Deny
Require all granted
</Directory>
</VirtualHost>
<VirtualHost *:80>
Servername admin.example.com
DocumentRoot /var/www/admin
<Directory /var/www/admin>
AllowOverride All
Allow from all
Order Allow,Deny
Require all granted
</Directory>
</VirtualHost>
Change the ports and turn off name based virtual hosting like this. Use different ports for each domain.
We are using port 8000 and 80001 for www.example.com and admin.example.com respectively.
<VirtualHost 127.0.0.1:8000>
DocumentRoot /var/www/html
<Directory /var/www/html>
AllowOverride All
Allow from all
Order Allow,Deny
Require all granted
</Directory>
</VirtualHost>

<VirtualHost 127.0.0.1:8001>
DocumentRoot /var/www/admin
<Directory /var/www/html>
AllowOverride All
Allow from all
Order Allow,Deny
Require all granted
</Directory>
</VirtualHost>
Restart Apache Webserver

$ sudo service apache2 restart


2. Change settings for Nginx server

Tested on nginx/1.4.6 (Ubuntu 14.04)
Open your site configuration, by default it is located at
/etc/nginx/sites-available/default.conf
You will see something like this
server {
listen 80 default_server;
listen [::]:80 default_server ipv6only=on;

root /usr/share/nginx/html;
index index.html index.htm;

# Make site accessible from http://localhost/
server_name localhost;

location / {
       # First attempt to serve request as file, then
       # as directory, then fall back to displaying a 404.
       try_files $uri $uri/ =404;
       # Uncomment to enable naxsi on this location
       # include /etc/nginx/naxsi.rules
}

}
Change the default port to other port and turn off name based virtual hosting like this. We will use port 8002 for nginx. Comment out the line containing ipv6only=on
server {
listen 127.0.0.1:8002 default_server;
#listen [::]:80 default_server ipv6only=on;

root /usr/share/nginx/html;
index index.html index.htm;

# Make site accessible from http://localhost/
#server_name localhost;

location / {
       # First attempt to serve request as file, then
       # as directory, then fall back to displaying a 404.
       try_files $uri $uri/ =404;
       # Uncomment to enable naxsi on this location
       # include /etc/nginx/naxsi.rules
}

}
Restart Nginx Webserver

sudo service nginx restart
Now at this stage you are having three virtualhosts running as follows
  1. 127.0.0.1:8000
  2. 127.0.0.1:8001
  3. 127.0.0.1:8002

3. Setup NodeJS server to listen on address 127.0.0.1 and port 8003

Let us take an example NodeJS http server which listens to port 3000 by default
var http = require('http');
http.createServer(function (req, res) {
   res.writeHead(200, {'Content-Type': 'text/plain'});
   res.end('Hello World\n');
}).listen(3000);
Change it something like this
var http = require('http');
http.createServer(function (req, res) {
   res.writeHead(200, {'Content-Type': 'text/plain'});
   res.end('Hello World\n');
}).listen(8003,'127.0.0.1');

4. Install HAProxy

Add vbernat repository for haproxy and install haproxy using command line

sudo add-apt-repository ppa:vbernat/haproxy-1.5
sudo apt-get update
 sudo apt-get install haproxy

5. Configure HAProxy for serving all the using name based virtual hosting

Your default HAProxy configuration resides in
/etc/haproxy/haproxy.cfg
You will something like this
global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
user haproxy
group haproxy
daemon
defaults
log global
mode http
option httplog
option dontlognull
contimeout 5000
clitimeout 50000
srvtimeout 50000
errorfile 400 /etc/haproxy/errors/400.http
errorfile 403 /etc/haproxy/errors/403.http
errorfile 408 /etc/haproxy/errors/408.http
errorfile 500 /etc/haproxy/errors/500.http
errorfile 502 /etc/haproxy/errors/502.http
errorfile 503 /etc/haproxy/errors/503.http
errorfile 504 /etc/haproxy/errors/504.http
Change it to something like this
log global
mode http
option httplog
option dontlognull
contimeout 5000
clitimeout 50000
srvtimeout 50000
errorfile 400 /etc/haproxy/errors/400.http
errorfile 403 /etc/haproxy/errors/403.http
errorfile 408 /etc/haproxy/errors/408.http
errorfile 500 /etc/haproxy/errors/500.http
errorfile 502 /etc/haproxy/errors/502.http
errorfile 503 /etc/haproxy/errors/503.http
errorfile 504 /etc/haproxy/errors/504.http

frontend public

bind 31.13.79.144:80

#Define hosts
acl www_host hdr(host) -i www.example.com
acl admin_host hdr(host) -i admin.example.com
acl static_host hdr(host) -i static.example.com
acl api_host hdr(host) -i api.example.com

#which one to use
use_backend www if www_host
use_backend admin if admin_host
use_backend static if static_host
use_backend api if api_host

#default backend serving whole domain
default_backend www

backend www
timeout server 30s
server apache 127.0.0.1:8000

backend admin
timeout server 600s
server node 127.0.0.1:8001

backend static
timeout server 30s
server node1 127.0.0.1:8082

backend api
timeout server 30s
server nginx1 127.0.0.1:8083

6. Start HAProxy and test your setup

Now name based virtual hosting like Apache has been setup for all your domains serving from a single machine
service haproxy start

No comments:

Post a Comment