icomHOST

Wszystko o domenach i hostingach

Jak działa load balancer na serwerze

Jak działa load balancer na serwerze

Load balancer to element infrastruktury, który rozdziela ruch między wiele serwerów aplikacyjnych lub bazodanowych tak, aby użytkownicy otrzymywali szybkie odpowiedzi, minimalną liczbę błędów i stabilne działanie usług, niezależnie od pojedynczych awarii czy skoków obciążenia. W ekosystemie firm hostingowych i w środowiskach własnych (kolokacja, VPS, bare-metal, chmura publiczna i prywatna) jest to narzędzie pierwszego wyboru, gdy rośnie zapotrzebowanie na skalowalność, trzeba utrzymać wysoka dostępność i zadbać o bezpieczeństwo oraz zgodność z wymaganiami biznesowymi. W praktyce load balancer bywa nazywany wrotami do aplikacji: zarządza połączeniami, podejmuje decyzje o trasowaniu, monitoruje kondycję węzłów, a nierzadko pełni dodatkowe role — od terminacji TLS po filtrowanie ruchu.

Podstawy: co faktycznie robi load balancer

Wyobraź sobie wirtualny adres IP (VIP), pod którym dostępna jest Twoja aplikacja. Load balancer nasłuchuje na tym adresie i nasługuje ruch przychodzący, a następnie kieruje każde nowe połączenie lub żądanie HTTP do jednego z serwerów zaplecza (backendów). W najprostszej konfiguracji jest to zestaw fizycznych lub wirtualnych maszyn z identycznym oprogramowaniem aplikacyjnym. Z perspektywy klienta wszystko dzieje się “pod jedną flagą” — ten sam adres i port, te same certyfikaty TLS, ta sama ścieżka URL — ale w tle pracuje wiele hostów.

Load balancer dba o równomierne rozłożenie ruchu, ale także o jego jakość. Jeżeli jeden z backendów zaczyna odpowiadać wolno albo całkiem przestaje odpowiadać, ruch zostaje skierowany do pozostałych maszyn. Jeżeli część użytkowników korzysta z długotrwałych połączeń (np. WebSocket), load balancer utrzymuje je i pilnuje, aby nie przeciążały jednego konkretnego serwera. Dobrze skonfigurowany LB potrafi też utrzymywać kontekst użytkownika (sesję) w sposób przewidywalny, co ma znaczenie dla koszyka w e-commerce, paneli klienta czy aplikacji korporacyjnych.

W architekturach hostingowych load balancer bywa budowany jako klaster aktywny–aktywny, gdzie kilka instancji LB współdzieli VIP i utrzymuje spójny stan trasowania, lub aktywny–pasywny, w którym drugi egzemplarz czeka w gotowości na przejęcie pracy. W każdym wariancie celem jest minimalizacja pojedynczych punktów awarii: nie tylko aplikacja, ale i sam element równoważący musi być nadmiarowy.

Modele pracy: L4, L7 i tryby przepływu ruchu

Najważniejszym rozróżnieniem jest klasyfikacja load balancerów względem poziomu warstwy modelu OSI, na której podejmują decyzje o trasowaniu. Wariant warstwowy zwany warstwa L4 operuje na poziomie TCP/UDP. Nie zaglądamy tu w nagłówki HTTP czy treść żądań — liczy się adres IP źródłowy i docelowy, porty oraz parametry połączenia. Taki LB jest bardzo szybki, bo działa blisko stosu sieciowego, często z wykorzystaniem akceleracji jądra i technik offloadu.

Drugi popularny wariant, warstwa L7, pracuje na poziomie protokołów aplikacyjnych (HTTP, HTTP/2, HTTP/3, gRPC). Może podejmować decyzje na podstawie ścieżek URL, nagłówków, ciasteczek, a nawet treści żądania. To otwiera drogę do routerskich reguł “content-aware”, A/B testów, przekierowań kontekstowych czy selektywnego cache’owania. L7 potrafi też gładko terminować TLS, wykonywać przepisywanie nagłówków i kompresję odpowiedzi.

W architekturze przepływu mówimy o trybach: NAT (adresy są modyfikowane, backend widzi jako źródło LB), DSR (Direct Server Return — odpowiedź omija load balancer i trafia bezpośrednio do klienta), oraz pełny proxy. Pełny reverse proxy przejmuje całe połączenie od klienta, a następnie niezależnie zestawia nowe połączenie do backendu. W trybie DSR zyskujemy przepustowość odpowiedzi, ale rośnie złożoność routingu i potrzeba spójnego MTU, ARP i polityk sieciowych. W NAT prostota wygrywa, choć kosztem dodatkowego przetwarzania po stronie LB. W świecie HTTP/2 i HTTP/3 dochodzą kwestie multipleksacji strumieni, utrzymywania priorytetów i ograniczania head-of-line blocking; nowoczesne balancery potrafią mapować wiele strumieni jednego połączenia do wielu backendów lub skupiać je na jednym, w zależności od polityki.

