Blog JSystems - uwalniamy wiedzę!

Szukaj


Z tego artykułu dowiesz się:

  • czym jest load balancing i w jakim celu się go stosuje,
  • czym jest HAProxy i w jakim celu się go stosuje,
  • jak działa load balancing z użyciem HAProxy,
  • jak skonfigurować HAProxy do współpracy z wieloma serwerami – w tym z klastrem Patroni,
  • jak testować działanie HAProxy,
  • jak podłączyć pgBouncer do HAProxy,
  • jak zrealizować load balancing i HA z pomocą HAProxy i pgBouncera.




HAProxy to popularne bezpłatne oprogramowanie z otwartym źródłem umożliwiające load balancing, czyli automagiczne dystrybuowanie zapytań w grupie serwerów, przez co obniżamy obciążenie na pojedynczych serwerach, a często też przyspieszamy obsługę zapytań. Dzięki możliwości monitorowania dostępności oraz roli serwerów PostgreSQL, pozwala automatycznie rozdystrybuować połączenia wykonujące sam odczyt na wiele replik. Potrafi także sprawdzać ich status i natychmiast reagować na sytuacje, kiedy serwer lidera był awaryjnie przełączony, natychmiast przekierowując cały ruch na nowy serwer primary.


HAProxy również bardzo dobrze współpracuje z Patroni, między innymi pozwala na wykluczenie repliki z load balancingu poprzez ustawienie jej tagu "noloadbalance" w konfiguracji patroni oraz automatyczne śledzenie lidera po "failoverze/switchoverze".


W połączeniu z pgBouncerem i Patroni możemy stworzyć wysoce dostępny klaster, który bez problemu spełnia wymagania czterech czwórek w dostępności (SLA czyli dostepnosc serwera przez 99,99% czasu czyli 52 minuty w roku może nie banglać), a możemy osiągnąć ich jeszcze kilka. Po automatycznym failoverze haproxy w sam poszuka , na którym serwerze jest nowy lider Patroni, a dzięki połączeniu z pgbouncerem połączone aplikacje nie stracą połączenia i będą kontynuowały pracę na nowej instancji primary. Jedyne utracone transakcje to te, które były zacommitowane podczas failovera.


Znając możliwości API Patroni, skonfigurujemy HAProxy dla serwera mastera oraz zmienimy konfigurację pgBouncera, aby łączył się do patroni przez haproxy.

Najpierw kopiujemy plik konfiguracyjny z domyślną konfiguracją, a następnie tworzymy nowy plik configa haproxy. Dzięki temu nie musimy wykomentowywać wielu linii.


# serwer pgbouncer
sudo mv /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg_old
sudo vi /etc/haproxy/haproxy.cfg

global
maxconn 300

defaults
log global
mode tcp
retries 2
timeout client 30m
timeout connect 4s
timeout server 30m
timeout check 5s

listen stats
mode http
bind *:7000
stats enable
stats uri /

listen primary
bind *:5000
option httpchk OPTIONS /master
http-check expect status 200
default-server inter 1s fall 3 rise 2 on-marked-down shutdown-sessions
server pg1 pg1:5432 maxconn 100 check port 8008
server pg2 pg2:5432 maxconn 100 check port 8008
server pg3 pg3:5432 maxconn 100 check port 8008

listen replica
bind *:5001
option httpchk OPTIONS /replica
http-check expect status 200
balance roundrobin
default-server inter 1s fall 3 rise 2 on-marked-down shutdown-sessions
server pg1 pg1:5432 maxconn 100 check port 8008
server pg2 pg2:5432 maxconn 100 check port 8008
server pg3 pg3:5432 maxconn 100 check port 8008


Sekcja GLOBAL parametry ustawiane na poziomie całego HAProxy oddziałujące na całość procesu, wszystkie listenery, itp.


  • maxconn - globalny limit połączeń do haproxy, do wszystkich frontendów, backendów i listenerów (połączenie frontend + backend)

Sekcja DEFAULTS zawiera domyślne ustawienia dla wszystkich zdefiniowanych backendów, frontendów czy listenerów.



  • mode tcp - tryb pracy http lub tcp, w naszym przypadku wszystkie listenery dla pgbouncera będą korzystały z trybu tcp, dlatego warto go dodać tutaj, żeby później się nie powtarzać

  • retries 2 - liczba powtórnych prób połączenia po błędzie

  • timeout client 30m - maksymalny czas bezczynności dla klienta przed automatycznym rozłączeniem, czas w milisekundach, chyba że podamy jednostkę (m - minuty, s - sekundy)

  • timeout connect 4s - maksymalny czas na nawiązanie połączenia

  • timeout server - maksymalny czas oczekiwania na odpowiedź serwera, po przekroczeniu połączenie zostanie rozłączone

  • timeout check - timeout dla healthchecka


