How to load balance an HTTP server (using with HAProxy or Pound)

HAProxy

HAProxy/haproxy@man is a TCP/HTTP reverse proxy which is particularly suited for high availability environments.

## install
$ sudo apt-get install haproxy | sudo yum install haproxy

## configure
$ vi /etc/haproxy/haproxy.cfg
global
  daemon                             # fork into background
  maxconn 256                        # max per-process concurrent connections
defaults    
  mode http                          # 'tcp' for layer4 ssl,ssh,smtp; 'http' for layer7
  timeout connect 5s
  timeout client 50s
  timeout server 50s
frontend http-in
   bind *:80                         # frontend bindto 'ip:port' listener
   reqadd X-Forwarded-Proto: http    # add http header to request
   default_backend servers           # backend used when no "use_backend" has been matched
backend servers
   stats enable
   stats hide-version
   stats uri /stats
   stats realm Haproxy Statistics
   stats auth haproxy:redhat         # credentials for HAProxy Statistic report page
   balance roundrobin                # roundrobin according to their using weights
   cookie LB insert
   server web1-srv 192.168.0.121:80 cookie web1-srv check
   server web2-srv 192.168.0.121:80 cookie web2-srv check
   server web3-srv 192.168.0.123:80 cookie web3-srv check
   server web4-srv 192.168.0.124:80 check backup
   server server1 127.0.0.1:8000 maxconn 32 

from haproxy@tecmint, haproxy@xmodulo, haproxy@digitalocean and haproxy@doc

  • Load balancing algorithms used to select a backend: roundrobin according to their weights, static-rr same as roundrobin but changing server’s weight on the fly has no effect, lastconn lowest number of connections is selected, first available with connection slots is selected, source hashs source ip hash ensuring same client ip reaches same server, uri hashs part or whole uri to select server, url_param hashs url get or post parameter value to select server, hrd() hashs http header value.
balance roundrobin
balance url_param userid
balance url_param session_id check_post 64
balance hdr(User-Agent)
balance hdr(host)
balance hdr(Host) use_domain_only
  • Using ACLs to select backends: default_backend specify the backend to use when no use_backend rule has been matched, use_backend switch to a specific backend if/unless an ACL-based condition is matched
# use_backend <backend> [{if | unless} <condition>]

# by url
acl url_blog path_beg /blog
use_backend blog-backend if url_blog
default_backend web-backend
  • Server options/params: backup only use this server if all other non-backups are unavailable, cookie cookie value assigned to server used for persistency/affinity, check server availability by making periodic tcp connections, inter interval in ms between checks, maxconn if number of incoming concurrent requests goes higher than this value they will be queued, maxqueue * maximal number of connections which will wait in server queue, *ssl enables SSL ciphering on outgoing connections, *weight * server’s weight relative to other servers
# server <name> <address>[:[port]] [param*]
server first  10.1.1.1:1080 cookie first  check inter 1000
server second 10.1.1.2:1080 cookie second check inter 1000
server transp ipv4@
server backup ${SRV_BACKUP}:1080 backup
server www1_dc1 ${LAN_DC1}.101:80
server www1_dc2 ${LAN_DC2}.101:80
  • Cookie-based backend persistence/affinity: rewrite cookie is provided by server and haproxy should modify it, insert cookie is provided/inserted by haproxy, prefix use an exiting cookie, indirect no cookie will be emitted to a client which already has a valid one for the server which has processed the request, preserve emit a persistent cookie
#cookie <name> [options*]
cookie JSESSIONID prefix
cookie SRV insert indirect nocache
cookie SRV insert postonly indirect
cookie SRV insert indirect nocache maxidle 30m maxlife 8h
  • Stats: stats admin enables the statistics admin level if/unless a condition is matched, stats auth enables statistics with default settings, and restricts access to declared users only