Jeśli obsługujemy protokoły czasu rzeczywistego (WebSocket, SSE, RTP), kluczowe stają się parametry keep-alive, limity liczby jednoczesnych połączeń, czasy bezczynności oraz ochrona przed atakami typu slowloris. L4 będzie tu często bardziej wydajny, ale L7 zapewni lepszą kontrolę nad nagłówkami i terminacją TLS.

Algorytmy rozkładu ruchu i utrzymanie sesji

Decyzja “który backend obsłuży następne żądanie?” opiera się na mechanizmach zwanych algorytmy równoważenia. Klasyka to round-robin (kolejno po kolei), weighted round-robin (z wagami), least connections (kto ma najmniej aktywnych połączeń), least response time (kto najszybciej odpowiada), a także hashowanie po IP źródłowym lub po atrybucie aplikacyjnym (np. identyfikator użytkownika, ścieżka). Konsystentne hashowanie bywa nieocenione przy cache’ach i systemach, gdzie chcemy utrzymać “lepkość” danych bez utrzymywania centralnej tablicy sesji.

Utrzymanie sesji (stickiness) można osiągnąć na kilka sposobów: przez ciasteczko LB, hashowanie po IP klienta, nagłówek wybrany przez aplikację lub metadane TLS (np. SNI). W środowiskach wielochmurowych lub mobilnych stickiness po IP bywa zawodna (NAT operatorów zmienia źródłowe IP), dlatego bezpieczniej jest bazować na ciasteczku albo identyfikatorze sesji zakodowanym w JWT. Alternatywą jest całkowicie bezstanowe podejście po stronie aplikacji: stan sesji trafia do zewnętrznego magazynu (Redis, Memcached, baza dokumentowa), a każdy backend może obsłużyć dowolny request. Taka architektura upraszcza operacje i redukuje ryzyko “przypięcia” użytkownika do węzła, który wkrótce zostanie wyłączony.

Algorytm powinien uwzględniać charakterystykę obciążenia. Dla krótkich, jednorodnych żądań round-robin będzie wystarczający; przy skokach opóźnień i nierównych czasach odpowiedzi lepiej sprawdzi się least response time. Wysokie wagi warto nadawać nowym, mocniejszym maszynom lub instancjom po reindeksacji pamięci podręcznej. Jeśli backendy wykonują kosztowne operacje I/O, pomocne jest wprowadzenie limitów równoległości i mechanizmów backpressure, aby nie zalać ich lawiną nowych połączeń.

Kondycja backendów, health-checki i odporność

Żeby decyzje były trafne, load balancer potrzebuje wiarygodnej informacji o kondycji serwerów. Służą do tego mechanizmy health check: od prostych pingów TCP/HTTP po złożone testy, które sprawdzają integralność zależności (np. odpowiedź kontrolera statusu aplikacji, opóźnienie zapytania do bazy, wynik operacji w kolejce). Dobrze zaprojektowany endpoint zdrowia powinien odróżniać stan “żywy” od “gotowy” (liveness vs readiness). Serwer może działać, ale chwilowo nie być gotowy do obsługi ruchu produkcyjnego — np. trwa migracja danych lub rozgrzewanie cache.

Oprócz health-checków LB powinien implementować politykę timeoutów, budżetów retry i bezpiecznych retransmisji. Retries zwiększają szansę na sukces w razie sporadycznych błędów sieci, ale w nadmiarze multiplikują ruch i mogą pogrążyć przeciążony system (efekt “retry storm”). Dlatego stosuje się backoff, jitter i limity globalne, a w warstwie aplikacyjnej wzorce circuit breaker i token bucket. To samo dotyczy kolejek wyprzedzających (surge queues): pomagają wygładzać szczyty, lecz zbyt długie kolejki oznaczają, że użytkownik poczeka zbyt długo i i tak przerwie żądanie.

Praktyczny aspekt odporności to również “draining” — przed planowanym wyłączeniem backendu informujemy load balancer, by przestał kierować do niego nowe połączenia i pozwolił zakończyć istniejące. To klucz do wdrożeń bez przestojów: aktualizacje aplikacji, zmiany konfiguracji jądra czy wymiana certyfikatów mogą wtedy przebiec bez odczuwalnego skutku dla użytkowników.