Sekcje z definicją listenerów LISTEN



  • bind - konfiguracja, na których interfejsach sieciowych i na jakim porcie dany listener ma nasłuchiwać

  • stats enable - włączenie zbierania statystyk

  • stats uri / - konfiguracja adresu, pod jakim dostępne są statystyki

  • option httpchk OPTIONS /master - sprawdzenie odpowiedzi na zapytanie http /master lub /replica na porcie "check port" z definicji serwera, podobnie do "curl -s -o /dev/null -w "%{http_code}" http://pg2:8008/master"

  • http-check expect status 200 - spodziewana odpowiedź z serwera na zapytanie http

  • default-server - domyślne parametry dla serwerów

  • inter 1s - interwał pomiędzy healthcheckiem

  • fall 3 - liczba nieudanych healthchecków, po których serwer zostanie uznany za niedostępny

  • rise 2 - liczba udanych healthchecków, po których serwer zostanie uznany za ponownie dostępny

  • on-marked-down shutdown-sessions - jeżeli serwer zostanie uznany za niedostępny, zamknie wszystkie aktywne sesje

  • server pg1 pg1:5432 maxconn 100 check port 8008 - definicja serwera, wartości kolejno to: nazwa, adres serwera i port, maksymalna liczba połączeń, port dla http checka

  • balance roundrobin - rozłożenie połączeń naprzemiennie pomiędzy dostępnymi serwerami


Konfiguracja zawarta w sekcji "listen primary" oraz "listen replica" sprawia, że haproxy odpytuje serwery pg1, pg2 i pg3 na porcie 8008, na którym nasłuchuje RestAPI Patroni. Wywołując zapytania z odpowiednio /master oraz /replica, sprawdza, który z serwerów odpowiada kodem 200, oznacza to, że serwer ten pełni odpytywaną rolę i haproxy połączy się do nich, kiedy otrzyma połączenie na porcie 5000 dla mastera/primary oraz na porcie 5001 dla replik.


Następnym krokiem będzie restart usługi haproxy oraz test połączenia


sudo systemctl restart haproxy

psql -h pgbouncer -p 5000 -U postgres -c "select pg_is_in_recovery()"
pg_is_in_recovery
-------------------
f
(1 row)

psql -h pgbouncer -p 5001 -U postgres -c "select pg_is_in_recovery()"
pg_is_in_recovery
-------------------
t
(1 row)


Spróbujmy jeszcze wykonać switchover i sprawdźmy, czy haproxy połączy nas do nowej instancji primary.


# Na dowolnym serwerze patroni
patronictl -c /etc/patroni/config.yml switchover szkolenie

# Na serwerze z pgbouncerem i haproxy
psql -h pgbouncer -p 5000 -U postgres -c "select pg_is_in_recovery()"


Teraz możemy zmodyfikować konfigurację pgbouncera, aby ten łączył się z postgresem przez haproxy. Najważniejszą zmianą jest przepisanie sekcji [databases], gdzie ustawiamy dwa aliasy, z których będziemy korzystać, łącząc się do bazy:



  1. master - przekierowujący połączenie z pgbouncera do haproxy na port 5000, który z kolei przekieruje nas na aktualny serwer primary/leadera patroni,

  2. replica - przekierowujący połączenie z pgbouncera na haproxy na port 5001, który dalej połączy nas z jedną z dostępnych replik.


# serwer pgbouncer
sudo vi /etc/pgbouncer/pgbouncer.ini

[databases]
master = host=pgbouncer port=5000 dbname=postgres pool_size=90
replica = host=pgbouncer port=5001 dbname=postgres pool_size=90

[pgbouncer]
logfile = /var/log/postgresql/pgbouncer.log
pidfile = /var/run/postgresql/pgbouncer.pid
unix_socket_dir = /var/run/postgresql

listen_addr = *
listen_port = 6432
pool_mode = transaction
max_client_conn = 10000
max_db_connections = 250
auth_type = md5
auth_file = /etc/pgbouncer/userlist.txt
admin_users = postgres


Sprawdźmy teraz połączenie oraz wykonajmy testowo switchover.


# z serwera z pgbouncerem

psql -h pgbouncer -p 6432 -U postgres master

master=# select pg_is_in_recovery(),now(),inet_server_addr();
pg_is_in_recovery | now | inet_server_addr
-------------------+-------------------------------+------------------
f | 2022-11-29 21:28:40.225751+00 | 192.168.56.12
(1 row)

master=# \watch 1


# na serwerze z patroni

patronictl -c /etc/patroni/config.yml switchover szkolenie

Tue Nov 29 21:29:12 2022 (every 1s)

pg_is_in_recovery | now | inet_server_addr
-------------------+-------------------------------+------------------
f | 2022-11-29 21:29:12.452795+00 | 192.168.56.12
(1 row)

Tue Nov 29 21:29:13 2022 (every 1s)

pg_is_in_recovery | now | inet_server_addr
-------------------+-------------------------------+------------------
f | 2022-11-29 21:29:28.536762+00 | 192.168.56.11


Całkowita przerwa w działaniu aplikacji wyniosła ok 16 sekund. Połączenie pozostało aktywne i mogło kontynuować pracę po wykonaniu failovera. Musiało jedynie poczekać, aż haproxy znajdzie nową instancję primary.

Komentarze (0)

Musisz być zalogowany by móc dodać komentarz. Zaloguj się przez Google

Brak komentarzy...