Serwery NUMA Nodes lokalnie tworzą dostępy do pamięci na gniazdo, a tym samym wymiernie zwiększają wydajność dużych systemów hostingowych. Pokażę, w jaki sposób ta architektura zmniejsza opóźnienia, zwiększa przepustowość, a tym samym Obciążenia lepiej skaluje się na serwerach korporacyjnych.
Punkty centralne
- Lokalność pamięci zmniejsza opóźnienia i ogranicza zdalny dostęp.
- Skalowalność na wielu rdzeniach bez wąskich gardeł magistrali pamięci.
- Świadomość NUMA w jądrze, hiperwizorze i aplikacjach zapewnia szybkość.
- Planowanie maszyn wirtualnych/kontenerów na węzeł zapobiega awariom.
- Monitoring poprzez numastat/perf odkrywa hotspoty.
Czym są serwery z węzłami NUMA?
Polegam na architekturze, w której każde gniazdo ma swój własny obszar pamięci lokalnej jako Węzeł NUMA otrzymuje. Oznacza to, że rdzeń uzyskuje dostęp przede wszystkim do szybkiej, pobliskiej pamięci RAM i unika wolniejszej, zdalnej pamięci. Dostęp przez interkonekty takie jak Infinity Fabric lub UPI pozostaje możliwy, ale kosztuje dodatkowy czas.
W przeciwieństwie do UMA, czas dostępu jest tutaj różny, co ma bezpośredni wpływ na Opóźnienie i przepustowość. Duże systemy łączą tak wiele rdzeni bez zawalania magistrali pamięci. Łatwe do zrozumienia wprowadzenie jest zapewnione przez kompaktowe Architektura NUMA w hostingu.
Lokalność pamięci w hostingu
Wiążę procesy i pamięć z tym samym węzłem, aby ścieżki danych pozostały krótkie i aby Schowek-wzrost liczby bitów. Ta lokalność pamięci ma natychmiastowy i zauważalny wpływ na serwery WWW, PHP-FPM i bazy danych. Odsuwam zdalny dostęp, dzięki czemu więcej żądań jest przetwarzanych na sekundę.
Zaplanowane powiązania procesora i pamięci zapobiegają wędrowaniu wątków między węzłami i Thrashing wyzwalacz. W przypadku konfiguracji dynamicznych testuję podejścia do równoważenia NUMA, które optymalizują dostępy w czasie; bardziej szczegółowe wprowadzenie można znaleźć tutaj Równoważenie NUMA. W ten sposób utrzymuję niskie opóźnienia i wydajniej wykorzystuję rdzenie.
Dlaczego NUMA liczy się dla dużych systemów hostingowych?
Duże platformy hostingowe obsługują wiele witryn jednocześnie i wymagają krótkich czasów reakcji. Szczyt-ruch. NUMA zwiększa szansę na to, że dane będą znajdować się blisko rdzenia wykonawczego i nie będą podróżować przez interkonekt. To właśnie tutaj sklepy, interfejsy API i systemy CMS zyskują kluczowe milisekundy.
W ten sposób zapewniam większą gęstość na hoście bez poświęcania wydajności i utrzymuję Czas sprawności-łatwiej. Nawet podczas szczytów ruchu, czasy odpowiedzi pozostają płynniejsze, ponieważ obciążenie zdalne jest mniejsze. Przekłada się to bezpośrednio na lepsze doświadczenia użytkowników i mniejszą liczbę anulowanych połączeń.
Technologia w praktyce
Odczytałem topologię za pomocą lscpu oraz numactl --hardware do Węzły, rdzenie i układ pamięci RAM. Następnie wiążę obciążenia z numactl --cpunodebind oraz --membind. Hiperwizory, takie jak KVM i nowoczesne jądra Linuksa, rozpoznają topologię i już planują korzystnie.
W systemach wielogniazdowych zwracam uwagę na przepustowość łącza i liczbę gniazd. RAM-kanałów na węzeł. Aplikacje z dużą ilością pamięci podręcznej umieszczam lokalnie w węźle. W przypadku usług z mieszanymi wzorcami używam pamięci z przeplotem, jeśli testy konsekwentnie z niej korzystają.
Ponadto oceniam za pomocą numactl --hardware die odległości węzłów wyłączony: Niskie wartości między sąsiednimi węzłami wskazują na szybszy dostęp zdalny, ale nadal zwiększają opóźnienie w porównaniu z lokalną pamięcią RAM. Uwaga --mempolicy=preferred zdalnie z naciskiem na pamięć, podczas gdy --membind jest rygorystyczna i powoduje niepowodzenie alokacji w przypadku wątpliwości. Używam tego w szczególności w zależności od krytyczności obciążeń.
Jeśli procesy tworzą wątki dynamicznie, ustawiam przed rozpoczęciem zestaw zadań- lub zestaw-maski, aby nowe wątki były automatycznie tworzone we właściwych CPU-domena. Podczas wdrażania planuję całą ścieżkę: Workery, wątki I/O, garbage collectory i wszelkie zadania w tle otrzymują spójne powinowactwa, aby nie było ukrytych ścieżek między węzłami.
Kluczowe wskaźniki wydajności w porównaniu
Oceniam optymalizację NUMA pod kątem opóźnień i przepustowości, CPU-wykorzystanie i skalowanie. Każda metryka pokazuje, czy lokalność jest skuteczna, czy też dominuje dostęp zdalny. Stałe testy pod obciążeniem zapewniają jasny kierunek dla kolejnych kroków dostrajania.
Poniższa tabela przedstawia typowe rozmiary w obciążeniach związanych z hostingiem usług internetowych i baz danych; ilustruje ona efekt lokalnego obciążenia. Dostępy przed zdalnym dostępem.
| Metryki | Bez optymalizacji NUMA | Z NUMA i lokalnością pamięci |
|---|---|---|
| Opóźnienie (ns) | 200-500 | 50–100 |
| Przepustowość (Req/s) | 10.000 | 25.000+ |
| Wykorzystanie procesora (%) | 90 | 60 |
| Skalowalność (rdzenie) | do 64 | 512+ |
Ciągle mierzę i porównuję Profile przed i po korektach. Powtarzalne punkty odniesienia są tutaj ważne, aby efekty nie wydawały się przypadkowe. W ten sposób uzyskuję konkretne, wiarygodne miary produktywnego działania.
Percentyle, takie jak p95/p99, są szczególnie istotne zamiast wartości średnich. Jeśli wysokie percentyle spadną zauważalnie po wyrównaniu dostępu zdalnego, platforma jest bardziej stabilna pod obciążeniem. Sprawdzam również współczynniki chybień LLC, przełączniki kontekstowe i długość kolejki uruchamiania na węzeł w celu czystej alokacji efektów harmonogramu i pamięci podręcznej.
Wyzwania i najlepsze praktyki
NUMA Thrashing występuje, gdy wątki przemieszczają się między węzłami i są stale Pamięć żądanie. Przeciwdziałam temu za pomocą stałego rozmieszczenia wątków, spójnego wiązania pamięci i limitów na usługę. Wyraźne przypisanie wyraźnie zmniejsza ruch zdalny.
Jako narzędzi testowych używam numastat, perf i zdarzenia jądra do Hotspoty do odkrycia. Regularne monitorowanie pokazuje, czy pula trafia do niewłaściwego węzła lub czy maszyna wirtualna jest niekorzystnie dystrybuowana. Podejmując małe, zaplanowane kroki, minimalizuję ryzyko i zapewniam stały postęp.
Opcje jądra i BIOS/UEFI
Sprawdzam ustawienia BIOS/UEFI, takie jak klastrowanie sub-NUMA lub partycjonowanie węzłów na gniazdo. Drobniejszy podział może wyostrzyć lokalność, ale wymaga bardziej rygorystycznych powiązań. Zwykle dezaktywuję globalne przeplatanie pamięci, aby zminimalizować różnice między pamięcią lokalną i zdalną. Pamięć pozostają widoczne, a planista może podejmować rozsądne decyzje.
Po stronie Linuksa pasuję kernel.numa_balancing świadomie. W przypadku sztywnych obciążeń HPC lub opóźnień dezaktywuję automatyczne równoważenie (echo 0 > /proc/sys/kernel/numa_balancing), w przypadku obciążeń mieszanych testuję go w połączeniu z wyraźnymi podobieństwami procesora. vm.zone_reclaim_mode Ustawiłem go konserwatywnie, aby węzły nie odzyskiwały własnych stron zbyt agresywnie i nie powodowały niepotrzebnych odzysków.
Dla baz danych intensywnie korzystających z pamięci planuję HugePages na węzeł. Transparent Huge Pages (THP) mogą się wahać; wolę używać statycznych HugePages i wiązać je lokalnie w węźle. Zmniejsza to współczynnik braku TLB i stabilizuje opóźnienia. Kontroluję również zamianę za pomocą vm.swappiness blisko 0, aby gorące ścieżki nie kończyły się w swapie.
Dopasowuję przerwania do topologii: irqbalance tak, aby przerwania NIC kończyły się na procesorach tego samego węzła, na którym działają odpowiedni pracownicy. Stosy sieciowe z RPS/RFS rozdziela pakiety zgodnie z maskami procesora; ustawiłem te maski tak, aby pasowały do pozycji pracownika, aby uniknąć ścieżek między węzłami w pasie danych.
W przypadku dysków SSD NVMe dystrybuuję kolejki na węzeł i wiążę wątki we/wy lokalnie. W ten sposób bazy danych, pamięci podręczne i metadane systemu plików mają najkrótsze możliwe łańcuchy opóźnień od procesora przez pamięć RAM do kontrolera pamięci masowej. W przypadku trwałych dzienników lub dzienników z wyprzedzeniem zapisu zwracam szczególną uwagę na czyste powinowactwa węzłów, ponieważ mają one bezpośredni wpływ na czasy odpowiedzi.
Konfiguracja we wspólnych stosach
Tworzę pule PHP FPM w taki sposób, że pracownicy na serwerze Węzeł i dopasowuję rozmiar puli do liczby rdzeni. W przypadku NGINX lub Apache wiążę procesy intensywnie korzystające z operacji wejścia/wyjścia z tą samą lokalizacją co cache. Bazy danych, takie jak PostgreSQL lub MySQL, otrzymują stałe HugePages na węzeł.
Na poziomie wirtualizacji tworzę układy vCPU spójne z fizycznymi procesorami. Układ na. Używam specjalnie CPU Affinity, szybki start jest tutaj Przynależność procesora. Zapobiega to niepotrzebnemu obciążaniu interkonektu przez gorące ścieżki.
Wzorce obciążenia: sieć, pamięć podręczna i bazy danych
Serwery WWW i PHP-FPM odnoszą korzyści, jeśli gniazda nasłuchujące, procesy robocze i pamięci podręczne znajdują się w tej samej domenie NUMA. Skaluję niezależnie na węzeł: oddzielne grupy procesów na węzeł z własną maską procesora i własnym obszarem pamięci współdzielonej. Zapobiega to przechodzeniu pamięci podręcznej sesji, OPCache lub lokalnych potoków FastCGI przez połączenie międzywęzłowe.
W konfiguracjach Redis/Memcached używam wielu instancji, po jednej na węzeł, zamiast jednej dużej instancji na obu gniazdach. Dzięki temu wiadra hash i płyty pozostają lokalne. W przypadku Elasticsearch lub podobnych wyszukiwarek celowo przypisuję shardy do węzłów i utrzymuję wątki zapytań i pozyskiwania na tej samej stronie, co powiązane obszary plików i pamięci podręcznej stron.
Z PostgreSQL udostępniam shared_buffers i pule robocze na segmenty węzłów, oddzielając instancje lub usługi na węzeł. Skaluję InnoDB poprzez innodb_buffer_pool_instances i upewnić się, że wątki puli pozostają w węźle. Osobno monitoruję check pointery, WAL writery i autovacuum, ponieważ często generują one niechciane zdalne dostępy.
W przypadku usług stanowych utrzymuję zadania w tle (zagęszczanie, analiza, reindeksacja) czasowo i topologicznie oddzielone od gorących ścieżek. W razie potrzeby używam numactl --preferred, aby umożliwić płynniejszy skok obciążenia bez pełnego rygoru --membind egzekwować.
Planowanie wydajności i koszty
Obliczam TDP, kanały pamięci RAM i pożądane gęstość na host przed przeniesieniem obciążeń. Podwójne gniazdo z wysokim procentem pamięci RAM na węzeł często zapewnia najlepszą wartość euro na żądanie. Oszczędności można zauważyć, gdy host obsługuje więcej maszyn wirtualnych o tym samym czasie odpowiedzi.
Na przykład, przejście na NUMA-aware placement może zwiększyć liczbę hostów o dwucyfrową liczbę. Procenty zmniejszyć. Nawet przy dodatkowych kosztach pamięci RAM w wysokości kilkuset euro na węzeł, bilans jest dodatni. Kalkulacja działa, jeśli zestawię pomiary z bieżącymi kosztami operacyjnymi w €.
Biorę również pod uwagę koszty energii: lokalność skraca czas procesora na żądanie, co znacznie zmniejsza zużycie energii. Podczas doboru warsztatów oceniam więc nie tylko szczytową liczbę żądań/s, ale także kWh/1000 żądań na topologię. Takie spojrzenie sprawia, że decyzje dotyczące większej gęstości i dodatkowych gniazd są bardziej namacalne.
vNUMA i migracja na żywo w praktyce
W środowiskach zwirtualizowanych mapuję topologie vNUMA, aby dopasować je do struktury fizycznej. Grupuję vCPU maszyny wirtualnej na vNode i uwzględniam przypisaną pamięć RAM. W ten sposób unikam rozprzestrzeniania się rzekomo małej maszyny wirtualnej w obu gniazdach i generowania zdalnych dostępów.
Konsekwentnie przypinam procesy QEMU i ich wątki we/wy, w tym iothread oraz vhost-tasks. Przechowuję HugePages na węzeł jako backend pamięci, aby maszyna wirtualna korzystała z tej samej pamięci lokalnej za każdym razem, gdy jest uruchamiana. Świadomie planuję kompromisy: Bardzo rygorystyczne strategie przypinania mogą ograniczać migrację na żywo; tutaj wybieram między maksymalną stabilnością opóźnień a elastycznością operacyjną.
W przypadku overcommit zwracam uwagę na wyraźne górne limity: Jeśli pamięć RAM na węzeł staje się niewystarczająca, preferuję alternatywne strategie w ramach tej samej grupy maszyn wirtualnych zamiast dzikiego rozlewania się między węzłami. Wolę podłączyć vNIC i vDisks do węzła, na którym pracownicy maszyn wirtualnych wykonują obliczenia, aby ścieżka danych pozostała spójna.
NUMA i orkiestracja kontenerów
Kontenery odnoszą korzyści, gdy żądania, pamięć podręczna i Dane są zlokalizowane lokalnie. W Kubernetes używam wskazówek dotyczących topologii, aby Scheduler przydzielał rdzenie i pamięć w tym samym węźle. Zabezpieczam klasy QoS i żądania/limity, aby pody nie błąkały się bez celu.
Testuję polityki dla Menedżera CPU i HugePages do czasu Opóźnienie i przepustowość. Obciążenia stanowe otrzymują stałe węzły, podczas gdy usługi bezstanowe skalują się bliżej krawędzi. Dzięki temu platforma pozostaje elastyczna, nie tracąc przy tym zalet lokalności.
Dzięki statycznej polityce menedżera CPU przydzielam rdzenie na wyłączność i uzyskuję wyraźne powiązania. Menedżer topologii nadaje priorytety single-numa-node, aby strąki były połączone razem. W przypadku bramek i kontrolerów Ingress dystrybuuję SO_REUSEPORT-listener na węzeł, aby ruch był zaplanowany lokalnie. Planuje pamięci podręczne, sidecary i segmenty pamięci współdzielonej na grupę podów, tak aby wylądowały na tym samym węźle NUMA.
Podręcznik benchmarkingu i monitorowanie
Pracuję z ustaloną procedurą, aby niezawodnie mierzyć i dostrajać efekty NUMA:
- Topologia przechwytywania:
lscpu,numactl --hardware, Sprawdź kanały połączeń i pamięci RAM. - Linia bazowa pod obciążeniem: rejestruj opóźnienia p95/p99, Req/s, profile braku CPU i LLC na węzeł.
- Wprowadzenie wiązania:
--cpunodebind/--membind, puli na węzeł. - Ponowne uruchomienie: to samo obciążenie, te same dane, logicznie przypisz różnice.
- Dostrajanie: powinowactwo przerwań, HugePages, alokator pamięci, garbage collection.
- Sprawdzanie regresji w CI: regularnie replikuj scenariusze, aby zapobiec dryfowi.
Jeśli chodzi o głębię, odsyłam do statystyka perf oraz rekord wydajności z powrotem, obserwować liczniki zdalnego dostępu, pominięcia LLC i TLB oraz udziały czasowe w jądrze vs. userland. numastat dostarcza mi rozkład alokacji i wskaźnik zdalnych błędów dla każdego węzła. Ten widok sprawia, że etapy optymalizacji są powtarzalne i można je priorytetyzować.
Obrazy błędów i rozwiązywanie problemów
Typowe anty-wzorce rozpoznaję po nieregularnych opóźnieniach i wysokim wykorzystaniu procesora bez odpowiedniego wzrostu przepustowości. Częstymi przyczynami są zbyt szerokie maski CPU, globalne THP bez stałych HugePages, agresywne automatyczne skalowanie bez odniesienia do topologii lub niefortunnie rozproszona pamięć podręczna.
Najpierw sprawdzam, czy wątki z ps -eLo pid,psr,psr,cmd oraz taskset -p działają tam, gdzie powinny. Następnie sprawdzam numastat-liczniki zdalnych dostępów i porównuję je ze szczytami ruchu. W razie potrzeby tymczasowo włączam przeplatanie, aby odkryć wąskie gardła, a następnie przełączam się z powrotem na ścisłą lokalność.
Udowodnił również swoją wartość, a dostosowując śrubę jedna po drugiej: Najpierw bindowanie, potem powinowactwo przerwań, następnie HugePages, a na końcu dostrajanie alokatora pamięci. W ten sposób efekty pozostają identyfikowalne i odwracalne.
Przyszły rozwój
Nowe interkonekty i CXL rozszerzają zakres adresowalności Pamięć i sprawiają, że odłączona pamięć RAM staje się bardziej namacalna. Serwery ARM z wieloma rdzeniami również wykorzystują topologie typu NUMA i wymagają takiego samego skupienia na lokalności. Trend wyraźnie zmierza w kierunku jeszcze dokładniejszych strategii rozmieszczania.
Oczekuję, że programy planujące silniej zintegrują sygnały NUMA z Czas rzeczywisty ocenić. Stosy hostingowe automatycznie integrują odpowiednie powiązania dla typowych obciążeń. Dzięki temu lokalizacja staje się standardem, a nie specjalnym środkiem.
Krótkie podsumowanie
Węzły NUMA Wiązki serwera lokalne Zasoby na gniazdo i znacznie skracam ścieżki danych. Łączę procesy i pamięć, minimalizuję zdalny dostęp i konsekwentnie mierzę efekty. Skutkuje to zauważalnym wzrostem opóźnień, przepustowości i gęstości.
Dzięki czystemu rozpoznawaniu topologii, sprytnym powiązaniom i ciągłemu Monitoring Dostawcy usług hostingowych lepiej wykorzystują swój sprzęt. Ci, którzy podejmują te kroki, konsekwentnie osiągają szybsze witryny, lepsze skalowanie i przewidywalne koszty. To jest dokładnie to, co robi różnicę w codziennej działalności.