Zabezpieczenia i ochrona aplikacji

Load balancer jest naturalnym miejscem, w którym zbiegają się różne linie obrony. Terminuje TLS, więc odpowiada za negocjację protokołów, wersji i szyfrów, a także za obsługę SNI i OCSP stapling. Gapowato ustawione handshake’y i nadmiernie długie czasy na nawiązanie połączenia mogą zwiększać ryzyko ataków zasobowych. Warto więc stosować rozsądne limity, HSTS, preferować nowoczesne szyfry i dbać o rotację certyfikatów.

Ochrona przed nadużyciami to rate limiting, filtrowanie botów, reguły WAF (od podstawowych sygnatur SQLi/XSS po reguły kontekstowe), a także mechanizmy weryfikacji geograficznej, listy dozwolonych adresów, nagłówki security i normalizacja wejścia. W środowiskach API często wykorzystuje się klucze i tokeny, a load balancer potrafi je wstępnie weryfikować, zanim żądanie trafi do aplikacji. Z perspektywy operatora hostingu to właśnie LB bywa tarczą pierwszego kontaktu przy atakach wolumetrycznych; współpraca z upstreamowym scrubbing center lub operatorem sieci może wtedy decydować o skuteczności obrony.

Warto pamiętać, że bezpieczeństwo dotyczy również kanałów wewnętrznych: ruch między load balancerem a backendem powinien być szyfrowany, gdy przechodzi przez niezaufane sieci, a w środowiskach regulowanych (np. finanse, zdrowie) również wzajemnie uwierzytelniany (mTLS). Dobre praktyki obejmują też segmentację i minimalne uprawnienia: LB widzi tylko to, co konieczne, a backend udostępnia wyłącznie porty i ścieżki niezbędne do funkcjonowania aplikacji.

Globalny ruch, DNS i integracja z chmurą

Skala geograficzna wymusza inny rodzaj równoważenia: globalne. GSLB (Global Server Load Balancing) decyduje, do którego regionu trafi użytkownik, często na poziomie DNS. Warianty z BGP i Anycast ogłaszają ten sam adres IP z wielu miejsc na świecie, dzięki czemu ruch trafia do najbliższego węzła topologicznie. Na krawędzi (edge) ruch może być dodatkowo filtrowany, przycinany i buforowany, a CDN przejmie dostarczanie statycznych treści i części dynamicznych odpowiedzi.

U dostawców chmurowych mamy do wyboru usługi L4 i L7 o różnym profilu: w AWS Classic/ALB/NLB, w GCP Load Balancing (HTTP(S), TCP/UDP, Internal), w Azure Front Door, Application Gateway czy Azure Load Balancer. Integracja z autoscalerami, grupami instancji i strefami dostępności upraszcza eksploatację i podnosi niezawodność. Warto jednak rozumieć ograniczenia: limity połączeń, sposób liczenia kosztów za GB i za reguły, latencję sond, a także funkcje specyficzne dla danego dostawcy (np. TLS passthrough vs termination, wsparcie dla PROXY protocol, sticky sessions).

W klasycznym hostingu współdzielonym równoważenie odbywa się często w warstwie HTTP poprzez farmę reverse proxy. Dla klientów VPS/serwerów dedykowanych popularnym wyborem jest HAProxy, NGINX lub Envoy — z możliwością własnej automatyzacji, metryk i logów oraz integracji z systemami CI/CD. Ważne są też procedury awaryjne: jeśli LB w chmurze stanie się wąskim gardłem kosztowym, można przenieść część ruchu na własne instancje lub CDN, zachowując spójność adresacji i certyfikatów.

Kubernetes, mikroserwisy i service mesh

W orkiestracji kontenerów rolę “wewnętrznego” load balancera pełni warstwa kube-proxy/iptables lub eBPF, a na krawędzi klastra — Ingress Controller (np. NGINX, HAProxy, Traefik) lub Gateway API. Usługa typu LoadBalancer integruje się z chmurą, aby uzyskać publiczny adres i zasady routingu. Wzorzec service mesh (Istio, Linkerd) wprowadza sidecary i polityki ruchu per usługa: retry, circuit breaking, limitowanie i obserwowalność bez modyfikacji kodu.

