Ostatnio pisałem o haproxy jako balanserze dla ruchu HTTP, dziś chciałbym uzupełnić poprzedni opis o coś co nazywane jest popularnie content switchingiem... czyli kierowanie ruchu HTTP na podstawie żądanego contentu/typu danych. Dla prostszego wyobrażenia sytuacji przygotowałem taki obrazek:
mamy jeden serwis w jednej domenie http://yoursite.pl/ i posiadamy tylko jeden adres IP, ale chcemy podawać content w zależności od żądanego pliku z różnych serwerów, apache sprawdzi się przy (.php .html), lighttpd lekki, szybki, zwinny, etc. doskonale poradzi sobie z obrazkami (.gif .jpg), a nginx'a chcemy użyć bo też jest modny, do podawania (.js .css), bez balancera w postaci haproxy który pracuje w 7 warstwie i potrafi analizować i wykonywać przeróżne akcje niczym ninja z filmów z dzieciństwa na nagłówkach HTTP byłoby to trochę bardziej skomplikowane. Zakładam, że mamy działające haproxy i pozostałe serwery httpd, jeśli tak to można troszkę pobawić się konfiguracją.
Zacznę od wyjaśnienia kilku pojęć:
- frontend - zgodnie z dokumentacją, frontendem jest nasza usługa która przyjmuje połączenia od użytkowników i je proxy'uje dalej do backendów.
- backend - to definicja serwerów które odbierają ruch od balancer'a i zwracają wyniki, w naszym przypadku backendami są serwery Apache, Lighttpd, Nginx.
- acl - Access List, dzięki acl'kom możemy zmatchować dany request np. na podstawie src, dst, path_reg, path_end
Nasza konfiguracja haproxy będzie wyglądać następująco:
root@xen7:~# cat /etc/haproxy.cfg
global
log 127.0.0.1 local0
log 127.0.0.1 local1 notice
maxconn 4096
user haproxy
group haproxydefaults
log global
mode http
option httplog
option dontlognull
retries 3
maxconn 2000
contimeout 5000
clitimeout 50000
srvtimeout 50000
option httpclosefrontend frontend_xen
bind 192.168.1.220:80
option forwardforacl acl_apache path_end .php .html
acl acl_lighttpd path_end .gif .jpg
acl acl_nginx path_end .css .jsuse_backend backend_xen2 if acl_apache
use_backend backend_xen3 if acl_lighttpd
use_backend backend_xen4 if acl_nginx
default_backend backend_xen2backend backend_xen2
mode http
balance roundrobin
server xen2 192.168.1.241:80 checkbackend backend_xen3
mode http
balance roundrobin
server xen3 192.168.1.242:80 checkbackend backend_xen4
mode http
balance roundrobin
server xen4 192.168.1.125:80 check
Po starcie daemona przeprowadzamy mały test:
$ lwp-request -Sde http://xen7/test.php | grep Server
Server: Apache/2.2.8 (Ubuntu)$ lwp-request -Sde http://xen7/test.css | grep Server
Server: nginx/0.5.33$ lwp-request -Sde http://xen7/test.jpg | grep Server
Server: lighttpd/1.4.19
Kluczową rolę odegrały definicje frontendu oraz backendów, ale bez ACL nie moglibyśmy powiedzieć balancer'owi jaki ruch gdzie kierować. Definiujemy więc 3 ACLe (acl_apache, acl_lighttpd, acl_nginx) gdzie warunkiem jest rozszerzenie:
acl acl_apache path_end .php .html
acl acl_lighttpd path_end .gif .jpg
acl acl_nginx path_end .css .js
składnia:
acl nazwa_acla sposób_matchowania warunek
Kolejny bardzo ważny element konfiguracji to wskazanie balancerowi gdzie ma kierować ruch po dopasowaniu do konkretnej acl'ki:
use_backend backend_xen2 if acl_apache
use_backend backend_xen3 if acl_lighttpd
use_backend backend_xen4 if acl_nginx
default_backend backend_xen2
Jeśli request pasuje do ACL acl_apache to kieruj do backend_xen2, jeśli pasuje do acl_lighttpd to kieruj do backend_xen3, itd... jeśli nie dopasuje do żadnej acl kieruje do default'owego backendu backend_xen2.
Bardzo proste do wdrożenia i daje nam ogromne możliwości zarządzania streamem HTTP, operowanie na rozszerzeniach to ułamek możliwości tego load balancer'a, będę starał się co jakiś czas, opisywać inne/pozostałe ciekawe przykłady wykorzystania haproxy.
A jakie Wy widzicie zastosowanie dla tego mechanizmu?