...

Servidor de nós NUMA: Importância para grandes sistemas de alojamento

Os servidores NUMA Nodes criam localmente os acessos à memória por socket, aumentando assim de forma mensurável a eficiência dos grandes sistemas de alojamento. Mostrarei como esta arquitetura reduz a latência, aumenta o débito e, consequentemente Cargas de trabalho é melhor escalado em servidores empresariais.

Pontos centrais

  • Localidade da memória diminui a latência e reduz o acesso remoto.
  • Escalabilidade em muitos núcleos sem estrangulamentos no barramento de memória.
  • Consciência NUMA no kernel, no hipervisor e nas aplicações traz velocidade.
  • Planeamento de VMs/contentores por nó evita o "thrashing".
  • Monitorização através do numastat/perf descobre os pontos de acesso.

O que são servidores de nós NUMA?

Confio numa arquitetura em que cada socket tem a sua própria área de memória local como um Nó NUMA recebe. Isto significa que um núcleo acede principalmente à RAM rápida e próxima e evita a memória mais lenta e remota. Os acessos através de interconexões como Infinity Fabric ou UPI continuam a ser possíveis, mas custam tempo adicional.

Ao contrário da UMA, o tempo de acesso varia aqui, o que tem um impacto direto na Latência e largura de banda. Os grandes sistemas agrupam tantos núcleos sem colapsar no barramento de memória. Uma introdução fácil de entender é fornecida pelo compacto Arquitetura NUMA em alojamento.

Localidade de memória no alojamento

Eu vinculo processos e memória ao mesmo nó para que os caminhos de dados permaneçam curtos e Cache-hits aumentam. Essa localidade de memória tem um efeito imediato e percetível em servidores web, PHP-FPM e bancos de dados. Eu empurro para trás os acessos remotos para que mais pedidos sejam processados por segundo.

Os binds planeados de CPU e memória impedem que as threads se desloquem entre nós e Bater acionamento. Para configurações dinâmicas, testo abordagens de balanceamento NUMA que optimizam os acessos ao longo do tempo; uma introdução mais aprofundada pode ser encontrada aqui Balanceamento NUMA. Desta forma, mantenho a latência baixa e utilizo os núcleos de forma mais eficiente.

Porque é que o NUMA é importante para sistemas de alojamento de grande dimensão

As grandes plataformas de alojamento comportam muitos sítios Web em simultâneo e exigem tempos de resposta curtos com Pico-tráfego. O NUMA aumenta a possibilidade de os dados estarem perto do núcleo de execução e não viajarem através da interligação. É exatamente aqui que as lojas, APIs e CMSs ganham os milissegundos cruciais.

Assim, asseguro uma maior densidade no anfitrião sem sacrificar o desempenho e mantenho Tempo de atividade-destinos mais facilmente. Mesmo durante os picos de tráfego, os tempos de resposta permanecem mais suaves porque há menos carga remota. Isto compensa diretamente com melhores experiências de utilizador e menos cancelamentos.

A tecnologia na prática

Leio a topologia com lscpu e numactl --hardware para Nós, núcleos e disposição da RAM de forma clara. Em seguida, associei cargas de trabalho com numactl --cpunodebind e --membind. Os hipervisores como o KVM e os kernels Linux modernos reconhecem a topologia e já programam com vantagem.

Em sistemas multi-socket, presto atenção à largura de banda de interconexão e ao número de RAM-canais por nó. Coloco aplicações com uma grande pegada de cache num nó local. Para serviços com padrões mistos, utilizo a memória intercalada se os testes beneficiarem dela de forma consistente.

Além disso, avalio com numactl --hardware o distâncias entre nós desligado: Valores baixos entre nós vizinhos indicam um acesso remoto mais rápido, mas ainda assim aumentam a latência em comparação com a RAM local. Note-se que --mempolicy=preferred remotamente com pressão de memória, enquanto --membind é rigoroso e faz com que as atribuições falhem em caso de dúvida. Utilizo-o especificamente em função da criticidade dos volumes de trabalho.

Se os processos criarem threads dinamicamente, eu defino antes do início conjunto de tarefas- ou cset-para que as novas threads sejam automaticamente criadas na CPU-domínio. Eu planeio todo o caminho durante a implantação: Trabalhadores, threads de E/S, coletores de lixo e quaisquer trabalhos em segundo plano recebem afinidades consistentes para que não haja caminhos ocultos entre nós.

