1/50
Wprowadzenie do wysokiej dostępności (HA)
  • Wysoka dostępność (HA, High Availability) to zdolność systemu do nieprzerwanego działania przez długi czas, przy minimalnych przestojach.
  • W dzisiejszym cyfrowym świecie, gdzie usługi muszą być dostępne 24/7, HA jest koniecznością.
  • Celem projektowania systemów HA jest eliminacja pojedynczych punktów awarii (SPOF - Single Point of Failure) poprzez redundancję na każdym poziomie architektury.
  • Dostępność mierzy się w procentach; „pięć dziewiątek” (99,999%) oznacza mniej niż 6 minut przestoju w skali całego roku.
Ilustracja dla slajdu 1

W praktyce inżynieryjnej wysoka dostępność oznacza zdolność systemu do maskowania awarii przed użytkownikiem końcowym poprzez inteligentne wykorzystanie zasobów zapasowych. Kluczowym pojęciem jest tutaj MTBF (Mean Time Between Failures) oraz MTTR (Mean Time To Repair), które bezpośrednio przekładają się na procentowy wskaźnik dostępności. Im wyższy MTBF i niższy MTTR, tym bardziej niezawodny staje się cały system informatyczny.

Projektowanie systemów HA wymaga przyjęcia założenia, że każdy komponent prędzej czy później ulegnie awarii – jest to tak zwane „design for failure”. Inżynierowie muszą przewidzieć scenariusze awarii dysków, kart sieciowych, zasilaczy, a nawet całych szaf serwerowych. Dopiero uwzględnienie wszystkich tych poziomów tworzy spójną strategię wysokiej dostępności.

Współczesne systemy HA często korzystają z architektur mikroserwisowych, gdzie każda usługa jest niezależnie replikowana i monitorowana. Dzięki temu awaria jednego komponentu nie paraliżuje całej platformy, a użytkownik doświadcza co najwyżej minimalnego spowolnienia. Takie podejście jest standardem w największych światowych serwisach internetowych.

2/50
Czym jest dostępność?
To kluczowy wskaźnik jakości usługi, mający bezpośredni wpływ na satysfakcję klienta i zaufanie do dostawcy.
  • Dostępność to metryka określająca, przez jaki procent czasu system jest sprawny dla użytkowników.
  • Oblicza się ją jako stosunek czasu sprawnego działania do całkowitego czasu w danym okresie.
  • Wysoka dostępność wymaga starannego planowania, wdrożenia redundancji, mechanizmów automatycznego przełączania awaryjnego oraz proaktywnego monitorowania stanu wszystkich komponentów.
Ilustracja dla slajdu 2

Dostępność systemu mierzy się nie tylko w kontekście całej infrastruktury, ale także na poziomie poszczególnych endpointów API. W nowoczesnych systemach rozproszonych każda ścieżka żądania może mieć inną charakterystykę dostępności. Dlatego kluczowe jest monitorowanie dostępności dla każdego zasobu osobno, a nie tylko ogólnego stanu serwera.

Warto rozróżnić dostępność techniczną (czy serwer odpowiada na ping) od dostępności funkcjonalnej (czy użytkownik może wykonać konkretną operację). Serwer może być technicznie żywy, ale jego baza danych może być przeciążona lub odcięta od sieci. Właśnie dostępność funkcjonalna jest tym, co naprawdę liczy się dla klienta końcowego.

W praktyce SLA często definiuje się dla różnych okien czasowych – na przykład osobno dla godzin szczytu i poza nimi. Dostawcy usług chmurowych oferują gwarancje dostępności na poziomie 99,99% dla pojedynczych zasobów, ale osiągnięcie tego wymaga odpowiedniej konfiguracji stref dostępności i mechanizmów automatycznego odzyskiwania.

3/50
SLA, SLO, SLI
  • Te trzy akronimy to fundament zarządzania niezawodnością.
  • SLI (Service Level Indicator) to konkretna, mierzalna metryka, np. czas odpowiedzi.
  • SLO (Service Level Objective) to wewnętrzny cel dla tej metryki, np. „99,9% żądań musi być poniżej 200 ms”.
  • SLA (Service Level Agreement) to formalna umowa z klientem określająca gwarantowany poziom usług i konsekwencje jego niedotrzymania.
  • Zespoły inżynierskie dążą do spełnienia SLO, które zazwyczaj są bardziej rygorystyczne niż SLA, by zapewnić niezbędny margines błędu.
Ilustracja dla slajdu 3

Zrozumienie różnicy między SLA, SLO i SLI jest kluczowe dla zarządzania niezawodnością usług w modelu DevOps. SLI to surowa metryka – na przykład opóźnienie (latency) mierzone w milisekundach, przepustowość (throughput) wyrażona w żądaniach na sekundę lub współczynnik błędów. SLO to wartość progowa, która definiuje akceptowalny poziom tej metryki.

SLI dzielą się na kilka kategorii: dostępność (availability), czas odpowiedzi (latency), przepustowość (throughput) oraz współczynnik błędów (error rate). Każda z tych kategorii wymaga innego podejścia do monitorowania i alarmowania. Dobrze zdefiniowane SLI pozwalają zespołowi szybko identyfikować, który aspekt usługi wymaga natychmiastowej interwencji.

SLA to dokument prawny, który określa konsekwencje finansowe niedotrzymania obietnic. Dlatego inżynierowie powinni dążyć do SLO bardziej rygorystycznych niż SLA – tworząc w ten sposób „error budget”, czyli budżet błędów, który można świadomie wykorzystać na ryzykowne aktualizacje lub nowe funkcje.

4/50
Architektury wysokiej dostępności
  • Budowa systemów HA opiera się na redundancji i automatyzacji.
  • Istnieje kilka modeli: N+1 (jedna dodatkowa instancja zapasowa), N+M (wiele instancji zapasowych).
  • Najbardziej niezawodne systemy wykorzystują architekturę rozproszoną geograficznie, gdzie infrastruktura jest zduplikowana w niezależnych centrach danych.
  • Chroni to przed katastrofami na dużą skalę, takimi jak awarie całych regionów sieciowych czy przerwy w dostawie prądu w dużych obszarach metropolitalnych.
Ilustracja dla slajdu 4

Architektury HA można klasyfikować według stopnia izolacji awarii – od lokalnych (redundancja wewnątrz jednego racka), przez regionalne (replikacja między strefami dostępności), aż po globalne (rozproszenie geograficzne). Każdy z tych poziomów wprowadza inne opóźnienia i koszty. Dobór odpowiedniego poziomu zależy od krytyczności biznesowej usługi.

W architekturze warstwowej każda warstwa (prezentacji, aplikacji, danych) wymaga własnej strategii HA. Na przykład warstwa prezentacji może być chroniona przez CDN i wiele load balancerów, natomiast warstwa danych wymaga zaawansowanej replikacji synchronicznej. Mieszanie strategii między warstwami może prowadzić do nieoczekiwanych interakcji i trudnych do debugowania problemów.

Coraz popularniejsze stają się architektury „multi-cloud”, gdzie zasoby są rozproszone między różnych dostawców chmurowych (AWS, Azure, GCP). Eliminuje to ryzyko awarii całego dostawcy, ale znacząco podnosi złożoność operacyjną i wymaga standaryzacji narzędzi oraz procesów zarządzania konfiguracją.

5/50
Model aktywny-aktywny vs aktywny-pasywny (Modele redundancji)
  • To dwa podstawowe modele redundancji.
  • W konfiguracji active-passive tylko jedna instancja obsługuje ruch, a druga jest w trybie gotowości (standby) i przejmuje pracę dopiero w razie awarii.
  • W modelu active-active wszystkie instancje jednocześnie obsługują żądania, co zapewnia nie tylko wysoką dostępność, ale i skalowalność, bo zasoby wszystkich maszyn pracują.
  • Choć model active-active jest bardziej złożony w konfiguracji i synchronizacji danych, oferuje lepszą wydajność i krótszy czas przełączania.
Ilustracja dla slajdu 5

W modelu aktywny-pasywny kluczową kwestią jest czas przełączania (failover time), który zależy od mechanizmu detekcji awarii i procedury promowania węzła pasywnego. Nowoczesne rozwiązania skracają ten czas do kilku sekund poprzez ciągłe utrzymywanie sesji i replikację stanu w czasie rzeczywistym. Nadal jednak istnieje okno podatności, w którym usługa jest niedostępna.

Model aktywny-aktywny wymaga starannego zarządzania spójnością danych, szczególnie w systemach rozproszonych. Konieczne jest zastosowanie mechanizmów takich jak distributed locking, quorum-based writes czy konfliktowe strategie CRDT (Conflict-free Replicated Data Types). Bez nich węzły mogą produkować sprzeczne dane, prowadząc do poważnych problemów biznesowych.

Hybrydowe podejścia, takie jak „active-active dla odczytów, active-passive dla zapisów”, są często stosowane w praktyce produkcyjnej. Pozwalają one na skalowanie ruchu odczytu na wielu węzłach, jednocześnie utrzymując prostotę zapisów na jednym masterze. Jest to kompromis między wydajnością a złożonością architektoniczną.

6/50
Rozkład obciążenia – modele
  • Równoważenie obciążenia (load balancing) jest kluczem do HA.
  • Load balancery warstwy 4 (transportowej) działają na poziomie IP i portów (np. TCP), co jest proste i wydajne.
  • Load balancery warstwy 7 (aplikacyjnej) analizują treść żądania (np. ścieżki URL, nagłówki, ciasteczka HTTP), co pozwala na inteligentny routing do specyficznych usług.
  • Dzięki temu można precyzyjniej zarządzać ruchem, realizować bezpieczne wdrożenia i optymalizować wykorzystanie zasobów serwerowych w zależności od rodzaju zapytania.
Ilustracja dla slajdu 6

Algorytmy równoważenia obciążenia dzielą się na statyczne (round-robin, weighted round-robin, IP hash) i dynamiczne (least connections, least response time, adaptive). Algorytmy dynamiczne reagują na bieżący stan serwerów i są bardziej skuteczne w środowiskach o zmiennym obciążeniu. Ich wadą jest jednak wyższe zużycie zasobów samego load balancera.

Nowoczesne load balancery często łączą funkcje warstwy 4 i 7, umożliwiając terminację SSL, buforowanie odpowiedzi, rate limiting oraz zaawansowane routowanie na podstawie zawartości żądania. Takie rozwiązania noszą nazwę Application Delivery Controllers (ADC) i stanowią zaawansowane narzędzia do zarządzania ruchem sieciowym.

W środowiskach chmurowych load balancery są często zarządzane jako usługa (ELB w AWS, Load Balancer w GCP), co odciąża zespoły operacyjne od utrzymania własnej infrastruktury. Kluczową zaletą jest automatyczne skalowanie samego load balancera oraz integracja z mechanizmami auto-healing i service discovery.

7/50
Rodzaje równoważników obciążenia
  • Równoważenie obciążenia może być sprzętowe (wysoka wydajność, ale wysoki koszt i mała elastyczność) lub programowe (Nginx, HAProxy, usługi chmurowe typu AWS ELB).
  • Programowe rozwiązania oferują ogromną elastyczność i łatwe skalowanie w poziomie.
  • Istnieje też równoważenie po stronie klienta (client-side load balancing), gdzie aplikacja sama wybiera serwer z listy dostępnych.
  • Każde podejście ma swoje wady i zalety w zależności od skali systemu, budżetu i wymagań co do czasu odpowiedzi.
Ilustracja dla slajdu 7

