Using HAProxy as a reverse proxy » History » Revision 6
Revision 5 (Christian Meyer, 10/06/2015 04:50 PM) → Revision 6/8 (Checheta Yan, 01/08/2016 04:08 PM)
h1. Using HAproxy as a reverse proxy
"HAproxy":http://haproxy.1wt.eu/ has a great feature set when used in conjunction with Wt:
* Uses async I/O and thus handles thousands of connections without any problem. Just like Wt!
* Supports reverse proxying of WebSocket connections (as per draft-76).
* Can be configured to use session affinity without needing cookies.
You need a fairly recent of haproxy for the options 'http-server-close' and 'http-pretend-keepalive' to work, which is needed for reliable load-balancing.
h2. Basic setup
<pre>
global
log 127.0.0.1 local0
log 127.0.0.1 local1 notice
maxconn 4096
user haproxy
group haproxy
daemon
defaults
log global
mode http
option httplog
option dontlognull
option http-server-close
option http-pretend-keepalive
option forwardfor
option originalto
retries 3
option redispatch
maxconn 2000
contimeout 5000
clitimeout 50000
srvtimeout 50000
listen 0.0.0.0:8181
server srv1 0.0.0.0:9090 check
</pre>
h2. Using session affinity
All of the built-in mechanisms in HAproxy for session affinity using the @appsession@ option rely on cookies, but cookies are not our preferred method since this does not give an intuitive user experience (e.g. a user cannot open multiple sessions), are not entirely reliable (a user can disable cookies) and a source of security risks (CSRF).
Luckily there is a work-around: using Wt's ability to generate session-id's that have a prefix which identifies the back-end, we can have HAproxy match on this prefix in the request URL and send the requests to the correct server.
Below is an example configuration for two back-end servers. <a href="http://svtros.ru">!!!</a>
<pre>
global
log 127.0.0.1 local0
log 127.0.0.1 local1 notice
maxconn 4096
user haproxy
group haproxy
daemon
defaults
log global
mode http
option httplog
option dontlognull
option http-server-close
option http-pretend-keepalive
option forwardfor
option originalto
retries 3
option redispatch
maxconn 2000
contimeout 5000
clitimeout 50000
srvtimeout 50000
frontend wt
bind 0.0.0.0:80
acl srv1 url_sub wtd=wt1
acl srv2 url_sub wtd=wt2
acl srv1_up nbsrv(bck1) gt 0
acl srv2_up nbsrv(bck2) gt 0
use_backend bck1 if srv1_up srv1
use_backend bck2 if srv2_up srv2
default_backend bck_lb
backend bck_lb
balance roundrobin
server srv1 0.0.0.0:9090 track bck1/srv1
server srv2 0.0.0.0:9091 track bck2/srv2
backend bck1
balance roundrobin
server srv1 0.0.0.0:9090 check
backend bck2
balance roundrobin
server srv2 0.0.0.0:9091 check
</pre>
And start the two Wt httpd servers using:
<pre>
$ app.wt --session-id-prefix=wt1 --http-port 9090 ...
$ app.wt --session-id-prefix=wt2 --http-port 9091 ...
</pre>
h2. Running multiple apps for multiple domains
In case you want different apps to be bound to different domains then I have the following configuration for you.
In my case it's a virtual Server for testing and development as well. With Apache to test wordpress and other things.
To not immediately show changes on the Main Page I have a second instance running, but see for yourself:
I hope the comments are self explanatory even for beginners like I have been =)
<pre>
global
maxconn 4096
user haproxy
group haproxy
daemon
defaults
log global
mode http
option httplog
option dontlognull
option http-pretend-keepalive
option forwardfor
option originalto
option redispatch
retries 3
timeout connect 5000
timeout client 50000
timeout server 50000
frontend http-in
bind *:80
# Having a .wt Application-Server for development/testing purposes with access regardless of path
# but subdomain is dev: dev.sample.com / dev.example.com
# While having several domains pointing to the same physical server
acl is_dev_URL hdr_beg(host) -i dev.
# Main-Page to load when connecting to host: should load sample.com/wt1
acl is_wt_Main hdr_end(host) sample.com
# Secondary Page shown when connecting from 2nd URL: example.com/wt2
acl is_wt_Second hdr_end(host) example.com
# Having apache for other reasons, too: testing wordpress / something
# refers to specific path: html
acl apache_path path_beg /html
# Following a folder architecture within docroot like:
# docroot/wt1/[styles][images][whatever]
# docroot/wtSecondary/[styles][images]
# ->Just giving an example of having another folder name than deployment path
acl wt_path path_beg /wt1
acl wt_path path_beg /wt2
acl wt_resource path_beg /resources
acl wt_resource path_beg /wt1
acl wt_resource path_beg /wtSecondary
# Checking whether Servers are up or down
acl wt_srv_up nbsrv(wt_hp) gt 0
acl wt_dev_up nbsrv(wt_dev) gt 0
# The Redirections:
# Redirect to Location /wt1 if Main-Page, no other app, Server is up, no apache path, no resource path, and no dev-server
redirect location /wt1 if is_wt_Main !wt_path wt_srv_up !apache_path !wt_resource !is_dev_URL
# Redirect Secondary
redirect location /wt2 if is_wt_Second !wt_path wt_srv_up !apache_path !wt_resource !is_dev_URL
# Choose the Backend
use_backend apache if apache_path !wt_srv_up
# HAProxy 1.5.x + :
default_backend wt
# HAProxy 1.4.x - :
# use_backend wt_live if is_wt_Main is_wt_Second wt_path !is_dev_URL wt_srv_up
# use_backend wt_dev if is_dev_URL wt_dev_up
# The Backends
backend wt
# use-server is only available in HAProxy 1.5.x
use-server Wt_Live unless is_dev_URL
server Wt_Live 0.0.0.0:9050 track wt_hp/Wt_Live
use-server Wt_Dev if is_dev_URL
server Wt_Dev 0.0.0.0:9020 track wt_dev/Wt_Dev
backend wt_hp
balance roundrobin
server Wt_Live 0.0.0.0:9050 check
backend apache
balance roundrobin
timeout connect 10s
timeout server 30s
server apache1 0.0.0.0:8050 check
backend wt_dev
balance roundrobin
server Wt_Dev 0.0.0.0:9020 check
</pre>
This is also updated to exclude deprecated keywords