Indicadores de desempenho em comparação

Avalio a otimização NUMA através da latência e da taxa de transferência, CPU-utilização e escalonamento. Cada métrica mostra se a localidade é eficaz ou se o acesso remoto é dominante. Os testes constantes sob carga fornecem uma direção clara para os próximos passos de afinação.

A tabela seguinte mostra tamanhos típicos em cargas de trabalho de alojamento para serviços relacionados com a Web e bases de dados; ilustra o efeito da Acessos contra o acesso remoto.

Métricas Sem otimização NUMA Com NUMA e Localidade de Memória
Latência (ns) 200-500 50–100
Taxa de transferência (Req/s) 10.000 25.000+
Utilização da CPU (%) 90 60
Escalabilidade (núcleos) até 64 512+

Meço continuamente e comparo Perfis antes e depois dos ajustamentos. A reprodutibilidade das referências é importante para que os efeitos não pareçam aleatórios. É assim que obtenho medidas concretas e fiáveis para o funcionamento produtivo.

Percentis como p95/p99 são particularmente significativos em vez de apenas valores médios. Se os percentis altos caírem visivelmente após a equalização dos acessos remotos, a plataforma é mais estável sob carga. Também verifico as taxas de erro LLC, as mudanças de contexto e comprimento da fila de espera de execução por nó, a fim de atribuir efeitos de programação e de cache de forma limpa.

Desafios e boas práticas

O NUMA Thrashing ocorre quando os threads se movem entre os nós e constantemente Memória pedido. Eu combato este problema com a colocação de threads fixas, a ligação consistente da memória e os limites por serviço. Uma atribuição clara reduz visivelmente o tráfego remoto.

Como ferramentas de teste, utilizo numastato, perfeito e eventos do kernel para Pontos de acesso para descobrir. A monitorização regular mostra se um pool desliza para o nó errado ou se uma VM é distribuída de forma desfavorável. Ao dar passos pequenos e planeados, minimizo o risco e asseguro um progresso constante.

Opções do kernel e do BIOS/UEFI

Eu verifico as configurações do BIOS/UEFI, como clustering sub-NUMA ou particionamento de nós por soquete. Uma divisão mais fina pode melhorar a localidade, mas requer ligações mais rigorosas. Normalmente desativo a intercalação de memória global para que as diferenças entre a memória local e remota possam ser minimizadas. Memória permanecem visíveis e o programador pode tomar decisões sensatas.

No lado do Linux, eu instalo kernel.numa_balancing conscientemente. Para cargas de trabalho HPC ou de latência rígidas, desactivei o balanceamento automático (echo 0 > /proc/sys/kernel/numa_balancing), para cargas de trabalho mistas, testo-o em combinação com afinidades claras com a CPU. vm.zone_reclaim_mode Defino-o de forma conservadora para que os nós não reclamem as suas próprias páginas de forma demasiado agressiva e desencadeiem reclamações desnecessárias.

Para bases de dados com muita memória, planeio Páginas enormes por nó. Transparent Huge Pages (THP) pode flutuar; eu prefiro usar HugePages estáticas e ligá-las localmente ao nó. Isso reduz as taxas de falha do TLB e estabiliza a latência. Eu também controlo a troca com vm.swappiness próximo de 0, para que os caminhos quentes não acabem na troca.

Faço corresponder as interrupções à topologia: equilíbrio do Iraque para que as interrupções da NIC terminem nas CPUs do mesmo nó em que os trabalhadores correspondentes estão a ser executados. Pilhas de rede com RPS/RFS distribuir os pacotes de acordo com as máscaras da CPU; eu defini essas máscaras para corresponder à posição do trabalhador, a fim de evitar caminhos entre nós no plano de dados.

Para SSDs NVMe, eu distribuo filas por nó e vinculei threads de E/S localmente. Dessa forma, os bancos de dados, caches e metadados do sistema de arquivos encontram as cadeias de latência mais curtas possíveis da CPU para a RAM e para o controlador de armazenamento. Para registos persistentes ou registos de escrita antecipada, presto especial atenção às afinidades de nós limpos, porque têm uma influência direta nos tempos de resposta.

Configuração em pilhas comuns