HAProxy to jeden z najpopularniejszych programowych load balancerów, oferujący bogate możliwości monitorowania stanu serwerów (health checks) i zaawansowane algorytmy równoważenia. Może pracować zarówno w trybie TCP, jak i HTTP, a jego konfiguracja jest w pełni deklaratywna. Nginx z kolei doskonale sprawdza się jako reverse proxy z wbudowanym load balancingiem i cache'owaniem.

W środowiskach chmurowych coraz częściej stosuje się service mesh (np. Istio, Linkerd), gdzie równoważenie obciążenia odbywa się na poziomie sidecar proxy. Każda instancja usługi ma własny proxy, który decyduje o routingu żądań. To podejście zapewnia większą kontrolę nad ruchem i lepszą obserwowalność kosztem dodatkowego narzutu obliczeniowego.

Client-side load balancing, popularny w ekosystemie Netflix OSS (Ribbon, Spring Cloud Load Balancer), polega na tym, że klient przechowuje listę dostępnych serwerów i sam wybiera, do którego wysłać żądanie. Eliminuje to pojedynczy punkt awarii w postaci centralnego load balancera, ale wymaga bardziej zaawansowanej logiki po stronie klienta.

8/50
Skalowanie pionowe
  • Skalowanie pionowe polega na zwiększaniu mocy pojedynczego serwera (więcej CPU, RAM, szybsze dyski).
  • To najprostsza metoda, niewymagająca zmian w architekturze kodu.
  • Ma jednak limity fizyczne i rosnące wykładniczo koszty.
  • Największą wadą jest to, że nie poprawia ono dostępności – wciąż mamy pojedynczy punkt awarii (SPOF).
  • Jeśli ten potężny serwer zawiedzie, usługa znika.
  • Skalowanie pionowe stosuje się zazwyczaj w początkowej fazie projektu lub dla specyficznych baz danych, których nie da się łatwo rozproszyć.
Ilustracja dla slajdu 8

Mimo ograniczeń skalowanie pionowe ma swoje miejsce w architekturze systemów, szczególnie w przypadku baz danych wymagających silnej spójności (strong consistency). Relacyjne bazy danych, takie jak PostgreSQL czy Oracle, często korzystają ze skalowania pionowego jako podstawowej metody zwiększania wydajności. Dodanie większej ilości pamięci RAM może znacząco poprawić czas wykonywania złożonych zapytań.

Proces skalowania pionowego w chmurze jest stosunkowo prosty – wymaga zatrzymania instancji, zmiany jej typu i ponownego uruchomienia. Wiąże się to jednak z przerwą w działaniu usługi (downtime), która może być niedopuszczalna dla systemów krytycznych. Rozwiązaniem są usługi oferujące „live resize”, ale są one dostępne tylko w wybranych platformach chmurowych.

Skalowanie pionowe ma również wpływ na architekturę aplikacji – jeśli aplikacja nie jest zaprojektowana z myślą o wykorzystaniu wielu rdzeni lub dużej ilości pamięci, dodanie mocy obliczeniowej może nie przynieść oczekiwanych rezultatów. W takich przypadkach konieczna jest optymalizacja kodu pod kątem współbieżności i zarządzania pamięcią.

9/50
Skalowanie poziome
  • Skalowanie poziome to dodawanie kolejnych, mniejszych serwerów pod load balancerem.
  • To fundament nowoczesnych chmur, pozwalający na niemal nieograniczoną rozbudowę.
  • Wymaga jednak, by aplikacja była „bezstanowa” (stateless), czyli nie przechowywała danych sesji lokalnie na dysku jednego serwera.
  • Skalowanie poziome naturalnie buduje wysoką dostępność – awaria jednego serwera w grupie 10 czy 100 jest niemal niezauważalna dla użytkowników, a uszkodzoną maszynę można automatycznie wymienić na nową.
Ilustracja dla slajdu 9

Skalowanie poziome wymaga od aplikacji spełnienia kryterium „statelessness” – czyli nieprzechowywania żadnych danych sesyjnych lokalnie. W praktyce oznacza to konieczność wydzielenia wspólnego magazynu dla danych sesji (Redis, Memcached) lub wykorzystanie tokenów JWT do przenoszenia kontekstu użytkownika między żądaniami. Bez tego dwa kolejne żądania tego samego użytkownika mogą trafić na różne serwery.

Kluczowym wyzwaniem w skalowaniu poziomym jest zarządzanie stanem rozproszonym (distributed state). Narzędzia takie jak Apache ZooKeeper, etcd czy Consul zapewniają spójny, rozproszony magazyn konfiguracji i informacji o stanie klastra. Służą one jako „kręgosłup” dla systemów, które muszą podejmować skoordynowane decyzje w środowisku rozproszonym.

W praktyce skalowanie poziome rzadko jest liniowe – dodanie drugiego serwera nie zawsze podwaja wydajność systemu. Straty wynikają z kosztów synchronizacji, komunikacji między węzłami oraz potencjalnych konfliktów dostępu do współdzielonych zasobów. Inżynierowie muszą uwzględniać te czynniki przy planowaniu pojemności (capacity planning).

10/50
Skalowanie aplikacji webowych
  • Skalowanie trójwarstwowej aplikacji wymaga podejścia do każdego poziomu osobno.
  • Warstwa webowa (interfejs) i aplikacyjna (logika) są zazwyczaj bezstanowe i skalują się poziomo dość łatwo.
  • Warunkiem jest delegacja stanu (np. sesji użytkownika) do zewnętrznego magazynu pamięci podręcznej (np. Redis).
  • Największym wyzwaniem pozostaje warstwa danych (bazy danych), która wymaga bardziej zaawansowanych technik replikacji i synchronizacji, by zachować spójność informacji przy jednoczesnym wzroście liczby zapytań.
Ilustracja dla slajdu 10

W trójwarstwowej architekturze webowej najprościej skaluje się warstwę statycznych zasobów (HTML, CSS, JS), które można serwować bezpośrednio z CDN. Prawdziwym wyzwaniem jest warstwa aplikacji, która często zawiera złożoną logikę biznesową i może być stanowa. Nowoczesne frameworki webowe (Node.js, Spring Boot, Django) oferują wbudowane wsparcie dla stanu bezstanowego.

Bazy danych w architekturze webowej są najczęściej wąskim gardłem. Techniki takie jak cachowanie zapytań (query caching), optymalizacja indeksów oraz sharding mogą znacząco opóźnić moment, w którym baza staje się problemem. Warto również rozważyć użycie baz NoSQL dla danych o mniej restrykcyjnych wymaganiach spójności.

Monitorowanie aplikacji webowej w kontekście skalowania wymaga śledzenia metryk takich jak liczba aktywnych połączeń, średni czas odpowiedzi w percentylach (P50, P95, P99) oraz przepustowość. Narzędzia takie jak Prometheus wraz z Grafana pozwalają na tworzenie dashboardów, które w czasie rzeczywistym pokazują, które warstwy wymagają interwencji.

11/50
Skalowanie baz danych
  • Skalowanie baz danych to trudny proces.
  • Odczyty (read) skaluje się przez tworzenie replik (read replicas).
  • Zapisy (write) są wyzwaniem, z którym radzi sobie sharding (dzielenie bazy na mniejsze partycje) lub przejście na rozproszone bazy NoSQL (np. Cassandra, MongoDB), zaprojektowane od podstaw pod skalowanie poziome.
  • Każda z tych metod ma swoje kompromisy, opisane twierdzeniem CAP (Consistency, Availability, Partition tolerance), które mówi, że w systemie rozproszonym nie można zagwarantować wszystkich trzech cech naraz.
Ilustracja dla slajdu 11

Sharding to technika polegająca na podziale danych na partycje (shardy) według klucza (shard key). Każdy shard jest przechowywany na innym serwerze, co pozwala na rozłożenie obciążenia zapisów. Wybór odpowiedniego klucza shardowania jest krytyczny – jeśli klucz nie zapewnia równomiernego rozkładu danych, niektóre shardy mogą być przeciążone (tzw. hot shards).

Twierdzenie CAP (Consistency, Availability, Partition Tolerance) mówi, że w systemie rozproszonym można zagwarantować tylko dwie z trzech cech. Systemy NoSQL często rezygnują z silnej spójności na rzecz dostępności i tolerancji na partycjonowanie. Cassandra oferuje tunable consistency, gdzie każde zapytanie może określić wymagany poziom spójności.

Współczesne bazy danych oferują coraz więcej automatyzacji w zakresie skalowania. Amazon Aurora automatycznie replikuje dane w trzech strefach dostępności i skaluje storage do 128 TB bez przestojów. Google Spanner oferuje globalne skalowanie z silną spójnością dzięki synchronizacji czasu za pomocą atomowych zegarów GPS i protokołu TrueTime.

12/50
Replikacja danych
  • Replikacja zapewnia HA i skalowalność odczytu.
  • W modelu master-slave, serwer główny (master) obsługuje wszystkie zapisy, a zmiany są kopiowane na serwery zapasowe (slaves).
  • Jeśli master ulegnie awarii, jeden z węzłów slave jest automatycznie „promowany” na nowego mastera.
  • Replikacja może być synchroniczna (gwarantuje brak utraty danych, ale jest wolniejsza) lub asynchroniczna (szybsza, ale dopuszcza minimalną utratę danych przy awarii).
  • Wybór zależy od krytyczności danych i wymagań co do czasu odpowiedzi aplikacji.
Ilustracja dla slajdu 12

Replikacja synchroniczna gwarantuje, że zapis jest potwierdzony dopiero po zapisaniu go na wszystkich węzłach repliki. Zapewnia to zerową utratę danych (RPO = 0), ale znacząco zwiększa opóźnienie zapisów, szczególnie przy dużych odległościach geograficznych między centrami danych. W praktyce stosuje się ją głównie w lokalnych klastrach o niskim opóźnieniu sieciowym.

Replikacja asynchroniczna pozwala na znacznie wyższą przepustowość zapisów, ponieważ węzeł główny nie czeka na potwierdzenie replik. Ryzyko polega na tym, że w przypadku awarii mastera przed zakończeniem replikacji, ostatnie transakcje mogą zostać utracone. Dlatego w krytycznych systemach stosuje się tryb semi-synchroniczny, gdzie zapis jest potwierdzany po zapisaniu na co najmniej jednym wybranym węźle.

W systemach bazodanowych replikacja może być również używana do tworzenia kopii zapasowych w czasie rzeczywistym (real-time backup) oraz do odciążania mastera od operacji odczytu (read scaling). Narzędzia takie jak Patroni dla PostgreSQL automatycznie zarządzają procesem promowania replik i wykrywania awarii.

13/50
Systemy kolejek wiadomości
  • Kolejki (np. RabbitMQ, Kafka) rozdzielają usługi, pozwalając na komunikację asynchroniczną.
  • Usługa wysyła zadanie do kolejki i natychmiast wraca do pracy, nie czekając na przetworzenie danych.
  • Inna usługa (konsument) pobiera zadania z kolejki we własnym tempie.
  • Taka architektura zwiększa odporność: jeśli konsument ulegnie awarii, zadania czekają bezpiecznie w kolejce.
  • Kolejki działają też jak bufor (tłumik), który chroni backend przed nagłymi skokami ruchu (np. podczas kampanii reklamowych czy „czarnych piątków”).
Ilustracja dla slajdu 13

Apache Kafka różni się od tradycyjnych kolejek (RabbitMQ, ActiveMQ) tym, że przechowuje log wiadomości na dysku i pozwala na wielokrotne odczytywanie tych samych danych. Jest to szczególnie przydatne w architekturze zdarzeniowej (event-driven architecture), gdzie wielu konsumentów może niezależnie przetwarzać ten sam strumień zdarzeń. Kafka gwarantuje kolejność w obrębie partycji.