## stats admin { if | unless } <cond>
# enable stats only for localhost
backend stats_localhost
  stats enable
  stats admin if LOCALHOST
# statistics admin level always enabled because of the authentication
backend stats_auth
  stats enable
  stats auth  admin:AdMiN123
  stats admin if TRUE

## stats auth <user>:<passwd>
# public access (limited to this backend only)
backend public_www
  server srv1 192.168.0.1:80
  stats enable
  stats hide-version
  stats scope   .
  stats uri     /admin?stats
  stats realm   Haproxy Statistics
  stats auth    admin1:AdMiN123
  stats auth    admin2:AdMiN321
# internal monitoring access (unlimited)
backend private_monitoring
  stats enable
  stats uri     /admin?stats
  stats refresh 5s
  • Logs: log adds a global syslog server, facility syslog facilities
global
  # log <address> [len <length>] <facility> [max level [min level]]
  log 127.0.0.1 local2

# enable udp syslog receiver and facility
$ cat /etc/rsyslog.d/haproxy.conf
local2.*    /var/log/haproxy.log
$ vi /etc/rsyslog.conf
$ModLoad imudp
$UDPServerRun 514
$ service rsyslog restart 
  • SSL: terminating/decrypting an SSL connection at the load balancer and sending unencrypted connections to the backend servers, pass-through sends SSL connections directly to the proxied servers is more secure but losses ability to get X-Forwarded- headers
$ sudo yum install openssl | sudo apt-get install openssl
# generate self-signed certificate for ssl termination only
$ openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/server.key -out /etc/ssl/server.crt
$ cat server.crt server.key > server.pem

## ssl termination
defaults
  mode http
frontend localhost
  bind *:80
  bind *:443 ssl crt server.pem
  redirect scheme https if !{ ssl_fc }   # ssl-only: redirect from http to https
  default_backend nodes

## ssl pass-through
defaults
  option tcplog
  mode tcp          # need to be tcp since haproxy treats connections just as a stream
frontend localhost
  bind *:80
  bind *:443
  default_backend nodes

from haproxy with ssl

Pound

pound/pound@man is a lightweight open source reverse proxy, load balancer and SSL wrapper used as a web server load balancing solution:

  • Listeners: how (ip+port) to receive requests from the clients, HTTP and/or HTTPS
  • Services: matching requests (by URL pattern, HTTP header and/or session) with list of back ends. Session can be matched by ip address, basic authentication, url parameter, cookie value or http header
  • Backend: list of (ip+port) web servers, optionally with priority
## install
$ sudo yum install pound (EPEL) | sudo apt-get install pound | cd /usr/ports/www/pound/ && make install clean

## configure
$ vi /etc/pound/pound.cfg | vi /etc/pound.cfg
# global options
User        "www-data"
Group       "www-data"
# logging (goes to syslog by default)
LogLevel    1
# check backend every X secs:
Alive       30

# main listening ports
ListenHTTP
  Address 202.54.1.5
  Port    80
End
ListenHTTPS
  Address 202.54.1.5
  Port    443
  Cert    "/etc/ssl/local.server.pem"
End

# image/static server
Service
  URL ".*.(jpg|gif)"
  BackEnd
    Address 192.168.1.10
    Port    80
  End
End

# virtual host www.mydomain.com (url-based session)
Service
  URL         ".*sessid=.*"
  HeadRequire "Host:.*www.mydomain.com.*"
  BackEnd
    Address 192.168.1.11
    Port    80
  End
  Session
    Type    PARM
    ID      "sessid"
    TTL     120
  End
End

# everything else (cookie-based session)
Service
  BackEnd
    Address 192.168.1.5
    Port    80
    Priority 5
  End
  BackEnd
    Address 192.168.1.6
    Port    80
    Priority 4
  End
  Session
    Type    COOKIE
    ID      "userid"
    TTL     180
  End
End

# restart
$ /etc/init.d/pound restart

from pound@cyberciti

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s