Eu crio pools PHP FPM de tal forma que os trabalhadores em um e dimensiono o tamanho do pool para corresponder ao número de núcleos. Para o NGINX ou o Apache, eu vinculo os processos de E/S intensiva ao mesmo local que os caches. Bases de dados como PostgreSQL ou MySQL recebem HugePages fixas por nó.

Ao nível da virtualização, crio layouts de vCPU consistentes com o Disposição sobre. Eu uso especificamente o CPU affinity, um início rápido está aqui Afinidade com a CPU. Isto evita que os caminhos quentes sobrecarreguem desnecessariamente a interligação.

Padrões de carga de trabalho: web, cache e bases de dados

Servidores Web e PHP-FPM se beneficiam se os sockets de escuta, workers e caches estiverem no mesmo domínio NUMA. Escalo independentemente por nó: grupos de processos separados por nó com sua própria máscara de CPU e sua própria área de memória compartilhada. Isso evita que caches de sessão, OPCache ou pipes FastCGI locais passem pela interconexão.

Nas configurações do Redis/Memcached, eu uso várias instâncias, uma por nó, em vez de uma instância grande em ambos os sockets. Isso mantém os hash buckets e slabs locais. Para o Elasticsearch ou motores de busca semelhantes, atribuo deliberadamente shards aos nós e mantenho as threads de consulta e ingestão na mesma página que as áreas de cache de arquivo e página associadas.

Com o PostgreSQL partilho buffers partilhados e pools de trabalho em segmentos de nós, separando instâncias ou serviços por nó. Eu dimensiono o InnoDB através de innodb_buffer_pool_instances e garantir que os threads de um pool permaneçam dentro de um nó. Monitorizo os ponteiros de verificação, os gravadores WAL e o autovacuum separadamente, uma vez que geram frequentemente acessos remotos indesejados.

Para serviços com estado, mantenho as tarefas em segundo plano (compactação, análise, reindexação) temporalmente e topologicamente separadas dos caminhos quentes. Se necessário, utilizo numactl --preferred, para permitir uma excursão de carga mais suave sem o rigor total de --membind para fazer cumprir.

Planeamento da capacidade e custos

Calculo o TDP, os canais de RAM e o densidade por anfitrião antes de mover as cargas de trabalho. Um socket duplo com uma elevada percentagem de RAM por nó proporciona frequentemente o melhor valor em euros por pedido. As economias podem ser vistas quando um host carrega mais VMs com o mesmo tempo de resposta.

Por exemplo, a mudança para a colocação com reconhecimento de NUMA pode aumentar o número de hosts em dois dígitos. Percentagens reduzir. Mesmo com custos adicionais de algumas centenas de euros por nó em RAM, o balanço é positivo. O cálculo funciona se compararmos as medições com os custos operacionais actuais em euros.

Também tenho em conta os custos de energia: a localidade reduz o tempo de CPU por pedido, o que reduz visivelmente o consumo. Nos workshops de dimensionamento, não avalio apenas o pico de req/s, mas também kWh/1000 pedidos por topologia. Esta visão torna as decisões entre maior densidade e sockets adicionais mais tangíveis.

vNUMA e migração em direto na prática

Em ambientes virtualizados, mapeio as topologias vNUMA para corresponder à estrutura física, agrupo as vCPUs de uma VM por vNode e incluo a RAM atribuída. Desta forma, evito que uma VM supostamente pequena se espalhe pelos dois sockets e produza acessos remotos.

Eu fixo os processos do QEMU e seus threads de E/S de forma consistente, incluindo iothread e hospedeiro-tarefas. Eu armazeno HugePages por nó como um backend de memória para que a VM use a mesma memória local toda vez que for iniciada. Eu planeio conscientemente compromissos: Estratégias de fixação muito rígidas podem restringir a migração em tempo real; aqui eu decido entre a estabilidade máxima de latência e a flexibilidade operacional.

Com o overcommit, presto atenção a limites superiores claros: Se a RAM por nó se tornar escassa, prefiro estratégias alternativas dentro do mesmo grupo de VMs, em vez de um spillover selvagem entre nós. Prefiro ligar vNICs e vDisks ao nó em que os trabalhadores das VMs estão a computar, para que o caminho dos dados permaneça consistente.

NUMA e orquestração de contentores