RabbitMQ oferuje bardziej zaawansowane wzorce routowania (topic exchange, direct exchange, fanout exchange) oraz potwierdzanie dostarczenia (delivery acknowledgments). Jego mechanizm dead letter queue pozwala na przechowywanie wiadomości, które nie mogły zostać przetworzone, co ułatwia debugowanie i analizę błędów. Wspiera także opóźnione kolejki (delayed queues).

Ważnym aspektem kolejek jest zagwarantowanie exactly-once delivery lub przynajmniej at-least-once delivery. Idempotentność konsumentów – czyli zdolność do wielokrotnego przetworzenia tej samej wiadomości bez negatywnych skutków – jest kluczową cechą przy projektowaniu systemów opartych na kolejkach. W przeciwnym razie duplikaty wiadomości mogą prowadzić do poważnych błędów biznesowych.

14/50
Pamięć podręczna
To najtańszy i najskuteczniejszy sposób na poprawę skalowalności.
  • Caching to przechowywanie wyników ciężkich obliczeń lub zapytań do bazy w szybkiej pamięci (Redis, Memcached).
  • Dzięki temu kolejne żądania o te same dane nie obciążają bazy danych, a użytkownik otrzymuje odpowiedź niemal natychmiast (milisekundy).
  • Kluczem do sukcesu jest właściwa strategia unieważniania (invalidation) – musimy decydować, jak długo dane mogą być „nieświeże”, by nie serwować użytkownikom błędnych informacji (np. starych cen czy stanów magazynowych).
Ilustracja dla slajdu 14

Strategie unieważniania pamięci podręcznej to jeden z najtrudniejszych problemów w inżynierii oprogramowania, co potwierdza znane powiedzenie, że są tylko dwa trudne problemy: nadawanie nazw, unieważnianie cache i błędy off-by-one. Cache-aside (lazy loading) to najprostsza strategia, gdzie aplikacja najpierw sprawdza cache, a w przypadku braku danych ładuje je z bazy i zapisuje w cache.

Write-through cache gwarantuje spójność danych, zapisując je jednocześnie do cache i do bazy. Wadą jest większe opóźnienie zapisu. Write-behind (write-back) cache zbiera zapisy i przesyła je do bazy partiami, co zwiększa wydajność, ale ryzykuje utratą danych w przypadku awarii cache przed opróżnieniem bufora.

Redis oferuje nie tylko pamięć podręczną, ale także zaawansowane struktury danych (listy, zbiory, posortowane zbiory, hiperloglogi) oraz moduły takie jak RedisJSON czy RediSearch. W trybie Redis Cluster dane są automatycznie shardowane na wiele węzłów, co zapewnia skalowanie poziome i wysoką dostępność.

15/50
Sieci dostarczania treści (CDN)
  • CDN (Content Delivery Network) to sieć serwerów rozproszona po całym świecie.
  • Przechowuje ona kopie obrazów, filmów i skryptów blisko użytkownika (np. w Warszawie zamiast w USA).
  • To drastycznie skraca czas ładowania strony i odciąża główny serwer, który nie musi wysyłać tych samych plików tysiące razy. CDN zapewnia też dodatkową warstwę ochrony przed atakami DDoS, rozpraszając zmasowany atak na setki swoich węzłów brzegowych, co czyni go niemal niemożliwym do zatrzymania.
Ilustracja dla slajdu 15

CDN działa na zasadzie geograficznie rozproszonych węzłów brzegowych (edge nodes), które przechowują kopie treści statycznych. Gdy użytkownik żąda pliku, DNS kieruje go do najbliższego geograficznie węzła, co znacząco redukuje opóźnienie. Nowoczesne CDN oferują także przetwarzanie dynamicznych treści na brzegu sieci (edge computing) z użyciem serverless functions.

CDN chroni przed atakami DDoS poprzez absorpcję ruchu na tysiącach serwerów brzegowych. W przypadku ataku na warstwę aplikacji, CDN oferuje reguły Web Application Firewall (WAF) oraz rate limiting. Dostawcy CDN tacy jak Cloudflare, Akamai czy Fastly oferują zaawansowane funkcje bezpieczeństwa wbudowane w platformę.

Purge (unieważnienie) zawartości CDN to operacja krytyczna podczas wdrażania nowych wersji aplikacji. Większość CDN oferuje API do programowego usuwania nieaktualnych plików z cache. Strategia „versioned URLs” (gdzie każda wersja pliku ma unikalną nazwę) eliminuje problem unieważniania, ale wymaga starannego zarządzania wersjami w procesie CI/CD.

16/50
Mechanizmy przełączania awaryjnego
  • Failover to automatyczny proces ratunkowy.
  • Wymaga on systemu detekcji awarii (heartbeat) oraz metody przekierowania ruchu (np. wirtualne adresy IP lub zmiany w rekordach DNS).
  • Kluczowe, by proces był szybki i nie wymagał interwencji ludzkiej w środku nocy.
  • W systemach rozproszonych failover może dotyczyć pojedynczego kontenera, całego serwera lub całego kraju.
  • Dobrze zautomatyzowany failover czyni awarię niezauważalną dla użytkownika końcowego, zachowując ciągłość transakcji biznesowych.
Ilustracja dla slajdu 16

Mechanizm przełączania awaryjnego na poziomie sieci często wykorzystuje protokół VRRP (Virtual Router Redundancy Protocol) lub HSRP (Cisco), które pozwalają na współdzielenie wirtualnego adresu IP między fizycznymi routerami. W przypadku awarii głównego ruthera, zapasowy przejmuje jego adres IP i obsługę ruchu. Proces ten jest całkowicie przezroczysty dla klientów końcowych.

W systemach rozproszonych na poziomie aplikacji stosuje się wzorce takie jak Health Check i Watchdog w połączeniu z systemami service discovery. Narzędzia takie jak Consul, etcd czy Kubernetes Service wykrywają niezdrowe instancje i automatycznie usuwają je z puli ruchu. Detekcja awarii musi być szybka, ale nie może generować fałszywych alarmów (false positives).

W architekturach mikroserwisowych przełączanie awaryjne wymaga sekwencyjnego uruchamiania zależności. Jeśli usługa A zależy od usługi B, to podczas awarii usługi B, usługa A musi mieć zaimplementowany mechanizm graceful degradation. Biblioteki takie jak resilience4j (Java) czy Polly (.NET) oferują gotowe implementacje circuit breaker, retry, timeout i bulkhead.

17/50
Mechanizmy ochrony usługi
  • Watchdog to strażnik monitorujący stan aplikacji.
  • Aplikacja musi regularnie wysyłać do niego sygnał „żyję”.
  • Jeśli sygnał nie dotrze w określonym czasie, watchdog uznaje, że system się zawiesił i podejmuje drastyczne, ale skuteczne działanie: zabicie procesu i jego restart lub restart całej maszyny.
  • To prosta i skuteczna metoda na błędy typu „memory leak” (wyciek pamięci) czy „deadlocks” (zakleszczenia procesów), które po pewnym czasie paraliżują system, a których nie da się łatwo wyeliminować z kodu źródłowego.
Ilustracja dla slajdu 17

Watchdog może działać na różnych poziomach: sprzętowym (zewnętrzny układ monitorujący napięcie i sygnały), systemowym (oprogramowanie w przestrzeni jądra) lub aplikacyjnym (proces nadzorujący wątek główny). Najbardziej niezawodne systemy stosują watchdog na poziomie sprzętowym, który jest w stanie zresetować serwer nawet przy całkowitym zawieszeniu systemu operacyjnego.

W środowiskach kontenerowych watchdog jest często zastępowany przez liveness probes w Kubernetes. Są to periodyczne zapytania wysyłane do kontenera, które mogą sprawdzać dostępność portu, odpowiedź HTTP lub wykonanie niestandardowego polecenia. W przypadku trzech kolejnych nieudanych prób, Kubernetes automatycznie restartuje kontener.

Mechanizmy ochrony muszą być zabezpieczone przed sytuacją, w której watchdog sam ulega awarii. Dlatego w krytycznych systemach stosuje się parę watchdogów – jeden monitoruje aplikację, a drugi monitoruje pierwszego. Jest to znane jako „two-dog problem” i znajduje zastosowanie w systemach lotniczych i medycznych.

18/50
Sygnały życia
To podstawa systemów klastrowych, pozwalająca na szybkie, oparte na faktach podejmowanie decyzji o wykluczeniu uszkodzonego elementu.
  • Heartbeat to sieć małych sygnałów („bicie serca”) wymienianych między węzłami klastra.
  • Każdy węzeł co sekundę mówi pozostałym: „Nadal tu jestem i działam”.
  • Brak sygnału oznacza awarię i uruchamia proces failover.
  • Aby unikać błędnych decyzji wywołanych chwilową zadyszką sieci, heartbeat powinien mieć własne, dedykowane łącze lub korzystać z kilku niezależnych ścieżek komunikacji.
Ilustracja dla slajdu 18

W klastrach wysokiej dostępności sygnały życia są wymieniane przez dedykowany interfejs sieciowy, często na osobnym VLAN-ie, aby uniknąć interferencji z ruchem produkcyjnym. Interwał heartbeat (zwykle 1–3 sekundy) musi być dostosowany do charakterystyki sieci i wymagań czasowych failoveru. Zbyt częste sygnały mogą generować niepotrzebny ruch, zbyt rzadkie – opóźniać wykrycie awarii.

Problem „split-brain” (rozszczepienia mózgu) występuje, gdy w wyniku awarii sieci obie strony klastra uznają się za lidera i zaczynają niezależnie przetwarzać dane. Rozwiązaniem jest zastosowanie mechanizmu kworum (quorum), który wymaga większości węzłów do podjęcia decyzji. Narzędzia takie jak Corosync i Pacemaker implementują zaawansowane algorytmy kworum.

W systemach rozproszonych (Cassandra, ZooKeeper, etcd) heartbeat jest integralną częścią protokołu konsensusu (Raft, Paxos). Węzły wymieniają się informacjami o stanie w ramach procesu wyboru lidera (leader election). Transakcje są zatwierdzane tylko po uzyskaniu zgody kworum węzłów, co zapewnia spójność nawet w przypadku awarii części klastra.

19/50
Klastrowanie
  • Klaster to grupa serwerów współpracujących jako jedna jednostka.
  • Klastry HA (High Availability) chronią przed awariami.
  • Klastry Load Balancing rozdzielają pracę dla wydajności.
  • Klastry obliczeniowe (HPC) łączą moc do ciężkich zadań.
  • Zaletą klastrowania jest to, że administrator zarządza całą grupą, a systemy potrafią same wykrywać brakujące węzły i balansować obciążenie tak, by strata jednej maszyny nie była odczuwalna dla aplikacji.
  • To najwyższy stopień organizacji infrastruktury technicznej.
Ilustracja dla slajdu 19

Klastry HA wymagają zarządzania stanem klastra za pomocą dedykowanego oprogramowania. Pacemaker z Corosync to jedna z najpopularniejszych par dla klastrów Linux, umożliwiająca skonfigurowanie zasad failoveru dla usług takich jak baza danych, serwer plików czy maszyny wirtualne. Pacemaker używa języka reguł (Constraint Language) do definiowania zależności i priorytetów między zasobami.

W klastrach obliczeniowych (HPC) stosuje się schedulery takie jak SLURM czy PBS, które zarządzają kolejkami zadań i przydzielają zasoby obliczeniowe. Różnica między klastrem HA a HPC polega na tym, że HA skupia się na dostępności usług, podczas gdy HPC koncentruje się na maksymalizacji mocy obliczeniowej dla zadań wsadowych.

Klastrowanie w chmurze często przyjmuje formę „managed Kubernetes cluster”, gdzie warstwa sterowania (control plane) jest zarządzana przez dostawcę. Eliminuje to konieczność konfiguracji własnego klastra etcd i API server, ale ogranicza kontrolę nad konfiguracją niskopoziomowych parametrów sieciowych i storage'u.

