Węzły, krawędzie, kierunki
Żądanie jako spacer po grafie
Każdy komponent, z którym żądanie wchodzi w interakcję, jest węzłem: klient, resolver DNS, krawędź CDN, proxy odwrotne, replika backendu, baza danych, cache.
Każde połączenie między dwoma węzłami to skierowana krawędź: żądania płyną do przodu, odpowiedzi wracają. Krawędź do przodu reprezentuje otwarte połączenie TCP oraz protokół na nim działający.
Pojedyncze żądanie to ścieżka przez ten graf. Całkowita praca wykonana przez system w celu odpowiedzi na żądanie jest równa sumie pracy na każdym węźle oraz opóźnienia na każdej krawędzi.
Dlaczego to ważne? Po narysowaniu grafu stają się widoczne właściwości, które są niewidoczne w kodzie:
- Liczba skoków (hop count): liczba krawędzi na ścieżce. Każdy skok dodaje opóźnienie (round trip sieciowy + przetwarzanie na węźle). Mniejsze liczba skoków = niższy dolny limit opóźnienia.
- Stopień wejściowy (in-degree): ile krawędzi wskazuje NA węzeł. Wysoki stopień wejściowy oznacza, że węzeł otrzymuje żądania z wielu źródeł i musi skalować się lub chronić.
- Stopień wyjściowy (out-degree): ile krawędzi wychodzi Z węzła. Wysoki stopień wyjściowy oznacza, że węzeł zależy od wielu usług dół (downstream) i ma wiele sposobów na awarię.
- Węzeł rozłączający (cut vertex): pojedynczy węzeł, którego usunięcie rozłącza graf. Proxy wsteczny bez pary jest węzłem rozłączającym; jego usunięcie usuwa cały dostęp do jego źródeł (origins).
Gdzie ruch się koncentruje
Zbieżność = Koncentracja
Stopień wejściowy węzła = liczba krawędzi wskazujących do niego. W grafie żądań stopień wejściowy = liczba źródeł górnych, które wysyłają żądania.
Wzorzec fan-in: wiele klientów -> jeden CDN; wiele krawędzi CDN -> kilka proxy źródłowych; wiele proxy -> mniej replik backendu; wiele backendów -> pojedyncza baza danych.
Koncentracja ma znaczenie, ponieważ węzeł o najwyższym stopniu wejściowym (in-degree) widzi największe obciążenie agregowane. Baza danych na końcu łańcucha może otrzymywać zapytania od każdego aktywnego żądania w całym systemie, nawet jeśli żaden pojedynczy użytkownik nie generuje dużego ruchu.
Fan-Out = Zależność
Stopień wyjściowy (out-degree) węzła = liczba krawędzi wychodzących z niego. Wysoki stopień wyjściowy oznacza wiele zależności w dół łańcucha (downstream).
Backend, który wywołuje bazę danych, dwa cache, trzy zewnętrzne API oraz kolejkę, ma stopień wyjściowy równy 7. Jego prawdopodobieństwo sukcesu jest przybliżone iloczynem prawdopodobieństwa sukcesu każdego z elementów w dół łańcucha (jeśli wszystkie są wymagane dla udanego odpowiedzi).
0,999 ^ 7 ≈ 0,993: backend z 7 zależnościami w dół łańcucha, z których każda ma niezawodność 99,9%, może osiągnąć tylko ok. 99,3% własnej niezawodności, nawet jeśli nie ma żadnych własnych błędów.
Zmniejsz stopień wyjściowy przez: cache'owanie wyników z elementów w dół łańcucha, uczynienie niekrytycznych elementów w dół łańcucha opcjonalnymi (graceful degradation), równoległe wykonywanie tego, co można równoleglić.
Asymetria
Fan-in koncentruje obciążenie, a fan-out mnoży ryzyko. Dobrze ukształtowany graf minimalizuje oba te zjawiska na węzłach o największym wpływie.
Baza danych (najwyższy fan-in): agresywnie stosuj cache, aby zmniejszyć obciążenie. Używaj replik odczytu, aby rozłożyć fan-in na wiele węzłów.
Usługa orkiestratora (najwyższy fan-out): przerywniki obwodu (circuit breakers) dla każdego zależności, eleganckie degradacje (graceful degradation), grodzie (bulkheads).
Wstawiony węzeł zapewnia elastyczność
Indyrekcyjność = dodanie węzła pośredniego
Bez proxy graf wygląda tak: client -> backend. Klient musi znać adres backendu. Przeniesienie backendu wymaga aktualizacji klienta (poprzez DNS lub konfigurację). Jest to silne sprzężenie.
Z proxy graf staje się: client -> proxy -> backend. Klient zna tylko proxy. Przeniesienie backendu wymaga aktualizacji konfiguracji upstream proxy, a nie klienta.
Operacja na grafie: wstawienie węzła wzdłuż istniejącej krawędzi. Nowa krawędź client -> proxy jest stabilna; nowa krawędź proxy -> backend jest teraz pod zarządzaniem zespołu.
Interpretacja geometryczna: indyrekcyjność dodaje warstwę, która rozłącza zmiany po stronie górnej (upstream) od zmian po stronie dolnej (downstream). Krawędzie każdej warstwy mogą być przełączane niezależnie.
Koszt pośrednictwa
Każda warstwa dodaje:
- Jedno dodatkowe opóźnienie (krawędź od klienta do proxy)
- Jeden dodatkowy wierzchołek rozłączający na ścieżce (samo proxy)
- Jedno dodatkowe miejsce, w którym może dojść do błędnego konfigurowania
Korzyści (przewirowanie, skalowanie, osłona, terminowanie TLS, dystrybucja obciążenia) zazwyczaj przewyższają koszty w przypadku każdego nietrywialnego systemu. Istnieje jednak limit: każda warstwa pośrednictwa dodaje kolejny przyskok oraz kolejnego kandydata na SPOF (Single Point of Failure).
Reguła ludowa: każdy problem można rozwiązać, dodając warstwę pośrednictwa (z wyjątkiem problemu zbyt wielu warstw pośrednictwa).
Czytanie architektury jako grafu
Synteza
Możesz teraz czytać architekturę systemu jako graf: liczyć skoki, identyfikować wierzchołki przecinające, mierzyć koncentrację wejścia (fan-in), obliczać górną granicę dostępności na podstawie wyjścia (fan-out) oraz oceniać kompromisy związane z pośrednictwem.
Zastosuj wszystkie cztery.
Nowa usługa ma następującą architekturę: clients -> CDN -> reverse proxy (2 repliki) -> backend tier (8 replik) -> { DB primary, cache cluster (3 węzły), external API }.
Notatki towarzyszące
Notatki towarzyszące
Ta lekcja z zakresu geometrii reinterpretuje główną lekcję Prokse i Źródła jako analizę grafu skierowanego.
Następna lekcja towarzysząca w tym kursie, geometry_of_stateless_horizontal_scaling, bierze matematykę replikacji z głównej lekcji o skalowaniu i wyprowadza krzywą kolejkową, prawo Little'a oraz punkt przegięcia przy 80% wykorzystaniu w sposób geometryczny.
Bardzo dobrze.