Kiedy ESX 5 i Hyper-V w systemie Windows Server 2012 zostały wydane i zmieniły ograniczenia, które wcześniej istniały dla rozmiarów maszyn wirtualnych, niemal natychmiast wiedziałem, że zobaczymy, jak coraz więcej obciążeń SQL Server o dużej skali zacznie być zwirtualizowanych. W zeszłym roku współpracowałem z wieloma klientami, którzy wirtualizują 16-32 rdzeniowe serwery SQL z różnych powodów, od uproszczonych strategii odzyskiwania po awarii, które pasowały do reszty firmy, po konsolidację i niższy całkowity koszt posiadania na nowszym sprzęcie platformy. Jednym z powodów zmiany skalowalności w ESX 5+ było wprowadzenie wirtualnej NUMA (vNUMA) dla szerokich gości, która przekroczyła rozmiar pojedynczego węzła sprzętowego NUMA. Dzięki vNUMA maszyna wirtualna gościa jest zoptymalizowana pod kątem sprzętowej topologii NUMA, dzięki czemu system operacyjny gościa i wszelkie aplikacje obsługujące technologię NUMA, takie jak SQL Server, które działają na maszynie wirtualnej, mogą korzystać z optymalizacji wydajności NUMA, tak jakby były działa na fizycznym serwerze.
W ramach VMware topologia vNUMA jest dostępna na sprzęcie w wersji 8 lub nowszej i jest domyślnie konfigurowana, jeśli liczba procesorów wirtualnych jest większa niż osiem dla gościa. Możliwe jest również ręczne skonfigurowanie topologii vNUMA dla maszyny wirtualnej przy użyciu zaawansowanych opcji konfiguracyjnych, co może być przydatne w przypadku maszyn wirtualnych, które mają przydzieloną do nich więcej pamięci niż może zapewnić fizyczny węzeł NUMA, ale nadal używają ośmiu lub mniej procesorów wirtualnych. W większości przypadków domyślne ustawienia konfiguracji działają w przypadku większości maszyn wirtualnych, które przyglądałem się w ciągu ostatnich kilku lat, ale są pewne scenariusze, w których domyślna topologia vNUMA nie jest idealna, a ręczna konfiguracja może zapewnić pewne korzyści. Ostatnio pracowałem z klientem z liczbą 32 maszyn wirtualnych vCPU SQL Server z przydzielonymi 512 GB pamięci RAM, dostrajając wydajność, gdzie topologia vNUMA nie była zbliżona do oczekiwanej.
Serwery hostów maszyn wirtualnych w tym środowisku składały się z czterech ośmiordzeniowych procesorów E5-4650 i 1 TB pamięci RAM, z których każdy był przeznaczony dla jednej maszyny wirtualnej SQL Server w typowych operacjach, ale z możliwością obsługi dwóch maszyn wirtualnych w przypadku awarii. Przy takim układzie sprzętowym istnieją cztery węzły NUMA, po jednym na gniazdo, a oczekiwana konfiguracja VM będzie zawierała również 4 węzły vNUMA dla konfiguracji 32 vCPU. Jednak patrząc na DMV w SQL Server odkryłem, że tak nie było:
Rysunek 1 – Nieprawidłowa konfiguracja vNUMA
Jak zapewne widać na obrazku, coś jest naprawdę nie tak z konfiguracją NUMA na tym serwerze. W systemie SQLOS istnieją cztery węzły pamięci i tylko jeden węzeł procesora, w którym są przydzielone wszystkie procesory wirtualne. Szczerze mówiąc, zaskoczyło mnie to, gdy to zobaczyłem, ponieważ było to sprzeczne ze wszystkim, co wiedziałem o tym, jak SQLOS konfigurował wewnętrzne struktury podczas uruchamiania instancji. Po przekopaniu się trochę w plikach ErrorLog, Performance Monitor i Windows Task Manager, pobrałem kopię CoreInfo z SysInternals i przyjrzałem się układowi NUMA zgłaszanemu do systemu Windows.
Mapa procesorów logicznych do gniazd:********———————— Gniazdo 0
——–********—————- Gniazdo 1
—————-********——– Gniazdo 2
———————******** Gniazdo 3
Mapa procesora logicznego do węzła NUMA:
********************************* Węzeł NUMA 0
Dane wyjściowe CoreInfo potwierdziły, że maszyna wirtualna przedstawia 32 vCPU jako 4 różne gniazda, ale następnie pogrupowała wszystkie 32 vCPU w NUMA Node 0. Patrząc na liczniki wydajności systemu Windows Server 2012 na maszynie wirtualnej, mogłem zobaczyć w grupie liczników NUMA Node Memory, że Systemowi operacyjnemu przedstawiono 4 węzły pamięci NUMA, a pamięć została równomiernie rozłożona na węzły. Wszystko to zgadzało się z tym, co widziałem w SQLOS, i mogłem również stwierdzić na podstawie wpisów ERRORLOG podczas uruchamiania, że maska procesora dla węzła maskowała wszystkie dostępne procesory w węźle procesora 0, ale tworzone były cztery duże alokatory stron, jeden dla każdy węzeł pamięci.
09/22/2013 05:03:37,Serwer,Nieznany,Konfiguracja węzła:węzeł 0:Maska procesora:0x00000000ffffffff:0 Aktywna maska procesora:0x00000000ffffffff:0. Ten komunikat zawiera opis konfiguracji NUMA dla tego komputera. To jest tylko wiadomość informacyjna. Żadne działanie użytkownika nie jest wymagane.22.09.2013 05:03:37,Server,Unknown,To wystąpienie programu SQL Server ostatnio zgłoszone przy użyciu identyfikatora procesu 1596 w dniu 9/22/2013 5:00:25 AM (lokalnie) 22.09.2013 10:00:25 (UTC). To jest tylko wiadomość informacyjna; żadne działanie użytkownika nie jest wymagane.
22.09.2013 05:03:35,Serwer,Nieznany,Duża strona Przydzielono:32MB
22.09.2013 05:03:35,Serwer,Nieznany,Duży Przydzielono stronę:32 MB
22.09.2013 05:03:35,Serwer,Nieznany,Przydzielono dużą stronę:32MB
22.09.2013 05:03:35,Serwer,Nieznany,Przydzielono dużą stronę :32MB
22.09.2013 05:03:35,Serwer,Nieznany,Korzystanie z zablokowanych stron w menedżerze pamięci.
22.09.2013 05:03:35,Serwer,Nieznany,Wykryto 524287 MB pamięci RAM. To jest wiadomość informacyjna; żadne działanie użytkownika nie jest wymagane.
22.09.2013 05:03:35,Serwer,Nieznany,SQL Server uruchamia się z normalnym priorytetem (=7). To jest tylko wiadomość informacyjna. Nie jest wymagane żadne działanie użytkownika.
22.09.2013 05:03:35,Server,Unknown,SQL Server wykrył 4 gniazda z 8 rdzeniami na gniazdo i 8 procesorami logicznymi na gniazdo 32 procesory logiczne; przy użyciu 32 procesorów logicznych w oparciu o licencje SQL Server. To jest wiadomość informacyjna; nie jest wymagane żadne działanie użytkownika.
W tym momencie byłem pewien, że jest to coś związanego z konfiguracją maszyny wirtualnej, ale nie mogłem określić, na czym konkretnie polegał problem, ponieważ nigdy nie widziałem tego zachowania na innych maszynach wirtualnych SQL Server, które pomagałem klientom na VMware ESX 5+ w przeszłości. Po dokonaniu kilku zmian konfiguracyjnych na testowym serwerze VM, który był dostępny, tylko żadna z nich nie poprawiła konfiguracji vNUMA prezentowanej wewnątrz maszyny wirtualnej. Po wywołaniu pomocy technicznej VMware poproszono nas o wyłączenie funkcji hotplug vCPU dla testowej maszyny wirtualnej i sprawdzenie, czy to rozwiązało problem. Po wyłączeniu hotplug na maszynie wirtualnej dane wyjściowe CoreInfo potwierdziły, że mapowanie vNUMA procesorów dla maszyny wirtualnej było teraz poprawne:
Mapa procesorów logicznych do gniazd:********———————— Gniazdo 0
——–********—————- Gniazdo 1
—————-********——– Gniazdo 2
———————******** Gniazdo 3
Mapa procesora logicznego do węzła NUMA:
********———————— Węzeł NUMA 0
——–********————— - Węzeł NUMA 1
—————-********——– Węzeł NUMA 2
————————******** Węzeł NUMA 3
To zachowanie jest faktycznie udokumentowane w artykule VMware KB (vNUMA jest wyłączone, jeśli włączona jest funkcja VCPU hotplug), z października 2013 r. Tak się złożyło, że była to pierwsza szeroka wirtualna maszyna wirtualna dla SQL Server, z którą pracowałem, w której włączono vCPU hotplug. nie jest to typowa konfiguracja, jakiej bym się spodziewał dla maszyny wirtualnej z 32 vCPU, ale była częścią standardowego szablonu używanego u klienta i miała wpływ na ich SQL Server.
Skutki wyłączenia vNUMA
Takie wyłączenie vNUMA może mieć wiele skutków dla obciążenia, ale istnieją dwa specyficzne problemy, które mogą mieć wpływ na SQL Server w przypadku tego typu konfiguracji. Po pierwsze, serwer może mieć problemy z akumulacją oczekiwania CMEMTHREAD, ponieważ do pojedynczego węzła NUMA przydzielono 32 procesory wirtualne, a domyślnym partycjonowaniem obiektów pamięci w SQLOS jest każdy węzeł NUMA. Ten konkretny problem został udokumentowany przez Boba Dorra z grupy CSS w firmie Microsoft w swoim poście na blogu SQL Server 2008/2008 R2 na nowszych komputerach z więcej niż 8 procesorami prezentowanymi na węźle NUMA może wymagać flagi śledzenia 8048. W ramach przeglądu statystyk oczekiwania na maszynie wirtualnej z klientem zauważyłem, że CMEMTHREAD był ich drugim najwyższym typem oczekiwania, co jest nienormalne z mojego doświadczenia i spowodowało, że spojrzałem na konfigurację SQLOS NUMA pokazaną na rysunku 1 powyżej. W tym przypadku flaga śledzenia nie jest rozwiązaniem, usunięcie vCPU hotplug z konfiguracji maszyny wirtualnej rozwiązuje problem.
Drugi problem, który może mieć wpływ na SQL Server w przypadku wersji bez poprawki, jest związany z zarządzaniem pamięcią NUMA w SQLOS oraz ze sposobem, w jaki SQLOS śledzi i zarządza stronami Away podczas początkowej fazy zwiększania pamięci po uruchomieniu instancji. To zachowanie zostało udokumentowane przez Boba Dorra we wpisie na blogu CSS, How It Works:SQL Server (NUMA Local, Foreign i Away Memory Blocks). Zasadniczo, gdy SQLOS próbuje alokacji pamięci lokalnego węzła podczas początkowego rozruchu, jeśli adres pamięci zwrócony pochodzi z innego węzła pamięci, strona jest dodawana do listy Away i następuje kolejna próba alokacji pamięci lokalnej, a proces jest powtarzany do alokacja pamięci lokalnej powiodło się lub osiągnięto docelową pamięć serwera. Ponieważ trzy czwarte pamięci naszych instancji znajduje się w węzłach NUMA bez żadnych programów planujących, powoduje to pogorszenie warunków wydajności podczas początkowego zwiększania ilości pamięci dla instancji. Ostatnie aktualizacje zmieniły zachowanie alokacji pamięci podczas początkowego przyspieszania, tak aby próbować alokacji pamięci lokalnej tylko ustaloną liczbę razy (konkretna liczba nie jest udokumentowana) przed użyciem pamięci obcej do kontynuowania przetwarzania. Te aktualizacje są udokumentowane w KB #2819662, POPRAWKA:Problemy z wydajnością programu SQL Server w środowiskach NUMA.
Podsumowanie
W przypadku szerokich maszyn wirtualnych, zdefiniowanych jako posiadające więcej niż 8 procesorów wirtualnych, pożądane jest, aby vNUMA została przekazana do maszyny wirtualnej przez hipernadzorcę, aby umożliwić systemom Windows i SQL Server wykorzystanie optymalizacji NUMA w ich bazie kodu. W rezultacie te szersze maszyny wirtualne nie powinny mieć włączonej konfiguracji vCPU hotplug, ponieważ jest to niezgodne z vNUMA i może skutkować obniżoną wydajnością SQL Server podczas wirtualizacji.