20/50
HA w środowiskach kontenerowych
  • Orkiestratory takie jak Kubernetes automatyzują wysoką dostępność.
  • Obiekt ReplicaSet pilnuje, by zawsze działała zadana liczba kopii aplikacji.
  • Jeśli kontener padnie, Kubernetes natychmiast uruchamia nowy na innym węźle.
  • Zdrowie kontenerów sprawdzają „proby” (liveness i readiness probes).
  • Dzięki temu system sam się naprawia (self-healing).
  • Cała infrastruktura serwerowa (węzły) jest schowana za systemem abstrakcji, co pozwala administratorowi skupić się na deklarowaniu stanu docelowego (np. „chcę 5 instancji”), a nie na ręcznej naprawie każdej z nich.
Ilustracja dla slajdu 20

W Docker Swarm i Kubernetes wysoka dostępność jest osiągana poprzez deklaratywne zarządzanie stanem (declarative state management). Administrator definiuje pożądany stan w plikach YAML, a orkiestrator nieustannie pracuje nad jego osiągnięciem. Jeśli kontener ulegnie awarii, orkiestrator automatycznie tworzy nowy, aby przywrócić zdefiniowaną liczbę replik.

Proby (probes) w Kubernetes dzielą się na trzy typy: liveness (czy kontener żyje), readiness (czy kontener jest gotów przyjmować ruch) i startup (czy kontener wystartował). Readiness probes są szczególnie ważne podczas skalowania – nowy kontener jest dodawany do puli load balancera dopiero po zgłoszeniu gotowości. Zapobiega to kierowaniu ruchu na nie w pełni zainicjalizowane instancje.

W środowiskach kontenerowych istotną rolę odgrywa polityka anty-afinitetu (pod anti-affinity), która zapewnia, że repliki tej samej usługi są rozkładane na różnych węzłach fizycznych. Dzięki temu awaria pojedynczego serwera nie eliminuje wszystkich instancji danej usługi. Topology spread constraints pozwalają na rozłożenie podów między strefy dostępności.

21/50
Kubernetes i wysoka dostępność
  • W pełni wysokodostępny klaster Kubernetes wymaga redundancji warstwy sterującej (control plane – minimum 3 bazy etcd i serwery API).
  • Węzły robocze (workers) powinny być rozproszone w różnych strefach dostępności (Availability Zones).
  • Jeśli zniknie cała strefa w chmurze (np. awaria centrum danych w Irlandii), Kubernetes automatycznie przeniesie kluczowe usługi do działającej strefy w Niemczech.
  • To podejście natywne dla chmury, gdzie odporność na awarie jest wpisana w samą strukturę systemu orkiestracji.
Ilustracja dla slajdu 21

Wysokodostępny control plane w Kubernetes wymaga co najmniej trzech instancji etcd, API Server, Controller Manager i Scheduler rozmieszczonych na różnych węzłach. Etcd, jako rozproszona baza klucz-wartość oparta na protokole Raft, musi mieć nieparzystą liczbę członków (3, 5, 7) dla zapewnienia kworum. Strata kworum oznacza brak możliwości zapisu do klastra.

Węzły robocze (worker nodes) powinny być rozproszone w różnych strefach dostępności (availability zones) w chmurze. Kubernetes natywnie wspiera topology-aware routing, który pozwala na priorytetyzację ruchu wewnątrz tej samej strefy dla zminimalizowania opóźnień. Klaster HA powinien działać na co najmniej trzech strefach dostępności.

Narzędzia takie jak kubeadm, Kubespray i Kops automatyzują tworzenie wysokodostępnych klastrów Kubernetes. W chmurze AWS usługa EKS zarządza control plane za nas, podczas gdy w rozwiązaniach on-premise konieczne jest samodzielne skonfigurowanie równoważenia obciążenia dla API servera oraz zapewnienie redundantnych połączeń sieciowych dla etcd.

22/50
Zarządzanie stanem (StatefulSets)
  • Bazy danych w kontenerach wymagają obiektów StatefulSet.
  • Zapewniają one stabilne identyfikatory (np. baza-0, baza-1) i stałe dyski (Persistent Volumes).
  • Dyski te „wędrują” za kontenerem – jeśli baza zostanie zrekonstruowana na innym serwerze, ten serwer automatycznie podłączy jej stary dysk z danymi.
  • StatefulSets gwarantują też kolejność uruchamiania i wyłączania, co jest niezbędne w klastrach bazodanowych, gdzie kolejność ma znaczenie dla poprawności replikacji i uniknięcia uszkodzenia bazy.
Ilustracja dla slajdu 22

StatefulSet różni się od Deployment tym, że gwarantuje unikalność i stałość tożsamości każdego poda. Każda replika ma własną nazwę (np. mysql-0, mysql-1) i przypisany do niej PersistentVolumeClaim, który nie jest usuwany wraz z podem. Dzięki temu po restarcie kontener zachowuje swoje dane i otrzymuje ten sam adres DNS.

StatefulSets są niezbędne dla baz danych w Kubernetes (MySQL, PostgreSQL, MongoDB), ale wymagają ostrożnego zarządzania operacjami takimi jak skalowanie i aktualizacje. Domyślnie pody w StatefulSet są aktualizowane sekwencyjnie (od najwyższego indeksu do najniższego), co pozwala na zachowanie spójności w klastrach bazodanowych.

Backup StatefulSets wymaga użycia narzędzi takich jak Velero (dawniej Heptio Ark) lub Stash, które wykonują snapshoty PersistentVolume i przechowują je w zewnętrznym magazynie (S3, GCS). Przywrócenie z backupu wymaga odtworzenia zarówno danych, jak i konfiguracji StatefulSet, co może być skomplikowane przy złożonych zależnościach między usługami.

23/50
Skonfigurowanie HA dla usług krytycznych
  • Dla usług krytycznych HA musi być holistyczne.
  • Redundancja musi dotyczyć każdego ogniwa: prądu, sieci, serwerów (load balancery), bazy danych i logiki.
  • Nawet najlepszy klaster padnie, jeśli ma tylko jedną bramę wyjściową do Internetu.
  • Każdy element musi mieć co najmniej jeden zapas (zasada mechanizmu 1+1).
  • Niezbędne jest też monitorowanie samego mechanizmu HA – musimy wiedzieć, kiedy zapasowy serwer przestaje działać, by nie obudzić się w sytuacji, w której „zapas nie zadziałał, gdy był potrzebny”.
Ilustracja dla slajdu 23

Proces konfiguracji HA dla usług krytycznych zaczyna się od analizy BIA (Business Impact Analysis), która określa maksymalny akceptowalny czas przestoju (MAO) i wpływ finansowy każdej godziny niedostępności. Na podstawie tych danych definiuje się RTO i RPO dla każdej usługi. Dopiero potem można dobrać odpowiednie technologie i architekturę.

Krytyczne usługi powinny być objęte automatycznymi testami chaos engineering, które celowo wprowadzają awarie w kontrolowanym środowisku. Narzędzia takie jak Chaos Monkey (Netflix), Gremlin czy Litmus sprawdzają, czy mechanizmy HA faktycznie reagują zgodnie z oczekiwaniami. Testy te powinny być przeprowadzane regularnie, najlepiej w godzinach pracy, aby zespół mógł natychmiast reagować na problemy.

Dokumentacja konfiguracji HA musi być przechowywana w systemie kontroli wersji (Git) i regularnie aktualizowana. Playbooki awaryjne (runbooks) powinny zawierać dokładne instrukcje krok po kroku, łącznie z poleceniami do wykonania i zrzutami ekranu. Każda zmiana infrastruktury powinna być odzwierciedlona w aktualizacji dokumentacji.

24/50
Eliminacja pojedynczych punktów awarii (SPOF)
Identyfikacja i usuwanie SPOF-ów to podstawa inżynierii HA.
To proces ciągły, bo nowe funkcje czy zmiany w infrastrukturze często wprowadzają ukryte SPOF-y, które trzeba proaktywnie eliminować na etapie projektowania.
  • Analizujemy ścieżkę od zasilacza w serwerze, przez kable sieciowe, switch, firewall, aż po dostawcę domeny.
  • Jeśli awaria JEDNEGO elementu kładzie CAŁY system – to jest SPOF.
  • Usuwamy go przez dublowanie (np. dwa zasilacze, dwa kable do różnych switchy, dwie niezależne bazy danych).
Ilustracja dla slajdu 24

Identyfikacja SPOF wymaga przeprowadzenia analizy zależności między wszystkimi komponentami systemu. Każda ścieżka krytyczna – od momentu wejścia żądania do systemu aż do zwrócenia odpowiedzi – musi być przeanalizowana pod kątem pojedynczych elementów, których awaria przerwie cały przepływ. Narzędzia takie jak Graphviz czy draw.io pomagają wizualizować te zależności w formie diagramów.

W praktyce wiele SPOF-ów znajduje się na poziomie infrastruktury fizycznej: pojedynczy zasilacz UPS, jeden switch szkieletowy, jedno łącze internetowe. Redundancja na tym poziomie wymaga podwójnych urządzeń z osobnym zasilaniem i niezależnymi łączami światłowodowymi. Wirtualizacja i chmura publiczna eliminują część tych problemów, ale wprowadzają nowe SPOF-y, takie jak pojedynczy region chmurowy.

Często pomijanym SPOF-em jest człowiek – administrator z dostępem do wszystkich systemów. Wdrożenie zasady „czterech oczu” (four-eyes principle) i podziału obowiązków (segregation of duties) zapobiega sytuacji, w której odejście kluczowego pracownika paraliżuje operacje IT. Systemy zarządzania hasłami (password vaults) minimalizują to ryzyko.

25/50
Analiza odporności systemu
  • Analiza odporności to sprawdzanie scenariuszy: „Co jeśli?”.
  • Używa się metod takich jak FMEA (Failure Mode and Effects Analysis) do systematycznego spisywania zagrożeń i oceny ich skutków.
  • Wynik to mapa ryzyka, która mówi, gdzie system jest najsłabszy.
  • Taka analiza pozwala świadomie decydować: czy inwestujemy w drugi zapasowy zasilacz, czy akceptujemy ryzyko na tym poziomie.
  • Odporność to nie brak awarii, ale świadome zarządzanie konsekwencjami ich wystąpienia i minimalizacja strat dla biznesu.
Ilustracja dla slajdu 25

FMEA (Failure Mode and Effects Analysis) to systematyczna metoda polegająca na identyfikacji wszystkich możliwych trybów awarii każdego komponentu systemu i ocenie ich wpływu na całość. Każdy tryb awarii otrzymuje ocenę w trzech kategoriach: dotkliwość (severity), prawdopodobieństwo wystąpienia (occurrence) i wykrywalność (detection). Iloczyn tych trzech wartości tworzy liczbę priorytetową RPN (Risk Priority Number).

Testy chaos engineering (Netflix Chaos Monkey, Chaos Kong, AWS Fault Injection Simulator) idą o krok dalej niż teoretyczna analiza. Polegają na celowym wprowadzaniu awarii w środowisku produkcyjnym (lub stagingowym) w kontrolowany sposób. Przykłady to zabijanie procesów, odłączanie sieci czy przeciążenie CPU.

Ważnym aspektem analizy odporności jest testowanie degradacji zależności zewnętrznych. Jeśli system korzysta z zewnętrznego API płatności, należy sprawdzić, jak zachowuje się, gdy API zwraca błędy, działa wolno lub jest całkowicie niedostępne. Implementacja stubów i mocków na poziomie integracji pozwala na bezpieczne testowanie tych scenariuszy.

