Load Balancing z NGINX
by admin · Grudzień 3, 2017
Wstęp
Load balancing – czyli równoważenie obciążenia jest powszechnie stosowaną techniką optymalizacji wykorzystania zasobów, maksymalizowania przepustowości, zmniejszania opóźnień i zapewnienia odpornych na awarię konfiguracji. Możliwe jest wykorzystanie nginx jako bardzo wydajnego HTTP Load Balancer’a do dystrybuowania ruchu do kilku serwerów aplikacji w celu poprawienia wydajności, skalowalności i niezawodności aplikacji internetowych.
W poniższym wpisie pokażę jak w łatwy sposób można zbudować Load Balancer HTTP na systemie Linux wykorzystując oprogramowanie NGINX.
Załóżmy że mamy w sieci trzy serwery web, które posiadają kopię tej samej strony WWW. Chcemy dla tych serwerów zastosować równoważenie obciążenia przy pomocy oprogramowania nginx. Najprostszą metodą równoważenia obciążenia w nginx jest round-robin. Round-robin to algorytm karuzelowy, który działa w następujący sposób.
Pierwszy użytkownik, który chce uzyskać dostęp do strony WWW zostaje odesłany do adresu IP serwera pierwszego, drugi użytkownik zostaje odesłany do adresu IP drugiego serwera, trzeci użytkownik zostaje odesłany do adresu IP trzeciego serwera, czwarty użytkownik zostaje odesłany do adresu IP pierwszego serwera itd.
Przykład
Do pokazania przykładu posłużę się topologią zbudowaną w GNS3 przy użyciu maszyn wirtualnych z Ubuntu, które spełniają następujące funkcje:
(WEB01, WEB02, WEB03) – serwery web na których postawiony jest apache, jako serwer www
LoadBalancer, czyli serwer, który będzie realizował równoważenie obciążania przy pomocy oprogramowania nginx
Client – klient, który będzie próbował otwierać stronę WWW.
Skonfigurujmy powyższą topologię w następujący sposób:
WEB01 – ip 192.168.0.101/24
WEB02 – ip 192.168.0.102/24
WEB03 – ip 192.168.0.103/24
CLIENT – ip 192.168.0.230/24
LoadBalancer – ip 192.168.0.100/24
Na serwerach www mamy postawionego apache’a, zmieńmy na nich index.html w następujący sposób:
Na WEB01 (var/www/html/index.html)
<html>
<head>
</head>
<body>
<h1>To jest strona na serwerze WEB01</h1>
</body>
</html>
Na WEB02 (var/www/html/index.html)
<html>
<head>
</head>
<body>
<h1>To jest strona na serwerze WEB02</h1>
</body>
</html>
Na WEB03 (var/www/html/index.html)
<html>
<head>
</head>
<body>
<h1>To jest strona na serwerze WEB02</h1>
</body>
</html>
Sprawdźmy teraz na kliencie jak wygląda strona na każdym z serwerów WEB.
Dla celów przykładu na każdym z serwerów jest inna zawartość strony www, w rzeczywistej instalacji zawartość strony powinna być taka sama. Dzięki czemu każdy użytkownik nie zależnie do którego serwera zostanie odesłany otrzyma ten sam kontent.
Konfiguracja NGINX
Teraz skonfigurujmy serwer LoadBalancer, który ma adres IP 192.168.0.100. Wchodzimy do pliku konfiguracyjnego /etc/nginx/nginx.conf w sekcji http przed # Basic Settings:
http {
upstream myweb {
server 192.168.0.101;
server 192.168.0.102;
server 192.168.0.103;
}
server {
listen 80;
location / {
proxy_pass http://myweb;
}
}
##
# Basic Settings
##
W sekcji upstream podajemy dowolną nazwę, a następnie listę serwerów (w moim przypadku są to adresy IP serwerów WEB01, WEB02 i WEB03.
Zapisujemy zmiany i restartujemy serwer nginx (/etc/init.d/nginx restart). Zostaje jeszcze jedna rzecz do zrobienia, a mianowicie należy usunąć dowiązanie symboliczne wskazującę na stronę domyślną nginx:
rm /etc/nginx/sites-enabled/default
To wszystko. Nasz LoadBalancer dziala.
Weryfikacja
Wróćmy teraz na klienta i otwórzmy przeglądarkę wpisując adres naszego LoadBalancera 192.168.0.100. Wyświetli się strona pierwszego serwera (WEB01):
Odświeżmy stronę i otrzymamy stronę z drugiego serwera (WEB02):
Load Balancer działa prawidłowo. Następne odświeżenie strony wyświetli nam stronę z WEB03, kolejne z WEB01 itd. Możemy to sprawdzić pisząc prosty skrypt Python, który otworzy stronę 100 razy i sprawdzi z którego serwera jest ona wyświetlana a następnie wyświetli ile razy z danego serwera została wyświetlona strona.
Skrypt
Do połączenia się ze stroną wykorzystam bibliotekę requests i funkcję get. Stronę można otworzyć stosując następujące polecenia:
>>>import requests
>>>r=requests.get('http://192.168.0.100')
>>>r.text
u'<html>\n<head>\n</head>\n<body>\n\n<h1>To jest strona na serwerze WEB02</h1>\n\n</body>\n</html>\n\n'
W wyniku otrzymałem zawartość strony, teraz skorzystam z wyrażeń regularnych i modułu re i przeszukam zawartość wyniku po wyrażeniu regularnym ‚WEB\d\d’, które zwróci tekst pasujący do tego wyrażenia, czyli WEBXX, gdzie XX to dowolne cyfry. A następnie to dopasowanie zapisywane będzie do tablicy, przy każdym otworzeniu strony. Potem z tej tablicy będą brane elementy i porównywane z WEB01, WEB02 i WEB03. Jak będzie dopasowanie to będzie się powiększany o 1 licznik dla każdego dopasowania. W konsekwencji dostaniemy 3 wyniki dla każdego web serwera, czyli informację jak często była otwierana dana strona.
Cały skrypt wygląda następująco:
import re, requests
regex = re.compile(r'(WEB\d\d)')
l = []
for i in range(1,101):
r = requests.get("http://192.168.0.100")
l.append(regex.findall(r.text)[0])
a=b=c=0
for i in l:
if i == 'WEB01':
a = a+1
if i == 'WEB02':
b = b+1
if i == 'WEB03':
c = c+1
print ('WEB01: '+str(a))
print ('WEB02: '+str(b))
print ('WEB03: '+str(c))
root@CLIENT:~# python skrypt.py
WEB01: 33
WEB02: 34
WEB03: 33
http {
upstream myweb {
ip_hash;
server 192.168.0.101;
server 192.168.0.102;
server 192.168.0.103;
}
Zrestartujmy nginx i odpalmy jeszcze raz skrypt:
root@CLIENT:~# python skrypt.py
WEB01: 100
WEB02: 0
WEB03: 0
Jak widać, teraz wszystkie żądania z klienta zostały przesłane do jednego serwera.
Teraz możemy zasymulować awarie jednego z serwerów (np. WEB01) w tym celu wyłączamy apache na serwerze 192.168.0.101 i otwieramy stronę 192.168.0.100 kilkukrotnie. Jak widać teraz w odpowiedzi dostajemy tylko strony z serwerów WEB02 i WEB03.
Sprawdźmy teraz jak wygląda komunikacja pomiędzy LoadBalancerem a serwerami. Uruchomimy do tego celu wiresharka na interefejsie prowadzącym do LoadBalancera.
Na powyższym zrzucie ekranu z wiresharka możemy zaobserwować następujące rzeczy:
1. Linijka 15
Klient (192.168.0.230) wydaje zapytanie GET / HTTP/1.1 do serwera 192.168.0.100
2. Linijka 17 i 18
LoadBalancer (192.168.0.100) próbuje się połączyć do pierwszego serwera (192.168.0.101) na porcie 80, w odpowiedzi otrzymuje RST, czyli nie zostało nawiązane połączenie.
3. Linijka 19-27
LoadBalancer próbuje połączyć się do następnego serwera z listy WEB02 (192.168.0.102) połączenie zakończyło się sukcesem i poszło żądanie GET / HTTP/1.1 (linijka 22) a następnie odpowiedź 200 OK (text/html) od serwera 192.168.0.102 do LoadBalancera 192.168.0.100 (linijka 24)
4. Linijka 28
LoadBalancer zwraca stronę otrzymaną w poprzednich linijkach od serwera 192.168.0.102 do klienta. Z punktu widzenia klienta serwerem który zwraca tą stronę jest LoadBalancer, dlatego w przykładzie posłużyłem się inną treścią strony na każdym serwerze, dzięki czemu po otrzymanej zawartości strony widać było z którego serwera jest ona pobierana. Poniżej screen z linijki 28 z wireshark:
Podsumowanie
Podsumowując nginx jest narzędziem, które nie tylko umożliwia działanie jako serwer www, ale również w prosty sposób możemy zrobić z niego loadbalancer dla stron www. Jest to bardzo przydatne i wygodne narzędzie, a co najważniejsze jest darmowe.