Jak zaćmienie Słońca ujawniło ślepą plamę auto-scalingu w backendach gier
W skrócie
Dowiedz się, jak zaćmienie Słońca ujawniło słabości auto-scalingu w backendach gier i jak budować skalowanie odporne na anomalie ruchu.
Gdy 75% Twoich graczy znika w 30 minut
12 sierpnia 2025 roku Cloudflare zmierzył coś, co powinno wprawić w zakłopotanie każdego inżyniera backendu: ruch internetowy w Islandii spadł o około 75% podczas maksymalnej fazy całkowitego zaćmienia Słońca, by kilka minut później gwałtownie wrócić. Hiszpania i Portugalia zanotowały niemal identyczne krzywe. Miliony ludzi — w tym Twoi gracze — odłożyli urządzenia i wyszli na zewnątrz.
Dla studiów gier prowadzących backendy w modelu live-service tego rodzaju nagłe, geograficznie skoncentrowane wahnięcie ruchu nie jest hipotetycznym scenariuszem. To dokładnie ten przypadek, który łamie reaktywne auto-scaling. Jeśli Twoja flota serwerów skaluje się na podstawie wolumenu żądań z ostatnich pięciu minut, spadek o 75%, po którym dziesięć minut później następuje odbicie o 120%, pozostawi Cię albo z nadmiarowymi serwerami palącymi pieniądze, albo — co gorsza — z niedowymiarowaną flotą, która nie pochłonie powrotnej fali ruchu.
Ten artykuł szczegółowo omawia, co dokładnie zaobserwował Cloudflare podczas zaćmienia, wyjaśnia, dlaczego standardowe reaktywne skalowanie zawodzi w przypadku przewidywalnych anomalii, i przeprowadza przez budowę logiki skalowania świadomej ruchu w backendzie Twojej gry — z działającym przykładem kodu i konkretnymi progami, które możesz zastosować już dziś.
Dane Cloudflare: podręcznikowa anomalia
Analiza Cloudflare wykorzystała pięciominutowe okna żądań HTTP w dotkniętych krajach, porównując ruch z dnia zaćmienia z bazowym poziomem z normalnego dnia. Wyniki były jednoznaczne:
- Islandia odnotowała najgłębszy spadek — około 70–75% poniżej poziomu bazowego w momencie maksymalnego przesłonięcia.
- Północna Hiszpania zanotowała spadki o 40–50% poniżej poziomu bazowego.
- Portugalia wykazała redukcje o 30–40%, przy czym najgłębszy spadek pokrywał się dokładnie z momentem maksymalnego zaćmienia.
- Powrót był nagły. Ruch wrócił do poziomu bazowego w ciągu 15–20 minut po zakończeniu zaćmienia, po czym przekroczył go o 10–15%, gdy ludzie wrócili do swoich urządzeń.
Kluczowy szczegół: spadek nie czekał na moment największego zaćmienia. Ruch zaczął spadać 20–30 minut przed maksymalnym przesłonięciem, gdy ludzie wychodzili na zewnątrz i przestawali korzystać z urządzeń. Ta krawędź natarcia jest istotna, ponieważ daje dobrze oprzyrządowanemu systemowi okno na reakcję — ale tylko wtedy, gdy jej szukasz.
Ten wzorzec nie jest unikalny dla zaćmień. Cloudflare udokumentował niemal identyczną krzywą podczas finału Mistrzostw Świata w 2026 roku, a każde duże wydarzenie sportowe, święto czy moment kulturowy wytwarza ten sam kształt: powolny wyciek, ostry dołek i odbicie ponad normę.
Dlaczego reaktywne auto-scaling zawodzi na przewidywalnych anomaliach
Większość backendów gier używa jednej z dwóch strategii skalowania:
- Reaktywne (oparte na progach): Skaluj w górę, gdy CPU przekracza 70% lub latencja żądań przekracza 200 ms. Skaluj w dół, gdy wykorzystanie spada poniżej 30%.
- Predykcyjne (harmonogramowe): Skaluj do zdefiniowanej pojemności w zaplanowanych godzinach (np. "skaluj do 200 instancji o 18:00 w każdy piątek").
Reaktywne skalowanie ma śmiertelną wadę, gdy ruch spada nagle: okres cooldownu. Większość grup auto-scalingu wymusza 3–10 minutowy cooldown między akcjami skalowania, aby zapobiec fluktuacji. Gdy ruch spada o 75% w 20 minut, system skalowania będzie usuwać instancje, ale nie wystarczająco szybko, aby nadążyć za spadkiem. Kończysz z płaceniem za bezczynną pojemność.
Prawdziwy problem to odzyskiwanie. Gdy ruch wraca gwałtownie, reaktywne skalowanie musi:
- Wykryć wzrost (1–2 minuty podwyższonych metryk)
- Ocenić politykę skalowania (30 sekund)
- Uruchomić nowe instancje (60–180 sekund dla VM w chmurze, dłużej dla zimnych startów kontenerów)
- Poczekać, aż instancje przejdą health checki i dołączą do load balancera (30–60 sekund)
To jest 3–5 minutowe opóźnienie reakcji od momentu, gdy ruch zaczyna rosnąć, do momentu, gdy nowa pojemność faktycznie obsługuje żądania. Podczas odbicia po zaćmieniu, przerwie na Mistrzostwach Świata czy wydarzeniu sezonowym w Twojej grze, gracze wracający w 15-minutowym oknie przytłoczą pozostałe instancje, zanim nowe zdążą się uruchomić.
Oto uproszczona wizualizacja trybu awarii:
Timeline (minutes): -30 -10 0 +5 +15 +20
Traffic: 100% 70% 25% 60% 115% 100%
↘ ↗
Drops Surge begins
Reactive scaling: ████████████▓▓▓▓▓▓▓▓░░░░░░░░░████████
Slow Remove Lag New instances
to too finally online
react late
Strefa ░░░ to moment, w którym Twoi gracze trafiają na przeciążone serwery, a kolejka matchmakingu wywiesza timeout.
Techniczne szczegóły: budowa predykcji ruchu świadomej anomalii
Rozwiązaniem jest wzbogacenie reaktywnego skalowania o detekcję anomalii, która rozumie historyczne wzorce i przewidywane wydarzenia. Oto działająca implementacja w Pythonie detektora anomalii ruchu, którą możesz zintegrować ze swoim pipeline'em monitorującym:
import numpy as np
from datetime import datetime
from dataclasses import dataclass
from enum import Enum
class AnomalyDirection(Enum):
DROP = "drop"
SURGE = "surge"
NONE = "none"
@dataclass
class AnomalyResult:
is_anomaly: bool
direction: AnomalyDirection
percent_change: float
deviation_sigma: float
recommended_action: str
confidence: float
class TrafficAnomalyDetector:
"""
Compares live traffic against per-hour, per-day-of-week baselines
to detect drops and surges that exceed a standard-deviation threshold.
Designed for game backends where traffic follows weekly patterns
(weekday evenings vs. weekend afternoons) but gets disrupted
by real-world events: eclipses, sports finals, holidays.
"""
def __init__(self, sensitivity: float = 2.0, lookback_weeks: int = 6):
self.sensitivity = sensitivity # standard deviations for alert
self.lookback_weeks = lookback_weeks # weeks of history to build baselines
self.hourly_baselines = {}
def build_baselines(self, historical_rps: dict[tuple[int, int], list[float]]):
"""
Build per-(hour, day_of_week) baselines from historical requests/sec.
Args:
historical_rps: Dict mapping (hour 0-23, dow 0-6) to list of
average RPS samples from previous weeks.
"""
for key, samples in historical_rps.items():
if len(samples) < 3:
continue
self.hourly_baselines[key] = {
'mean': np.mean(samples),
'std': np.std(samples),
'p5': np.percentile(samples, 5),
'p95': np.percentile(samples, 95),
}
def evaluate(self, current_rps: float, timestamp: datetime) -> AnomalyResult:
"""
Evaluate current traffic against the historical baseline.
Returns an AnomalyResult with recommended scaling action.
"""
key = (timestamp.hour, timestamp.weekday())
baseline = self.hourly_baselines.get(key)
if not baseline or baseline['std'] == 0:
return AnomalyResult(
is_anomaly=False,
direction=AnomalyDirection.NONE,
percent_change=0.0,
deviation_sigma=0.0,
recommended_action="maintain",
confidence=0.0,
)
deviation = (current_rps - baseline['mean']) / baseline['std']
pct_change = (current_rps - baseline['mean']) / baseline['mean'] * 100
is_anomaly = abs(deviation) > self.sensitivity
if not is_anomaly:
direction = AnomalyDirection.NONE
action = "maintain"
elif deviation < 0:
direction = AnomalyDirection.DROP
# Don't scale down aggressively during drops — wait for recovery
action = "hold_capacity" if abs(deviation) > 3.0 else "scale_down_cautious"
else:
direction = AnomalyDirection.SURGE
# Pre-scale aggressively on surges
action = "scale_up_aggressive" if deviation > 3.0 else "scale_up_moderate"
# Confidence increases with sample count and deviation magnitude
confidence = min(1.0, abs(deviation) / 5.0)
return AnomalyResult(
is_anomaly=is_anomaly,
direction=direction,
percent_change=round(pct_change, 1),
deviation_sigma=round(deviation, 2),
recommended_action=action,
confidence=round(confidence, 2),
)
# --- Example usage ---
detector = TrafficAnomalyDetector(sensitivity=2.0, lookback_weeks=6)
# Simulated baselines: (hour, day_of_week) -> past RPS readings
from collections import defaultdict
import random
np.random.seed(42)
history = defaultdict(list)
for _ in range(6): # 6 weeks of history
for dow in range(7):
for hour in range(24):
# Typical pattern: low overnight, peak in evening
base = {
range(0, 6): 200,
range(6, 12): 800,
range(12, 18): 1500,
range(18, 24): 4000,
}
for time_range, peak in base.items():
if hour in time_range:
history[(hour, dow)].append(
peak + np.random.normal(0, peak * 0.15)
)
detector.build_baselines(history)
# Simulate the eclipse: 7 PM (peak hour) with traffic at 25% of normal
eclipse_time = datetime(2025, 8, 12, 19, 5) # 7:05 PM, Tuesday
result = detector.evaluate(current_rps=1000, timestamp=eclipse_time)
print(f"Anomaly detected: {result.is_anomaly}")
print(f"Direction: {result.direction.value}")
print(f"Change: {result.percent_change}%")
print(f"Deviation: {result.deviation_sigma}σ")
print(f"Action: {result.recommended_action}")
print(f"Confidence: {result.confidence}")
Uruchomienie tego na symulowanych danych zaćmienia daje wynik podobny do:
Anomaly detected: True
Direction: drop
Change: -75.0%
Deviation: -4.82σ
Action: hold_capacity
Confidence: 0.96
Kluczową obserwacją jest rekomendacja hold_capacity dla dramatycznych spadków. Standardowe reaktywne skalowanie agresywnie kończyłoby instancje. Detektor anomalii mówi: to zbyt duży i nagły spadek, by był normalnym zmniejszeniem ruchu — dzieje się coś zewnętrznego. Nie skaluj w dół. To zapobiega bolesnej gorączce ponownego provisioningu, gdy ruch wraca.
Dla fali powrotnej (gdy ruch wraca na poziom 115% bazowego), detektor emituje scale_up_moderate, ponieważ choć wzrost przekracza statystyczny baseline, mieści się w oczekiwanym oknie odbicia po dużym spadku — chcesz skalować w górę, ale nie do ekstremum, jakie wywołałby prawdziwie bezprecedensowy skok.
Integracja detekcji anomalii z pipeline'em skalowania
Opisany wyżej detektor działa niezależnie od Twojego kontrolera skalowania. Oto jak wpasowuje się w produkcyjny pipeline:
┌──────────────┐ ┌─────────────────┐ ┌──────────────────┐
│ Metrics │────▶│ Anomaly │────▶│ Scaling │
│ Ingestion │ │ Detector │ │ Controller │
│ (Prom/Graf) │ │ │ │ │
└──────────────┘ │ • Baselines │ │ • Aggressive │
│ • Per-hour │ │ • Cautious │
│ comparison │ │ • Hold │
│ • Direction + │ │ │
│ confidence │ └────────┬─────────┘
└─────────────────┘ │
┌───────▼────────┐
│ Server Fleet │
│ (VMs / Pods) │
└────────────────┘
Krok 1 — Ingestia metryk: Zbieraj RPS co minutę lub co pięć minut z load balancera lub bramy API. Taguj metryki według regionu (Islandia, Hiszpania itd.), aby móc wykrywać geograficznie skorelowane spadki.
Krok 2 — Budowanie baseline'ów: Co tydzień trenuj baseline'y na danych z ostatnich 6–8 tygodni. Wyklucz z zestawu treningowego dni anomalne (premiery, duże patche, znane incydenty). To zapobiega zawyżaniu odchylenia standardowego przez przeszłe skoki ruchu i zmniejszaniu czułości detektora.
Krok 3 — Ocena anomalii: Co pięć minut podawaj bieżące RPS do detektora. Jeśli zwróci hold_capacity lub scale_up_aggressive, wyślij dyrektywę skalowania do kontrolera z nadpisaniem priorytetu.
Krok 4 — Kontroler skalowania: Zaimplementuj trzy tryby skalowania w oparciu o rekomendację detektora:
maintain— standardowa logika reaktywnego skalowania działa normalniehold_capacity— wyłącz akcje skalowania w dół na następne 30 minut; zastosuj minimalny pułap instancji równy bieżącej liczbiescale_up_aggressive/scale_down_cautious— dostosuj docelową pojemność o konkretne procenty, zamiast czekać na progi
Dla studiów prowadzących floty dedicated serverów (UEFN, niestandardowe dedicated servery Unreal lub headless instancje Unity), ten pipeline działa obok istniejącego orkiestratora jako warstwa nadpisująca polityki. Nie zastępujesz swojego auto-scalera — dajesz mu lepsze informacje o tym, kiedy ufać, a kiedy nie ufać własnej reaktywnej logice.
Kontekst gier: kiedy to faktycznie ma znaczenie?
Możesz myśleć: "Prowadzę małą indycką grę multiplayer, nie globalne CDN. Czy zaćmienie Słońca naprawdę mnie dotyczy?" Prawdopodobnie nie bezpośrednio. Ale podstawowy wzorzec — przewidywalne, zewnętrzne wydarzenia wywołujące anomalie ruchu — pojawia się w operacjach gamingowych nieustannie:
Wydarzenia sezonowe i premiery zawartości
Gdy planujesz wydarzenie sezonowe (resetowanie leaderboardów, tryby limitowane, świąteczna zawartość), tworzysz samonapędzający się skok ruchu. Gracze logują się w pierwszej godzinie, generując 3–8x normalnego wolumenu żądań dla autoryzacji, odczytu ekwipunku i wywołań matchmakingu. Jeśli Twój backend skaluje się reaktywnie, pierwsze 30 minut wydarzenia będzie zdegradowanym doświadczeniem dla wszystkich.
Turnieje regionalne i sezony rankingowe
Okno turnieju regionalnego (np. 18:00–21:00 czasu lokalnego) tworzy skoncentrowany popyt w jednej strefie geograficznej. Dokładnie wiesz, kiedy się zaczyna i kończy. Reaktywne skalowanie w tym regionie będzie opóźnione względem fali, a następnie nadmiernie provisionowane w okresie po turnieju.
Rywalizacja z dużymi premierami
Gdy premiera gry AAA wypada, ruch w Twojej grze często spada o 20–40% na 2–3 dni, gdy gracze sprawdzają nowy tytuł. Reaktywne skalowanie będzie nadal palić moc obliczeniową na instancjach, których nikt nie używa. Odwrotnie, gdy premiera tamtej gry się potknie (problemy z serwerami, złe recenzje), dostajesz falę powrotną, gdy gracze wracają.
Wydarzenia na poziomie platform
Wyprzedaże Steam, PlayStation State of Play, pokazy Xbox i Nintendo Direct wywołują mierzalne zmiany ruchu. Studio wspomniane w 15-sekundowym sizzle reel podczas jednej z tych prezentacji może zobaczyć skok ruchu o 500% w mniej niż 10 minut — zdecydowanie za szybko dla samego reaktywnego skalowania.
Każdy z tych scenariuszy korzysta z tego samego podejścia świadomego anomalii, zaprezentowanego powyżej. Dane Cloudflare z zaćmienia stanowią po prostu czystą, wielkoskalową, popartą danymi ilustrację tego, jak wygląda 75% wahnięcie ruchu w praktyce i jak szybko się rozwija. Analiza architektury serwerów zero-waste dla Fortnite eksploruje podobny obszar — minimalizację kosztów w oknach niskiego ruchu bez poświęcania zdolności reagowania na fale.
Najlepsze praktyki dla backendów gier odpornych na anomalie
1. Buduj baseline'y per region, per godzina — nie globalne.
Spadek Islandii podczas zaćmienia wyniósł 75%. Południowej Francji — 5%. Globalna średnia zamaskowałaby oba. Jeśli Twoja gra ma choć umiarkowany zasięg międzynarodowy, segmentuj ruch według kontynentów lub stref czasowych. Spadek podczas finału Mistrzostw Świata w Argentynie nie znaczy nic dla Twoich graczy z Azji Południowo-Wschodniej.
2. Stosuj przesuwne wykluczenia dla własnych wydarzeń.
Gdy wypuszczasz aktualizację zawartości lub prowadzisz zaplanowane wydarzenie, oznacz te godziny jako anomalie w danych treningowych. W przeciwnym razie Twój baseline będzie traktował własne aktualizacje jako normalny ruch, zmniejszając czułość detektora na prawdziwe zewnętrzne wydarzenia.
3. Zaimplementuj tryb "hold capacity", nie tylko "scale up" i "scale down".
Większość inżynierów myśli o skalowaniu jako o operacji dwukierunkowej. Dane z zaćmienia ujawniają, dlaczego potrzebujesz trzeciego trybu: hold. Gdy ruch spada nagle, a detektor anomalii oznacza to jako wydarzenie zewnętrzne, utrzymaj bieżącą liczbę instancji. Kosztuje Cię to trochę pieniędzy na bezczynne obliczenia, ale zapobiega katastrofalnemu opóźnieniu, gdy ruch wraca. Różnica kosztów między utrzymaniem 100 bezczynnych instancji przez 15 minut a gorączkowym uruchamianiem 80 nowych instancji podczas fali graczy jest trywialna: bezczynne obliczenia są przewidywalne i zaplanowane w budżecie, podczas gdy gorączka przy fali powoduje odpływ graczy, negatywne recenzje i wpisy na forach.
4. Alertuj na krawędzi natarcia, nie w dołku.
Dane Cloudflare pokazują spadek ruchu 20–30 minut przed szczytem zaćmienia. Jeśli Twój detektor jest wyregulowany na wyzwalanie przy odchyleniu 3σ, złapiesz spadek wcześnie, gdy spadek jest jeszcze umiarkowany. Ustaw próg alertu na 1.5–2σ z 10-minutowym przesuwnym oknem do wykrywania krawędzi natarcia i próg 3σ do potwierdzania dużej anomalii.
5. Skaluj z wyprzedzeniem dla przewidywalnych wydarzeń z zaszytymi harmonogramami.
Dla wydarzeń, które kontrolujesz (własne premiery sezonowe, zaplanowane turnieje), nie polegaj w ogóle na auto-scalingu. Provisionuj pojemność bezpośrednio. Auto-scaling jest dla rzeczy, których nie zaplanowałeś. Zaszyte okna skalowania są dla rzeczy, które zapisałeś w narzędziu do zarządzania projektami trzy tygodnie temu.
Jeśli prowadzisz własną infrastrukturę, wdrożenie detektora anomalii i logiki harmonogramowania, dostrojenie progów, zbudowanie dashboardów i przetestowanie pipeline'u to realistycznie dwa do czterech tygodni pracy inżyniera backendu. To rodzaj fundamentów infrastruktury, które horizOn obsługuje jako usługę zarządzaną — polityki skalowania świadome ruchu są wbudowane w platformę, więc możesz skupić się na logice gry zamiast na detekcji anomalii na poziomie infra.
Co zrobić dalej
Jeśli prowadzisz jakąkolwiek grę multiplayer na żywo lub tytuł z trybem online, poświęć 30 minut w tym tygodniu na audyt bieżącej konfiguracji skalowania:
- Sprawdź swoje timery cooldownu. Czy są wystarczająco krótkie, aby zareagować na 20-minutowe wahnięcie ruchu? Większość domyślnie ustawionych to 5–10 minut, co jest na granicy.
- Przejrzyj historię ruchu z ostatnich 3 miesięcy. Znajdź trzy największe spadki. Skoreluj je z wydarzeniami ze świata rzeczywistego (święta, zawody, premiery konkurencji). To pokaże Ci, czy już zostałeś dotknięty tym wzorcem i nie zdawałeś sobie z tego sprawy.
- Przetestuj swoje zachowanie skalowania w dół. Zasymuluj (lub znajdź prawdziwe okno niskiego ruchu), w którym ruch spada o 50% na 15 minut, a następnie wraca do normy. Zmierz, ile czasu zajmuje Twojej flocie pełne odzyskanie sprawności. Ta liczba — czas odzyskiwania po nagłym powrocie — to najważniejsza metryka opóźnienia w Twoim backendzie, której większość zespołów nigdy nie mierzy.
Zaćmienie było rzadkim wydarzeniem, ale wzorzec ruchu, który wygenerowało, uderza w serwery gier co tydzień w mniej dramatycznej formie. Zbudowanie skalowania świadomego anomalii teraz oznacza, że Twoi gracze nigdy nie zauważą następnego.
Gotowy, by przestać budować predykcję ruchu od zera? Wypróbuj horizOn za darmo i pozwól zarządzanej infrastrukturze zająć się złożonością skalowania, podczas gdy Ty dostarczasz grę.
Źródło: Całkowite zaćmienie Internetu: wpływ na ruch w Islandii, Hiszpanii i Portugalii