26/50
Testy obciążeniowe
  • Testy obciążeniowe sprawdzają, czy system wytrzyma zakładany ruch (np. 10 000 użytkowników naraz).
  • Pozwalają znaleźć „wąskie gardła” (bottlenecks) – elementy, które pierwsze spowalniają pracę.
  • To jak testowanie mostu pod ciężkim transportem.
  • Testy te są niezbędne przed dużymi wydarzeniami (kampanie, premiery).
  • Pozwalają określić limit systemu, sprawdzić stabilność bazy danych oraz zweryfikować, czy automatyczne skalowanie (auto-scaling) faktycznie dodaje nowe serwery w odpowiednim czasie, zanim system zacznie odrzucać żądania.
Ilustracja dla slajdu 26

Narzędzia do testów obciążeniowych, takie jak Apache JMeter, Gatling, k6 czy Locust, pozwalają na symulację tysięcy wirtualnych użytkowników wykonujących scenariusze biznesowe. Każde z tych narzędzi ma inne możliwości – JMeter jest bogaty w protokoły, Gatling oferuje wydajną symulację w Scali, k6 integruje się z ekosystemem JavaScript, a Locust umożliwia definiowanie scenariuszy w Pythonie.

Podczas testów obciążeniowych kluczowe jest monitorowanie metryk po stronie serwera (CPU, RAM, I/O, połączenia sieciowe) oraz po stronie aplikacji (czas odpowiedzi, liczba błędów, przepustowość). Wąskie gardła często ujawniają się w nieoczekiwanych miejscach – na przykład w limitach puli połączeń do bazy danych czy rozmiarze kolejki wątków.

Wyniki testów obciążeniowych powinny być przechowywane w formie historycznej, aby umożliwić porównanie wydajności między kolejnymi wersjami aplikacji. Automatyzacja testów w procesie CI/CD pozwala na wykrycie regresji wydajności natychmiast po wprowadzeniu zmiany, zanim trafi ona na produkcję.

27/50
Testy przeciążeniowe
  • Stress testing idzie o krok dalej – celowo „łamie” system.
  • Sprawdzamy, co się stanie po przekroczeniu granic wytrzymałości (np. 10-krotny ruch).
  • Celem jest upewnienie się, że system „umiera z godnością" – czyli nie gubi danych, nie psuje bazy i, co najważniejsze, potrafi sam wrócić do pracy, gdy obciążenie spadnie.
  • To kluczowe, by uniknąć sytuacji „śmierci kaskadowej”, gdy jedna awaria trwale uszkadza system tak, że wymaga on ręcznej interwencji administratora przez wiele godzin.
Ilustracja dla slajdu 27

Stress testy często ujawniają problemy związane z wyciekami pamięci (memory leaks), które w normalnych warunkach są niezauważalne, ale pod ekstremalnym obciążeniem prowadzą do wyczerpania zasobów i awarii systemu. Profilowanie pamięci za pomocą narzędzi takich jak Valgrind, YourKit czy VisualVM pomaga zidentyfikować obiekty, które nie są prawidłowo usuwane przez garbage collector.

Ważnym aspektem testów przeciążeniowych jest sprawdzenie zachowania systemu po ustąpieniu obciążenia. System powinien powrócić do normalnego stanu, zwolnić wszystkie zasoby i być gotowy na kolejne zapytania. Jeśli po teście pozostają otwarte połączenia sieciowe lub niezwolnione blokady w bazie danych, oznacza to błąd w zarządzaniu zasobami.

Testy przeciążeniowe powinny dotyczyć również warstwy sieciowej i wejściowej (API gateway, load balancer). Należy sprawdzić, czy rate limiting i throttling działają poprawnie przy przekroczeniu limitów. System powinien odrzucać nadmiarowe żądania z odpowiednim kodem HTTP (429 Too Many Requests) i komunikatem informującym o czasie oczekiwania.

28/50
Testy wydajności
  • Load testing skupia się na mierzalnych celach (SLO).
  • Sprawdzamy, czy pod typowym ruchem czas odpowiedzi (latency) mieści się w normie (np. 500 ms).
  • To pozwala na planowanie zasobów (capacity planning) – wiemy, że 1 serwer uciągnie 200 osób, więc dla 1000 osób potrzebujemy 5 serwerów.
  • Regularne testy wydajności po każdej zmianie w kodzie chronią przed „regresją wydajności”, gdy drobna poprawka dewelopera nagle 3-krotnie spowalnia działanie całego serwisu, co na produkcji przy dużym ruchu kończy się awarią.
Ilustracja dla slajdu 28

Testy wydajnościowe powinny być powtarzalne i izolowane od czynników zewnętrznych. Oznacza to konieczność wykonywania ich na dedykowanym środowisku testowym o stabilnej charakterystyce wydajnościowej. Zmienne takie jak współbieżne obciążenie z innych testów, wahania sieci czy procesy w tle mogą znacząco wpłynąć na wyniki i utrudnić porównanie między testami.

Wyniki testów wydajnościowych są często wyrażane w percentylach: P50 (mediana), P95 (95% żądań szybszych od tej wartości) i P99 (99% żądań). Wartości te dają pełniejszy obraz niż średnia, która może być wypaczona przez pojedyncze długie żądania (outliers). Cel SLO często definiuje się jako P99 poniżej określonego progu.

Capacity planning na podstawie testów wydajnościowych pozwala na przewidywanie, kiedy system osiągnie swoje limity i wymaga skalowania. Wykorzystuje się do tego modele matematyczne, takie jak prawo Little'a (zależność między liczbą żądań w systemie, przepustowością i czasem odpowiedzi) lub analizę szeregów czasowych.

29/50
Benchmarking
  • Benchmarking to porównywanie wyników z innymi.
  • Sprawdzamy, czy nasza baza danych działa tak szybko, jak podaje producent, lub czy nowa wersja PHP faktycznie przyspieszyła nasz kod.
  • To pomaga podjąć decyzje biznesowe: „Czy opłaca się wydać 1000 zł więcej na serwer?”.
  • Bez benchmarków działamy w ciemno, opierając się na marketingu dostawców.
  • Rzetelne porównanie różnych typów maszyn wirtualnych czy różnych systemów bazodanowych pozwala na gigantyczne oszczędności przy zachowaniu nienagannej wydajności usług.
Ilustracja dla slajdu 29

W przypadku baz danych benchmarking jest często wykonywany przy użyciu standardowych zestawów testów, takich jak TPC-C (transakcje), TPC-H (zapytania analityczne) czy YCSB (NoSQL). Wyniki tych testów pozwalają na obiektywne porównanie różnych silników bazodanowych w kontrolowanych warunkach. Rzeczywisty profil obciążenia rzadko jednak odpowiada idealnym parametrom testów benchmarkowych.

W kontekście aplikacji webowych benchmarki często mierzą przepustowość (requests per second) i opóźnienie przy różnych rozmiarach payloadu. Web frameworki regularnie publikują benchmarki porównujące wydajność (TechEmpower Web Framework Benchmarks), które pomagają w wyborze odpowiedniego stosu technologicznego. Wyniki te należy traktować z ostrożnością.

Benchmarking infrastruktury chmurowej (porównanie typów instancji EC2, maszyn wirtualnych Azure) powinien uwzględniać nie tylko cenę, ale także stabilność wydajności w czasie (performance consistency). Niektóre typy instancji wykorzystują model burst CPU, gdzie wydajność może spaść po wyczerpaniu kredytów CPU.

30/50
Automatyczne skalowanie
  • Auto-scaling to „magia” chmury.
  • System sam dodaje serwery, gdy obciążenie CPU przekroczy np. 70%, i sam je usuwa, gdy ludzie wyjdą z pracy i ruch spadnie.
  • To zapewnia elastyczność (usługa nie „padnie” pod nagłym ruchem) i oszczędność (nie płacimy za serwery, które stoją puste w nocy).
  • Konfiguracja wymaga ustalenia progów i limitów (min/max instancji), aby uniknąć „puchnięcia” rachunków przy ataku DDoS lub gwałtownego wyłączania serwerów przy chwilowym spadku metryk.
Ilustracja dla slajdu 30

Auto-scaling może być oparty na różnych metrykach: zużycie CPU, pamięci, liczbie żądań na sekundę (RPS), długości kolejki SQS w AWS czy niestandardowych metrykach aplikacyjnych. Wybór odpowiedniej metryki jest kluczowy – skalowanie wyłącznie na podstawie CPU może nie odzwierciedlać rzeczywistego obciążenia aplikacji, szczególnie w przypadku zadań związanych z operacjami wejścia-wyjścia.

Progi skalowania (thresholds) muszą być starannie dobrane, aby uniknąć efektu „flapping” – częstego dodawania i usuwania serwerów w krótkim czasie (thrashing). W tym celu stosuje się okresy wygrzewania (cooldown periods) i histerezę (różnica między progiem dodawania a usuwania). W AWS Auto Scaling Groups parametr cooldown zapobiega dodawaniu kolejnych instancji zbyt szybko.

Predykcyjne skalowanie (predictive auto-scaling) wykorzystuje uczenie maszynowe do analizy historycznych wzorców ruchu i przewidywania przyszłego zapotrzebowania. AWS Predictive Scaling i Google Cloud Autoscaler z machine learningiem pozwalają na proaktywne dodawanie zasobów, zanim nastąpi skok obciążenia. Jest to szczególnie przydatne przy sezonowych wzrostach ruchu.

31/50
Skalowanie Podów (HPA)
  • Horizontal Pod Autoscaler (HPA) to auto-scaler wewnątrz Kubernetesa.
  • Monitoruje on użycie zasobów (CPU/RAM) przez kontenery i dynamicznie zmienia liczbę replik.
  • Jeśli np. promocja w sklepie generuje gigantyczny ruch, HPA w sekundę zwiększy liczbę kontenerów z 10 do 50, rozkładając obciążenie.
  • To pozwala na błyskawiczną reakcję na trendy, której człowiek nie byłby w stanie wykonać ręcznie.
  • HPA umożliwia też skalowanie w oparciu o niestandardowe metryki, np. liczbę oczekujących wiadomości w kolejce.
Ilustracja dla slajdu 31

Horizontal Pod Autoscaler może skalować nie tylko na podstawie CPU i pamięci, ale także na podstawie niestandardowych metryk (custom metrics) i zewnętrznych metryk (external metrics). Custom metrics API pozwala na udostępnianie własnych metryk aplikacyjnych, takich jak liczba żądań na sekundę czy głębokość kolejki. External metrics API zbiera metryki spoza klastra.

HPA działa cyklicznie, co 15 sekund domyślnie (można zmienić flagą --horizontal-pod-autoscaler-sync-period). Oblicza pożądaną liczbę replik na podstawie wzoru: desiredReplicas = ceil(currentReplicas * currentMetricValue / desiredMetricValue). W przypadku braku stabilizacji metryki, HPA stosuje opóźnienie (stabilization window).

W Kubernetes 1.18+ wprowadzono scaling behavior, który pozwala na kontrolowanie tempa skalowania (stabilization window, policy, selectPolicy). Można skonfigurować szybkie skalowanie w górę (np. podwojenie replik w 30 sekund) i wolniejsze skalowanie w dół (np. maksymalnie 1 replika na minutę). Jest to szczególnie przydatne dla aplikacji z długim czasem uruchamiania.

32/50
Zapasowe centra danych
  • Zapasowe centra danych (DR Site) to najwyższy poziom zabezpieczenia.
  • Hot Site (gorący zapas) to gotowa kopia systemów, działająca równolegle, gotowa przejąć ruch w milisekundy.
  • Warm Site (ciepły zapas) ma gotowy sprzęt i dane, ale wymaga chwili na uruchomienie aplikacji.
  • Cold Site (zimny zapas) to tylko pusta hala z prądem – najtańszy, ale przywrócenie usług zajmie tygodnie.
  • Wybór zależy od tego, ile firma straci w 1 dzień braku działania (analiza BIA - Business Impact Analysis).