os contentores beneficiam quando os pedidos, a cache e os Dados estão localizadas localmente. No Kubernetes, utilizo dicas de topologia para que o Scheduler atribua núcleos e memória no mesmo nó. Eu protejo classes e solicitações/limites de QoS para que os pods não fiquem vagando sem rumo.

Estou a testar políticas para o Gestor de CPU e HugePages até Latência e taxa de transferência. As cargas de trabalho com estado recebem nós fixos, enquanto os serviços sem estado são dimensionados mais perto da borda. Isso mantém a plataforma ágil sem perder as vantagens da localidade.

Com uma política de gestor de CPU estático, atribuo núcleos exclusivamente e obtenho afinidades claras. O gestor de topologia dá prioridade a nó único-numa, para que os pods sejam agrupados. Para gateways e controladores Ingress, distribuo SO_REUSEPORT-por nó para que o tráfego seja programado localmente. Planeio caches, sidecars e segmentos de memória partilhada por grupo de pods para que aterrem no mesmo nó NUMA.

Manual de avaliação comparativa e monitorização

Trabalho com um procedimento fixo para medir e ajustar de forma fiável os efeitos NUMA:

  • Capturar a topologia: lscpu, numactl --hardware, interconexão e canais de RAM.
  • Linha de base sob carga: registar latências p95/p99, Req/s, CPU e perfis de falha LLC por nó.
  • Introduzir a encadernação: --cpunodebind/--membind, pools por nó.
  • Nova execução: mesma carga, mesmos dados, atribuir logicamente as diferenças.
  • Afinação: afinidade de interrupção, HugePages, alocador de memória, recolha de lixo.
  • Verificações de regressão na IC: reproduzir cenários regularmente para evitar desvios.

Para uma maior profundidade, remeto para estatística perfeita e registo de desempenho para trás, observe os contadores de acesso remoto, as falhas de LLC e TLB e as partilhas de tempo no kernel em comparação com o userland. numastato fornece-me a distribuição das atribuições e a taxa de falhas remotas para cada nó. Esta visão torna as etapas de otimização reprodutíveis e prioritárias.

Imagens de erros e resolução de problemas

Reconheço os antipadrões típicos por latências erráticas e alta utilização da CPU sem um ganho correspondente na taxa de transferência. As causas frequentes são máscaras de CPU demasiado largas, THP global sem HugePages fixas, escalonamento automático agressivo sem referência à topologia ou uma cache distribuída infeliz.

Primeiro verifico se as threads com ps -eLo pid,psr,psr,cmd e conjunto de tarefas -p funcionam onde é suposto. Depois verifico o numastato-contadores de acessos remotos e comparo-os com os picos de tráfego. Se necessário, ligo temporariamente a intercalação para descobrir os estrangulamentos e depois volto a ligar a localidade estrita.

Também provou o seu valor, a ajustando os parafusos um após o outro: Primeiro as ligações, depois a afinidade de interrupções, depois as HugePages e, finalmente, o ajuste fino do alocador de memória. Desta forma, os efeitos permanecem rastreáveis e reversíveis.

Desenvolvimentos futuros

As novas interligações e o CXL alargam a gama de produtos endereçáveis Memória e tornam a RAM dissociada mais tangível. Os servidores ARM com muitos núcleos também utilizam topologias do tipo NUMA e exigem a mesma atenção à localidade. A tendência está claramente a evoluir para estratégias de colocação ainda mais finas.

Espero que os programadores integrem mais fortemente os sinais NUMA em Tempo real avaliar. As pilhas de alojamento integram então automaticamente as ligações adequadas para cargas de trabalho típicas. Isto torna a localização a norma em vez de uma medida especial.

Brevemente resumido

Nós NUMA Pacotes de servidores locais Recursos por socket e encurtar significativamente os caminhos de dados. Eu junto processos e memória, minimizo o acesso remoto e meço os efeitos de forma consistente. Isso resulta em ganhos notáveis em latência, taxa de transferência e densidade.

Com um reconhecimento limpo da topologia, ligações inteligentes e Monitorização os fornecedores de alojamento tiram mais partido do seu hardware. Aqueles que tomam estas medidas conseguem consistentemente sites mais rápidos, melhor escalonamento e custos previsíveis. É exatamente isto que faz a diferença no dia a dia das empresas.

Artigos actuais