Szczególne znaczenie ma autoskalowanie na podstawie metryk (HPA, KEDA). Gdy rośnie ruch, przybywa podów, a Ingress automatycznie uwzględnia nowe endpointy. Wymaga to przemyślanych readiness probe, aby nowe repliki nie zostały od razu zalane żądaniami. W mikroserwisach ważne jest też ograniczenie kaskadowych retry między usługami — load balancer na krawędzi może zagrać rolę “doradcy”, ale to polityki w mesh i logika aplikacji zapobiegają burzy ponowień.

Jeśli aplikacja korzysta z gRPC, trzeba zadbać o obsługę strumieni i mapowanie metod do backendów. HTTP/2 wprowadza długowieczne połączenia, które warto równoważyć nie tylko na poziomie żądań, ale i połączeń. Niektóre controllery wspierają out-of-the-box prerouting, SNI-routing, wzorce canary i blue/green, co ogromnie ułatwia wdrożenia.

Wydajność i tuning: od jądra po TLS

Wysoka przepustowość zaczyna się na poziomie systemu operacyjnego. Warto włączyć SO_REUSEPORT, odpowiednio dobrać rozmiary buforów, okna TCP, parametry SYN backlog i ochronę (SYN cookies), a przy bardzo wysokich wolumenach sięgnąć po XDP/eBPF, DPDK lub akcelerację sprzętową. Epoll/kqueue i model wielowątkowy dopasowany do liczby rdzeni pomagają uniknąć blokad. W warstwie TLS liczy się preferencja do ECDHE, sesje w trybie resumption i 0-RTT (z rozwagą), a także cache sesji między procesami balancera.

W HTTP przyspieszamy dzięki kompresji (gzip, brotli) z limitem dla dużych odpowiedzi, buforowaniu nagłówków, normalizacji i odfiltrowaniu niepotrzebnych pól. Dobrą praktyką jest ograniczanie rozmiaru nagłówków i ciał żądań, co chroni zarówno LB, jak i backendy przed nieuczciwym wykorzystaniem zasobów. Jeśli korzystamy z WebSocket, trzeba dostroić parametry keep-alive i limity ramek.

Warto testować wydajność w sposób etapowy: najpierw syntetyczne narzędzia (wrk, vegeta, k6), potem testy zbliżone do realnego ruchu, wreszcie chaos engineering (awarie backendów, skoki opóźnień, utrata pakietów). Kluczowe metryki to P50/P95/P99 opóźnień, liczba aktywnych połączeń, odsetek błędów, wykorzystanie CPU i pamięci, a także metryki buforów i kolejek w samym LB.

Wysoka dostępność load balancera i sieć pod spodem

Redundancja LB to często duet z wirtualnym IP i protokołem VRRP/keepalived. W środowiskach o większej skali stosuje się pary lub kwadry aktywne–aktywne, z dystrybucją ruchu przez ECMP i konsystentne hashowanie na routerach brzegowych. W warstwie routingu BGP jest królem: pozwala szybko przełączyć trasę, ogłaszać prefiksy z wielu lokalizacji i realizować polityki ruchu w zależności od stanu.

Nie zapominajmy o magazynie stanu. Jeśli LB utrzymuje tablice sesji lub cache TLS, potrzebne są mechanizmy replikacji albo podejście bezstanowe. W praktyce operatorzy starają się, by LB był jak najbardziej stateless: prościej go wtedy skalować i przełączać. Dane operacyjne (metryki, logi, trasy) trafiają do systemów zewnętrznych, które również są redundantne i gotowe na awarie domeny dostępności.

Gdy zależy nam na minimalnych przestojach, przydatne są techniki connection draining, stopniowego włączania instancji i testów “shadow traffic”, które duplikują część ruchu na nową wersję aplikacji bez wpływu na użytkowników. Z kolei wdrożenia typu blue/green i canary pozwalają zestawiać środowiska równoległe i przełączać ruch w kontrolowany sposób, z możliwością szybkiego rollbacku.

Eksploatacja: logi, monitoring i diagnozowanie problemów

Load balancer generuje cenne dane: logi dostępu, logi błędów, metryki warstwy sieci i aplikacji, a często również ślady rozproszone zgodne z OpenTelemetry. Na ich podstawie budujemy alerty, SLO i budżety błędów. W praktyce wiele incydentów zaczyna się od subtelnych zmian w P99 lub wzrostu liczby połączeń w stanie CLOSE_WAIT — sygnały, które widać w metrykach, zanim dojdzie do dużej awarii.

Diagnoza problemów obejmuje korelację logów LB z logami backendów i analizę trasowania. Nierzadko przyczyna jest poza aplikacją: MTU path mismatch, błędna polityka sieciowa, oversubscription łącza. Warto mieć pod ręką narzędzia jak tcpdump, ss, mtr i zestaw dashboardów z metrykami end-to-end. W świecie HTTP ważna jest też inspekcja nagłówków (X-Forwarded-For, X-Request-ID, PROXY protocol), aby backendy wiedziały, skąd przyszedł użytkownik i jak spiąć ślady w systemie obserwowalności.