Ilustracja dla slajdu 32

Wybór lokalizacji zapasowego centrum danych jest krytyczny – musi ono znajdować się w odległości co najmniej 100–200 km od centrum głównego, aby uniknąć tych samych katastrof naturalnych (powodzie, huragany, trzęsienia ziemi). Jednocześnie odległość nie może być zbyt duża, aby opóźnienia sieciowe nie uniemożliwiały replikacji. W chmurze strefy dostępności w jednym regionie są oddalone o kilkadziesiąt kilometrów.

Koszty utrzymania zapasowego centrum danych zależą od jego typu: Hot Site to nawet 100% kosztów centrum głównego, Warm Site około 50–70%, a Cold Site około 20–30%. W chmurze publicznej koszty DR można znacząco obniżyć, utrzymując infrastrukturę w formie kodu (Terraform, CloudFormation) i uruchamiając ją tylko wtedy, gdy jest potrzebna.

Testowanie procedur DR powinno być przeprowadzane co najmniej raz w roku, z pełnym przełączeniem ruchu na zapasowe centrum danych. Testy te nazywane są „DR drills” i obejmują nie tylko techniczne przełączenie, ale także weryfikację procesów operacyjnych i biznesowych.

33/50
Odzyskiwanie po katastrofie (Disaster Recovery)
  • Disaster Recovery (DR) to plan na „koniec świata” (pożar, wojna, paraliż regionu).
  • To nie tylko technika, ale procedury: kto ma klucze, kto zna hasła, jak powiadomić pracowników.
  • Plan DR musi być spisany na papierze i regularnie testowany.
  • Bez testu plan DR to tylko bajka – zazwyczaj okazuje się, że backupy są nieczytelne, nikt nie pamięta hasła do vaulta, a serwery zapasowe nie mają prądu.
  • Prawidłowy proces DR to gwarancja przetrwania firmy w ekstremalnie trudnych warunkach rynkowych i losowych.
Ilustracja dla slajdu 33

Plan DR powinien zawierać dokładnie zdefiniowane role i obowiązki członków zespołu odpowiedzialnego za odzyskiwanie (Incident Response Team). Każda osoba musi wiedzieć, co robić, w jakiej kolejności i z kim się komunikować. W planie znajduje się również lista kontaktów awaryjnych (escalation list), łącznie z numerami telefonów do dostawców usług zewnętrznych.

Automatyzacja DR jest kluczowa dla skrócenia RTO. Narzędzia takie jak AWS Systems Manager Automation, Azure Site Recovery czy Google Cloud Disaster Recovery pozwalają na definiowanie zautomatyzowanych runbooków, które wykonują sekwencje działań w odpowiedzi na zdarzenia. Automatyzacja eliminuje ryzyko błędu ludzkiego podczas stresującego procesu odzyskiwania.

Po każdej katastrofie (nawet jeśli została pomyślnie zażegnana) należy przeprowadzić „post-mortem” (analizę powłamaniową). Dokument ten opisuje, co się wydarzyło, jakie były przyczyny, jak zareagował zespół i co można poprawić na przyszłość. Kultura blameless post-mortem zachęca do uczciwego raportowania błędów.

34/50
Parametry RTO i RPO
  • RTO (Recovery Time Objective) to czas, w jakim musimy odzyskać działanie (np. „musimy wstać w 2h”).
  • RPO (Recovery Point Objective) to data ostatnich danych, które możemy stracić (np. „możemy stracić dane z ostatnich 15 min”).
  • Te dwa parametry dyktują cenę systemu – system z RTO i RPO bliskim zeru kosztuje fortunę, bo wymaga ciągłej, synchronicznej replikacji danych między kontynentami.
  • Biznes musi zdecydować, na ile danych i czasu przestoju może sobie pozwolić przed bankructwem.
Ilustracja dla slajdu 34

RTO i RPO są często definiowane w umowach SLA i mają bezpośrednie przełożenie na architekturę techniczną systemu. Dla banków RTO wynosi często poniżej 15 minut, a RPO poniżej 1 minuty, co wymaga replikacji synchronicznej między centrami danych i automatycznego failoveru. Dla mniej krytycznych systemów RTO 4 godziny i RPO 1 godzina mogą być akceptowalne.

Zależność między RTO a kosztami jest wykładnicza – skrócenie RTO z 24 godzin do 4 godzin może podwoić koszty infrastruktury, ale skrócenie z 1 godziny do 5 minut może je zwiększyć dziesięciokrotnie. Wynika to z konieczności stosowania coraz bardziej zaawansowanych technologii: od backupów taśmowych, przez replikację dyskową, po synchroniczną replikację.

W praktyce często stosuje się różne RTO i RPO dla różnych warstw systemu. Warstwa aplikacji (bezstanowa) może mieć RTO 5 minut i RPO 0, podczas gdy warstwa bazy danych może mieć RTO 1 godzina i RPO 15 minut. Hierarchia priorytetów pozwala na optymalizację kosztów przy zachowaniu akceptowalnego poziomu ryzyka.

35/50
Strategie odzyskiwania (Disaster Recovery)
  • Różne sytuacje wymagają różnych reakcji.
  • Najprostsza to „Backup and Restore” (odzyskaj z taśmy/dysku).
  • Szybsza to „Pilot Light” – baza danych replikuje się na żywo, ale serwery aplikacji są wyłączone.
  • Jeszcze szybsza to „Warm Standby” (serwery działają na minimum).
  • Najdroższa to „Multi-Site Active-Active” – wszystko działa naraz w dwóch miejscach.
  • Wybór strategii to kompromis między kosztem utrzymania pustej infrastruktury a potencjalnymi stratami wynikającymi z długiego czasu naprawy (downtime).
Ilustracja dla slajdu 35

Strategia „Pilot Light” polega na utrzymywaniu w zapasowym centrum danych minimalnej konfiguracji: uruchomionej bazy danych (z replikacją), ale wyłączonych serwerów aplikacji. W przypadku awarii serwery aplikacji są uruchamiane z obrazów AMI lub snapshotów, co trwa zwykle 10–30 minut. Ta strategia oferuje dobry balans między kosztem a RTO.

„Warm Standby” to strategia, w której zapasowe centrum danych ma uruchomioną minimalną liczbę serwerów aplikacji i baz danych, ale na mniejszych instancjach. Ruch produkcyjny jest kierowany do centrum głównego, ale zapasowe centrum jest gotowe na skalowanie w górę w razie awarii. Koszty są wyższe niż Pilot Light, ale RTO jest krótsze.

„Multi-site Active-Active” to najdroższa, ale najbardziej niezawodna strategia. Ruch jest rozdzielany między dwa lub więcej centrów danych, które jednocześnie obsługują żądania użytkowników. Wymaga to zaawansowanego DNS (global load balancing) i rozwiązań do synchronizacji danych. RTO wynosi zero, a RPO może być bliskie zeru przy replikacji synchronicznej.

36/50
Kopia zapasowa i odtwarzanie
  • Backup to „świętość”.
  • Zasada 3-2-1: 3 kopie danych, na 2 różnych nośnikach, 1 kopia w innej lokalizacji (poza biurem/chmurą).
  • Kopia to nie tylko pliki, ale i obrazy całych serwerów (Snapshots).
  • Najważniejsze to regularne TESTOWANIE odtwarzania.
  • Administrator, który nie testuje backupów, tylko „wierzy”, że one działają.
  • W dobie Ransomware (wyłudzeń danych), offline backup (odcięty od sieci) to jedyna pewna metoda na odzyskanie firmy po ataku hakerskim, który usuwa wszystkie dane online.
Ilustracja dla slajdu 36

Rodzaje backupów dzielą się na pełne (full backup), przyrostowe (incremental backup) i różnicowe (differential backup). Pełny backup zawiera wszystkie dane i jest podstawą do odtworzenia, ale zajmuje najwięcej miejsca i czasu. Backup przyrostowy zapisuje tylko zmiany od ostatniego backupu (dowolnego typu), a różnicowy od ostatniego pełnego backupu.

Zasada „3-2-1-1-0” to rozszerzenie klasycznej zasady 3-2-1: co najmniej 3 kopie danych, na co najmniej 2 różnych nośnikach, 1 kopia w innej lokalizacji, 1 kopia offline (air-gapped) i 0 błędów podczas testów przywracania. Kopia offline jest ostatnią linią obrony przed ransomware.

Narzędzia do backupu w środowiskach kontenerowych, takie jak Velero (dla Kubernetes) lub Kasten K10, oferują możliwość backupu nie tylko danych, ale także konfiguracji klastra (namespace, deployment, configmap, secret). Umożliwiają one migrację klastra do innego regionu przez proste przywrócenie backupu.

37/50
Replikacja między centrami danych
Kluczowym ograniczeniem jest tu prędkość światła – im dalej centra od siebie, tym większe opóźnienie (latency).
  • Aby chronić dane przed katastrofą lokalną, musimy je replikować między centrami danych (DC).
  • Replikacja może być na poziomie macierzy (storage), bazy danych lub aplikacji.
  • To wymusza stosowanie replikacji asynchronicznej (z pewnym opóźnieniem zapisu na zapasie), co oznacza ryzyko utraty kilku sekund danych w przypadku nagłej awarii łącza lub całego centrum głównego.
Ilustracja dla slajdu 37

Replikacja między centrami danych może odbywać się na kilku poziomach: storage (blokowy – SAN/NAS), bazy danych (log shipping, stream replication) lub aplikacji (dual-writes). Każdy poziom ma inne charakterystyki – replikacja storage'u jest przezroczysta dla aplikacji, ale nie radzi sobie z logiką spójności transakcyjnej. Replikacja aplikacji oferuje największą kontrolę, ale wymaga modyfikacji kodu.

Opóźnienia sieciowe (latency) między centrami danych są głównym ograniczeniem replikacji synchronicznej. Dla odległości 1000 km minimalne opóźnienie wynosi około 10 ms (zgodnie z prędkością światła w światłowodzie). Każda transakcja zapisu musi czekać na potwierdzenie z drugiego centrum, co przy dużej liczbie zapisów obniża przepustowość.

W AWS replikacja międzyregionowa jest realizowana za pomocą usług takich jak DynamoDB Global Tables, Aurora Global Database, S3 Cross-Region Replication czy RDS Cross-Region Read Replicas. Każda z tych usług ma różne charakterystyki RPO (od kilku sekund do kilku minut) i różną konfigurację kosztów.

38/50
Monitorowanie pod kątem wysokiej dostępności
  • W HA monitorujemy nie tylko czy serwer „żyje” (ping), ale czy usługa spełnia swoje zadanie.
  • Monitorujemy zdrowie replikacji (replication lag), stan mechanizmów heartbeat i logi błędów load balancera.
  • System monitoringu musi sam być wysokodostępny – jeśli padnie monitoring, administrator staje się „ślepy”.
  • Kluczowe jest wczesne wykrywanie trendów (np. kończąca się pamięć), by zdążyć z interwencją, zanim mechanizm failover będzie musiał zadziałać, co zawsze niesie ze sobą pewne ryzyko chwilowej niestabilności.
Ilustracja dla slajdu 38

Skuteczne monitorowanie HA wymaga implementacji modelu „USE” (Utilization, Saturation, Errors) dla każdego zasobu. Utilization to procent wykorzystania zasobu (np. 70% CPU), Saturation to stopień przeciążenia (np. długość kolejki zadań), Errors to liczba błędów (np. 5xx). Monitorowanie tych trzech wymiarów daje pełny obraz stanu każdego komponentu.