Dobrym nawykiem jest testowanie procedur awaryjnych: manualny i automatyczny failover, symulacja utraty jednej strefy dostępności, testy wydajności certyfikatu i przeładowania konfiguracji bez zrywania połączeń. To pozwala uniknąć “niespodzianek” w produkcji.

Dobór rozwiązań i wzorce użycia w hostingu

Małe wdrożenia skorzystają z prostego L4/L7 na jednej lub dwóch instancjach z VRRP. Średnia skala to farmy LB z autoskalerem i centralnym systemem metryk. Wielka skala wymaga separacji ról (edge vs core), specjalizacji (TLS terminacja na dedykowanych węzłach) i często własnej sieci z BGP. W hostingach współdzielonych ważny jest multi-tenancy: izolacja klientów, limity per domena, per IP, per ścieżka, a także elastyczne reguły routingu różne dla setek witryn.

Wybór między L4 i L7 zależy od funkcjonalnych potrzeb: jeśli wystarczy szybkie przesyłanie TCP/UDP i minimalne opóźnienie, L4 wygra wydajnością. Gdy potrzebne są reguły zależne od ścieżek, nagłówków i ciasteczek, L7 jest naturalnym wyborem. W praktyce często łączymy warstwy: L4 jako brama wysokiej przepustowości i L7 bliżej aplikacji, gdzie wykonuje się cięższe decyzje.

Warto też ocenić, czy część zadań nie przenieść na CDN: statyczne pliki, obrazy, komponenty SPA. To redukuje koszt i obciążenie LB oraz backendów. Z drugiej strony, nie każdy ruch nadaje się do cache’owania, a dynamiczne API wymaga starannej obsługi nagłówków i autoryzacji.

Lista kontrolna wdrożenia

  • Architektura: zdecyduj o warstwie (L4/L7), trybie (NAT/DSR/proxy) i redundancji (aktywny–aktywny/aktywny–pasywny).
  • Algorytm: dobierz strategię rozkładu ruchu i politykę stickiness, biorąc pod uwagę charakter żądań.
  • Zdrowie: zaimplementuj liveness/readiness, ustal częstotliwość i progi odcięcia backendów.
  • Timeouty i retry: zdefiniuj budżety, backoff, jitter i ograniczenia globalne.
  • Bezpieczeństwo: TLS terminacja/passthrough, mTLS tam, gdzie to potrzebne, WAF i rate limiting.
  • Obserwowalność: metryki P50/P95/P99, logi z korelacją, ślady rozproszone, alerty i SLO.
  • Wydajność: tuning systemu, limity połączeń, kompresja, limity rozmiarów, cache nagłówków.
  • HA: VRRP/BGP, testy failover, connection draining, procedury backupu konfiguracji.
  • CI/CD: blue/green, canary, testy shadow, automatyzacja reloadu bez zrywania połączeń.
  • Koszt: monitoruj zużycie przepustowości, liczbę reguł i połączeń; w razie potrzeby przenieś część ruchu na CDN.

Najczęstsze błędy i jak ich uniknąć

Najpoważniejsze problemy wynikają ze słabych health-checków (fałszywe pozytywy/negatywy), braku limitów retry i zbyt agresywnej kompresji. Inną pułapką jest stickiness po IP w środowisku mobilnym, co prowadzi do “skaczących” sesji. Nierzadko spotyka się też błędny routing DSR z powodu asymetrii tras. Rozwiązaniem są klarowne, przetestowane reguły, rozdzielenie ról L4/L7 i stopniowe wdrażanie zmian z dobrą telemetrią.

W obszarze TLS częsty kłopot to nieprzemyślana rotacja certyfikatów i brak automatyzacji. Użycie narzędzi typu ACME/Let’s Encrypt i magazynów kluczy z kontrolą dostępu minimalizuje ryzyko. Należy też pilnować zgodności wersji protokołów z klientami — zbyt agresywne cięcia mogą odciąć część użytkowników, ale zbyt konserwatywne konfiguracje narażają na podatności.

Wreszcie, nie ignoruj kosztów: niektóre chmurowe LB rozliczają ruch, reguły i godziny działania. Architekturę warto planować z myślą o budżecie, korzystając z cache, CDN i skalowania horyzontalnego tam, gdzie ma to największy efekt.