Black-box monitoring (zewnętrzny) symuluje zachowanie prawdziwego użytkownika, wysyłając żądania do systemu z zewnątrz. Narzędzia takie jak Pingdom, Checkly czy syntetyczne testy AWS CloudWatch Synthetic Canaries wykonują okresowe zapytania i mierzą czas odpowiedzi, poprawność treści i dostępność. Ten typ monitoringu wykrywa problemy, których nie zauważy monitoring wewnętrzny.

White-box monitoring (wewnętrzny) opiera się na metrykach eksportowanych przez samą aplikację (Prometheus metrics, statsd). Biblioteki instrumentacyjne (Micrometer dla JVM, OpenTelemetry dla wielu języków) pozwalają na definiowanie własnych metryk biznesowych. Połączenie obu typów monitoringu daje kompleksowy obraz systemu.

39/50
Alerty dostępności usług
Przeładowanie administratorów nieistotnymi alarmami prowadzi do „alert fatigue” – gdy wystąpi prawdziwa awaria, zostanie ona zignorowana jako kolejny błąd konfiguracyjny lub „szum” w systemie monitorowania.
  • Alerty muszą być mądre.
  • Używamy monitoringu zewnętrznego (Black-box), sprawdzającego dostępność strony z Internetu (z różnych miast świata).
  • Alert o niedostępności musi budzić ludzi („Critical Alert”), ale alert o 80% CPU o 3 w nocy powinien tylko zapisać się w logach do analizy rano.
Ilustracja dla slajdu 39

Skuteczny system alarmowy opiera się na hierarchii ważności: P1 (Critical) – usługa niedostępna, natychmiastowa eskalacja do osoby dyżurnej (on-call); P2 (High) – znacząca degradacja, alert w godzinach pracy; P3 (Medium) – ostrzeżenie, ticket dla zespołu; P4 (Low) – informacja, log. Każdy poziom ma zdefiniowany maksymalny czas reakcji.

Aby uniknąć „alert fatigue” (zmęczenia alarmami), stosuje się agregację alertów i deduplikację. Jeśli 100 instancji tej samej usługi przestaje odpowiadać, powinien zostać wysłany jeden alert, a nie 100. Narzędzia takie jak PagerDuty, OpsGenie czy Grafana On-Call oferują wbudowane mechanizmy grupowania i suppression.

Obsługa incydentów powinna być wspierana przez runbooki – procedury krok po kroku, które opisują, jakie działania podjąć w przypadku każdego alertu. Runbooki są przechowywane w systemie zarządzania wiedzą i powinny być regularnie testowane i aktualizowane. Automatyzacja runbooków za pomocą narzędzi takich jak Rundeck pozwala na automatyczne wykonywanie rutynowych czynności naprawczych.

40/50
Wykrywanie degradacji wydajności
  • Degradacja to „cicha śmierć” systemu.
  • Strona niby działa, ale zamiast 1s ładuje się 15s.
  • To wygania klientów szybciej niż brak strony.
  • Systemy monitoringu (np. Prometheus) muszą śledzić percentyle (np. P99), by wykryć te spowolnienia.
  • Analiza anomalii pozwala wykryć problem, zanim usługa całkowicie padnie.
  • Często przyczyną degradacji jest „leaking” (wyciek) zasobów lub zapchanie łączy sieciowych, które narasta powoli, maskując się w średnich statystykach, co daje złudne poczucie bezpieczeństwa u administratora.
Ilustracja dla slajdu 40

Degradacja wydajności często jest spowodowana wyciekami pamięci (memory leaks), które narastają z czasem. Monitorowanie trendów zużycia pamięci (memory trending) pozwala na wczesne wykrycie problemu – jeśli po każdym restarcie pamięć rośnie w sposób systematyczny, a nie osiąga plateau, oznacza to wyciek. Narzędzia APM (Application Performance Monitoring) takie jak New Relic, Datadog czy Dynatrace oferują automatyczne wykrywanie wycieków.

Kolejną częstą przyczyną degradacji są zapytania bazodanowe, które z czasem działają wolniej. „Query regression” może być spowodowana rosnącą ilością danych, brakiem odpowiednich indeksów lub zmianami w planach zapytań. Monitorowanie bazy danych z użyciem pg_stat_statements (PostgreSQL) czy Performance Schema (MySQL) pozwala na identyfikację wolnych zapytań.

Degradacja wydajności na poziomie sieci może być spowodowana błędami konfiguracji routingu, utratą pakietów (packet loss) lub przeciążeniem łącza. Monitorowanie SNMP i NetFlow/IPFIX dostarcza danych o wykorzystaniu pasma i błędach interfejsów sieciowych. Narzędzia takie jak MRTG, Cacti czy PRTG oferują historyczne wykresy trendów wykorzystania sieci.

41/50
Ograniczenie wpływu awarii
  • Mechanizm Circuit Breaker (bezpiecznik) chroni system przed reakcją łańcuchową.
  • Jeśli usługa zewnętrzna (np. płatności) spowalnia, „otwieramy bezpiecznik” i natychmiast zwracamy błąd użytkownikowi, zamiast kazać mu czekać 30s.
  • To ratuje nasze własne serwery przed zablokowaniem wszystkich wątków przez czekanie na coś, co i tak nie działa.
  • Po pewnym czasie „zamykamy bezpiecznik”, by sprawdzić, czy usługa zewnętrzna już ozdrowiała.
  • To kluczowa technika w budowaniu odpornych mikrousług, chroniąca system przed paraliżem kaskadowym.
Ilustracja dla slajdu 41

Wzorzec Bulkhead (przedział hermetyczny) polega na podziale systemu na izolowane grupy zasobów, tak aby awaria jednej grupy nie wpływała na pozostałe. Na przykład pula połączeń do bazy danych dla usługi A jest oddzielona od puli dla usługi B. Jeśli usługa A zacznie przeciążać bazę, nie wpłynie to na dostępność usługi B.

Timeout to najprostszy mechanizm ochronny – każde zewnętrzne wywołanie powinno mieć zdefiniowany maksymalny czas oczekiwania. Wartości timeoutów muszą być dostosowane do charakterystyki usługi: zapytania do bazy danych mogą mieć 5–10 sekund, zapytania do zewnętrznych API 2–3 sekundy, a zapytania do usług wewnętrznych 500 ms. Zbyt długie timeouty maskują problemy.

Rate limiting (ograniczenie tempa) chroni system przed przeciążeniem przez pojedynczego klienta lub adres IP. Implementuje się go na poziomie API Gateway (Kong, AWS API Gateway, Nginx) z użyciem algorytmów takich jak token bucket, leaky bucket czy sliding window. Dane o użyciu limitów są przechowywane w Redis dla szybkiego dostępu.

42/50
Wdrożenia kanarkowe
  • Wdrożenie „kanarkowe” to puszczanie nowej wersji kodu tylko na 1-5% ruchu.
  • Monitoring sprawdza, czy ta mała grupa użytkowników ma błędy.
  • Jeśli „kanarek przeżył” (brak błędów), zwiększamy ruch na nową wersję.
  • To najbezpieczniejsza metoda aktualizacji dużych systemów.
  • Jeśli w nowym kodzie jest błąd, ucierpi tylko garstka osób, a nie wszyscy klienci.
  • Metoda ta pozwala na testowanie nowej logiki biznesowej na „żywym organizmie” przy minimalnym ryzyku dla wizerunku i przychodów firmy.
Ilustracja dla slajdu 42

Wdrożenia kanarkowe wymagają zaawansowanego routowania ruchu na poziomie load balancera lub service mesh. Narzędzia takie jak Flagger (dla Kubernetes), Argo Rollouts czy Istio Virtual Services pozwalają na precyzyjne sterowanie procentem ruchu kierowanego do nowej wersji. Automatyzacja analizy metryk (Prometheus, Datadog) decyduje o promocji lub wycofaniu wdrożenia.

Czas trwania fazy kanarkowej powinien być wystarczająco długi, aby wykryć problemy związane z długotrwałym działaniem (memory leaks, stopniowa degradacja). Zazwyczaj wynosi od kilku minut do kilku godzin. W tym czasie analizowane są metryki takie jak współczynnik błędów (error rate), czas odpowiedzi (latency percentiles) i logi błędów aplikacji.

W przypadku wykrycia problemów podczas wdrożenia kanarkowego, cały ruch jest automatycznie przekierowywany z powrotem do stabilnej wersji (rollback). Proces ten powinien być całkowicie zautomatyzowany, aby zminimalizować czas ekspozycji użytkowników na błędy. Narzędzia CI/CD (Jenkins, GitLab CI, GitHub Actions) wspierają tworzenie potoków z wdrożeniem kanarkowym.

43/50
Wdrożenia niebiesko-zielone
  • Utrzymujemy dwa identyczne środowiska: Niebieskie (produkcja) i Zielone (testy nowej wersji).
  • Gdy Zielone jest gotowe, jednym kliknięciem na load balancerze przełączamy CAŁY ruch na Zielone.
  • Jeśli coś pójdzie nie tak – jednym kliknięciem wracamy na stare Niebieskie (Instant Rollback).
  • To eliminuje stres przy aktualizacjach i zapewnia zerowy czas przestoju (Zero Downtime).
  • Metoda ta wymaga jednak dwukrotnie większej infrastruktury, co podnosi koszty operacyjne, ale drastycznie skraca czas okien serwisowych.
Ilustracja dla slajdu 43

Wdrożenie niebiesko-zielone wymaga utrzymywania dwóch kompletnych środowisk: produkcyjnego (np. niebieskie) i przygotowanego do przejęcia (zielone). Koszt infrastruktury jest podwojony, ale można go zminimalizować poprzez wykorzystanie środowiska zielonego do testów wydajnościowych przed przełączeniem. W chmurze środowiska można włączać tylko na czas testów i przełączania.

Przełączenie ruchu między środowiskami może być realizowane na kilka sposobów: przez zmianę rekordu DNS (z opóźnieniem propagacji), przez aktualizację konfiguracji load balancera (natychmiastowe) lub przez zmianę wag routingu w service mesh. Najszybsze jest przełączenie na poziomie load balancera, które może być wykonane w czasie poniżej sekundy.

W przypadku problemów po przełączeniu na nowe środowisko, rollback (powrót do starej wersji) jest natychmiastowy i bezpieczny, stare środowisko nadal działa. Aby ograniczyć koszty, stare środowisko może być utrzymywane tylko przez ograniczony czas (np. 24–48 godzin), po czym jest wyłączane.

44/50
Aktualizacje kroczące
  • Rolling update to wymienianie serwerów/kontenerów jeden po drugim. Kubernetes wyłącza 1 stary pod, włącza 1 nowy, czeka aż będzie gotowy i przechodzi do następnego.
  • Dzięki temu usługa cały czas działa (z 90% wydajnością podczas procesu).
  • To standard w kontenerach.
  • Jeśli nowy pod nie wstaje (błąd startu), proces jest przerywany, a stara wersja nadal obsługuje ruch.
  • Pozwala to na uniknięcie katastrofalnych awarii przy wdrażaniu błędnego kodu, który uniemożliwia uruchomienie aplikacji (crash looping).
Ilustracja dla slajdu 44

W Kubernetes aktualizacje kroczące są domyślną strategią dla obiektów Deployment. Parametry maxSurge (maksymalna liczba dodatkowych podów w trakcie aktualizacji) i maxUnavailable (maksymalna liczba niedostępnych podów) kontrolują tempo i bezpieczeństwo aktualizacji. Domyślnie maxSurge=25% i maxUnavailable=25%, co oznacza, że podczas aktualizacji może być więcej podów niż docelowo.

Podczas aktualizacji kroczącej Kubernetes sprawdza readiness probe każdego nowego poda przed przejściem do następnego. Jeśli readiness probe zwróci błąd, proces aktualizacji jest wstrzymywany, a nieudany pod jest automatycznie wycofywany. Można również skonfigurować minReadySeconds i progressDeadlineSeconds dla bardziej restrykcyjnej kontroli.

W przypadku wykrycia regresji podczas aktualizacji (np. wzrost wskaźnika błędów), Kubernetes automatycznie wycofuje aktualizację (rollback). Aby to umożliwić, należy pamiętać o przechowywaniu poprzednich wersji (revision history) przez odpowiedni okres. Domyślnie przechowywanych jest 10 poprzednich rewizji.

45/50
Przykład architektury o wysokiej dostępności
  • Idealna architektura: Ruch z Internetu (CDN + Route53) trafia do Load Balancera (ALB), który rozrzuca go na serwery w 3 różnych strefach (AZ).
  • Aplikacje są bezstanowe, a sesję trzymają w klastrze Redis.
  • Dane trafiają do bazy (np. AWS Aurora) rozproszonej w 3 strefach, z automatycznym failoverem.
  • Backupy są replikowane do innego regionu geograficznego.
  • Taki system przeżyje awarię pojedynczego serwera, bazy, a nawet całego wielkiego centrum danych Amazonu, zachowując nienaganną dostępność dla użytkowników końcowych.
Ilustracja dla slajdu 45

Przedstawiona architektura korzysta z AWS jako przykładu, ale podobne rozwiązania istnieją w Azure (Availability Zones, Traffic Manager, Azure SQL) i GCP (Google Cloud Load Balancing, Cloud Spanner, Cloud CDN). Każdy dostawca oferuje analogiczne usługi, często z innymi nazwami, ale podobną funkcjonalnością. Kluczowa jest umiejętność mapowania konceptów między dostawcami.

W architekturze HA krytyczne jest zapewnienie, że żaden pojedynczy komponent nie jest SPOF. Load balancer (ALB) w AWS jest domyślnie wysokodostępny w obrębie regionu. Podobnie Route53 (DNS) jest globalnie rozproszony i odporny na awarie. Baza danych Aurora z Multi-AZ zapewnia automatyczny failover w ciągu 1–2 minut.

Do pełnego obrazu brakuje jeszcze monitorowania (CloudWatch, Prometheus) i systemu alarmowania (SNS, PagerDuty). Wszystkie komponenty powinny być udokumentowane w formie diagramu architektonicznego z zaznaczonymi ścieżkami awaryjnymi. Dokumentacja powinna być przechowywana razem z kodem (diagram as code w repozytorium).

46/50
Planowanie ciągłości działania (BCP)
Dobry plan BCP pozwala firmie przetrwać nawet miesiące chaosu rynkowego, skupiając się na najważniejszych funkcjach życiowych organizacji i stopniowym przywracaniu mniej istotnych procesów w miarę odzyskiwania stabilności.
  • BCP (Business Continuity Planning) to szerszy plan niż techniczne DR.
  • Obejmuje: jak firma ma pracować bez Internetu? Gdzie mają się spotkać pracownicy? Jak zapłacić faktury, gdy system bankowy padnie? To analiza wpływu na biznes (BIA) i procedury awaryjne.
Ilustracja dla slajdu 46

BCP różni się od Disaster Recovery tym, że obejmuje nie tylko IT, ale całą organizację. Business Impact Analysis (BIA) to proces identyfikacji krytycznych funkcji biznesowych i określenia maksymalnego akceptowalnego czasu ich przerwy (MAO). Każda funkcja biznesowa jest oceniana pod kątem wpływu finansowego, operacyjnego i reputacyjnego jej braku.

Plan BCP powinien zawierać procedury komunikacji kryzysowej (crisis communication) – kto, komu i jak przekazuje informacje w trakcie awarii. W dobie mediów społecznościowych i natychmiastowego przepływu informacji, brak komunikacji z klientami w trakcie awarii może być bardziej szkodliwy niż sama awaria. Szablony komunikatów oszczędzają czas w krytycznej sytuacji.

Testowanie BCP powinno obejmować scenariusze takie jak: brak dostępu do biura (pożar, powódź), brak dostępu do Internetu, brak dostępu do systemów IT (ransomware), atak na personel (choroba kluczowych pracowników). Ćwiczenia typu „tabletop” pozwalają na sprawdzenie procedur bez kosztów technicznych.

47/50
Koszty wysokiej dostępności
  • HA nie jest darmowe.
  • Każda kolejna „dziewiątka” (z 99,9% na 99,99%) kosztuje 10x więcej.
  • Wymaga to dublowania sprzętu, licencji, łączy i przede wszystkim czasu drogich ekspertów.
  • Biznes musi wiedzieć: „Czy godzina przestoju kosztuje nas więcej niż utrzymanie zapasowego serwera?”.
  • Często okazuje się, że dla mniejszych firm 99% (3.5 dnia przestoju rocznie) jest akceptowalne, podczas gdy dla banku 99.9% (9h przestoju) to już katastrofa grożąca utratą licencji lub gigantycznymi karami finansowymi.
Ilustracja dla slajdu 47

Koszty HA można podzielić na bezpośrednie (sprzęt, licencje, łącza, prąd) i pośrednie (praca inżynierów, szkolenia, utrzymanie). W modelu chmurowym koszty bezpośrednie są zastąpione opłatami za usługi (pay-as-you-go), co często jest tańsze dla małych i średnich firm. Dla dużych firm własne centra danych mogą być bardziej opłacalne przy odpowiedniej skali.

ROI (Return on Investment) z HA oblicza się, porównując koszt wdrożenia HA z kosztem przestoju. Jeśli godzina przestoju kosztuje firmę 100 000 zł, to inwestycja 500 000 zł w HA (eliminująca 10 godzin przestoju rocznie) zwraca się w ciągu 6 miesięcy. W e-commerce koszt przestoju jest szczególnie wysoki w okresach świątecznych.

Wiele firm stosuje model „tiered HA”, gdzie różne usługi mają różne poziomy HA w zależności od krytyczności biznesowej. Usługi Tier 1 (obsługa płatności) mają pełną redundancję geograficzną, Tier 2 (panel zarządzania) tylko redundancję lokalną, a Tier 3 (raportowanie) nie ma dedykowanej ochrony.

48/50
Automatyzacja infrastruktury
  • Aby HA było powtarzalne, musimy używać kodu do budowy serwerów (Infrastructure as Code - Terraform).
  • Pozwala to na błyskawiczne odtworzenie całej infrastruktury w nowym regionie w razie katastrofy (DR).
  • Ręczna konfiguracja serwerów przez „klikanie” to proszenie się o błędy i uniemożliwienie szybkiego powrotu po awarii.
  • Dzięki IaC cała nasza serwerownia jest zapisana w plikach tekstowych na Git, co gwarantuje spójność, łatwość audytu oraz możliwość testowania zmian infrastrukturalnych na kopiach przed ich wdrożeniem.
Ilustracja dla slajdu 48

Infrastructure as Code (IaC) opiera się na zasadzie deklaratywnego opisu pożądanego stanu infrastruktury. Narzędzia takie jak Terraform, Pulumi, AWS CDK czy Ansible pozwalają na definiowanie zasobów (maszyny wirtualne, sieci, bazy danych) w postaci kodu. Terraform używa własnego języka HCL, Pulumi wspiera TypeScript, Python i Go, a Ansible używa YAML.

Kluczową zaletą IaC w kontekście HA jest możliwość szybkiego odtworzenia całej infrastruktury w nowym regionie w ramach strategii DR. Wystarczy zmienić zmienną region w kodzie Terraform i uruchomić apply, aby cała infrastruktura została odtworzona w innym miejscu geograficznym. Proces ten jest w pełni powtarzalny i pozbawiony błędów ręcznej konfiguracji.

Wersjonowanie kodu IaC w Git pozwala na audyt zmian, cofanie błędnych konfiguracji i współpracę wielu inżynierów nad tą samą infrastrukturą. Code review dla zmian infrastrukturalnych powinien być obowiązkowy, a zmiany powinny przechodzić przez potok CI/CD z automatyczną walidacją przed wdrożeniem.

49/50
Podsumowanie
System idealny nie istnieje, ale dzięki opisanym technikom możemy budować usługi, które służą milionom ludzi bez przerwy, będąc fundamentem nowoczesnej gospodarki cyfrowej i zaufania użytkowników do technologii.
  • Wysoka dostępność i skalowanie to niekończąca się podróż, a nie cel.
  • Wymaga to zmiany myślenia z „naprawiania serwerów” na „projektowanie systemów odpornych na awarie”.
  • Kluczem jest redundancja, bezstanowość, automatyzacja i przede wszystkim – kultura testowania wszystkiego (od kodu po backupy).
Ilustracja dla slajdu 49

Wysoka dostępność i skalowanie to dwa filary nowoczesnych systemów rozproszonych. HA zapewnia ciągłość działania mimo awarii, a skalowanie pozwala na obsługę rosnącego obciążenia bez degradacji wydajności. Oba cele są ze sobą ściśle powiązane – system, który skaluje się horyzontalnie, jest zazwyczaj bardziej odporny na awarie.

Kluczowe technologie omówione podczas wykładu – Kubernetes, Terraform, Prometheus, Redis, Kafka, CDN – są standardem w nowoczesnych architekturach chmurowych. Znajomość tych narzędzi i umiejętność ich łączenia w spójną architekturę jest jedną z najbardziej pożądanych kompetencji na rynku pracy w IT.

Ciągłe uczenie się i testowanie jest kluczem do sukcesu w dziedzinie HA. Technologie ewoluują, pojawiają się nowe wyzwania (edge computing, serverless, AIOps). Inżynierowie powinni regularnie uczestniczyć w konferencjach, czytać case studies i eksperymentować z nowymi technologiami w bezpiecznym środowisku laboratoryjnym.

50/50
Sesja pytań
Wiedza o tym, jak budować systemy, które się nie psują (lub psują w sposób kontrolowany), to jedna z najbardziej pożądanych kompetencji na rynku IT.
  • Dziękuję za uwagę i wytrwałość.
  • Przeszliśmy przez najbardziej zaawansowane tematy inżynierii usług sieciowych.
  • Teraz jest czas na Państwa pytania – czy to o konkretne technologie (Kubernetes, Terraform, AWS), czy o strategie biznesowe.
  • Zapraszam do dyskusji i dzielenia się spostrzeżeniami dotyczącymi skalowania Państwa własnych projektów studenckich i zawodowych.
Ilustracja dla slajdu 50

Zachęcam do zadawania pytań dotyczących konkretnych technologii omówionych podczas wykładu. Jeśli interesuje Państwa implementacja którejś z architektur, chętnie omówię szczegóły konfiguracji Kubernetes, Terraform czy AWS. Jestem również otwarty na pytania dotyczące strategii biznesowych i kosztów wdrażania wysokiej dostępności w różnych skalach.

Pytania mogą dotyczyć również różnic między dostawcami chmurowymi (AWS, Azure, GCP) w kontekście oferowanych usług HA. Każdy z dostawców ma swoje mocne i słabe strony, a wybór odpowiedniego dostawcy zależy od specyficznych wymagań projektu, budżetu i kompetencji zespołu.

Na zakończenie zachęcam do zapoznania się z dodatkowymi materiałami: oficjalna dokumentacja AWS Well-Architected Framework, Kubernetes Documentation, Terraform Best Practices oraz książka „Site Reliability Engineering” od Google. Te źródła dostarczają pogłębionej wiedzy o projektowaniu niezawodnych systemów.