Estou executando um conjunto de testes de carga para determinar o desempenho da seguinte configuração:
Node.js test suite (client) --> StatsD (server) --> Graphite (server)
Em resumo, o conjunto de testes node.js envia uma quantidade definida de métricas a cada x segundos para uma instância StatsD localizada em outro servidor. O StatsD, por sua vez, libera as métricas a cada segundo para uma instância do Graphite localizada no mesmo servidor. Depois, analiso quantas métricas foram realmente enviadas pelo conjunto de testes e quantas foram recebidas pelo Graphite para determinar a perda de pacotes entre o conjunto de testes e o Graphite.
No entanto, notei que às vezes recebia taxas muito grandes de queda de pacotes (observe que ele está sendo enviado com o protocolo UDP), variando de 20 a 50%. Foi então que comecei a investigar onde esses pacotes estavam sendo descartados, pois poderia haver algum problema de desempenho com o StatsD. Então comecei a registrar as métricas em todas as partes do sistema para rastrear onde essa queda ocorreu. E é aí que as coisas ficam estranhas.
Estou usando o tcpdump para criar um arquivo de captura que inspeciono após a execução do teste. Mas sempre que eu executo os testes com o tcpdump em execução, a perda de pacotes é quase inexistente! Parece que o tcpdump está aumentando o desempenho dos meus testes e não consigo descobrir por que e como isso acontece. Estou executando o seguinte comando para registrar as mensagens tcpdump no servidor e no cliente:
tcpdump -i any -n port 8125 -w test.cap
Em um caso de teste específico, estou enviando 40000 métricas / s. O teste durante a execução do tcpdump apresenta uma perda de pacotes de cerca de 4%, enquanto o teste sem uma perda de pacotes de cerca de 20%
Ambos os sistemas estão executando como VMs do Xen com a seguinte configuração:
- Intel Xeon E5-2630 v2 a 2.60GHz
- 2GB RAM
- Ubuntu 14.04 x86_64
Coisas que eu já verifiquei para possíveis causas:
- Aumentando o tamanho de recebimento / envio do buffer UDP.
- Carga da CPU que afeta o teste. (carga máxima de 40-50%, do lado do cliente e do servidor)
- Executando o tcpdump em interfaces específicas em vez de 'any'.
- Executando o tcpdump com '-p' para desativar o modo promíscuo.
- Executando o tcpdump apenas no servidor. Isso resultou na perda de pacotes de 20% e parece não afetar os testes.
- Executando o tcpdump apenas no cliente. Isso resultou em maior desempenho.
- Aumentando netdev_max_backlog e netdev_budget para 2 ^ 32-1. Isso não fez diferença.
- Tentei todas as configurações possíveis do modo promíscuo em todos os nichos (servidor ativado e cliente desativado, servidor desativado e cliente ativado, ambos ativados, ambos desativados). Isso não fez diferença.
-p
opção de pular isso para ver se faz alguma diferença.ifconfig eth0 promisc
ativa eifconfig eth0 -promisc
desativa o modo promíscuo em eth0. Se isso fizer diferença, tente comparar as 4 combinações possíveis de promisc ativadas / desativadas nas duas máquinas. Isso pode ajudar a identificar a fonte dos problemas.Respostas:
Quando o tcpdump estiver em execução, será bastante rápido ler os quadros recebidos. Minha hipótese é que as configurações do buffer de anel de pacote da NIC podem ser um pouco menores; Quando o tcpdump está em execução, ele é esvaziado de maneira mais oportuna.
Se você é um assinante da Red Hat, este artigo de suporte é muito útil. Visão geral da recepção de pacotes . Tem algumas coisas que acho que você ainda não considerou.
Considere como seu sistema está lidando com IRQs; considere aumentar o 'dev_weight' da interface de rede (significando mais pacotes lidos da NIC para o espaço do usuário); observe com que frequência o aplicativo lê o soquete (ele pode usar um thread dedicado, existem problemas / solução alternativa conhecidos sobre escalabilidade).
Aumente o buffer do quadro da NIC (usando o
ethtool
comando - veja os--set-ring
argumentos etc.).Observe 'redimensionamento lateral de recebimento' e use pelo menos muitos segmentos de recebimento para ler no tráfego.
Gostaria de saber se o tcpdump está fazendo algo interessante, como usar o suporte ao kernel para buffers de anel de pacotes . Isso ajudaria a explicar o comportamento que você está vendo.
fonte
Qual governador de poder você está usando? Eu já vi comportamentos semelhantes com o governador "ondemand" ou "conservador".
Tente usar o governador de "desempenho" e desativar todos os recursos que economizam energia no BIOS do servidor.
Isso muda alguma coisa?
fonte
cpufreq-info
mas recebi uma mensagem dizendono or unknown cpufreq driver is active on this CPU
. Também ao usá-cpupower frequency-info
lo retornano or unknown cpufreq driver is active on this CPU
. Embora eu não posso confirmar isso no momento, o site do fabricante VM me leva a acreditar que está em execução no modo "performance" desde que eu tenho uma CPU Intel ..cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
2)cat /proc/cpuinfo
3)lsmod | grep cpu
Outra maneira é o
ip_conntarck
módulo: Você tem certeza que sua caixa Linux pode aceitar uma nova conexão? teste via:Você tem que testar
se max == count, sua conexão máxima está cheia e sua caixa Linux não pode aceitar nova conexão.
Se você não possui o ip_conntrack, pode carregar facilmente via
modprobe ip_conntrack
fonte
Eu suspeito que o lado receptor simplesmente não é capaz de lidar com a taxa de pacotes e aqui está o porquê:
o uso do tcpdump no cliente reduz os pacotes descartados: o tcpdump está diminuindo a velocidade do cliente e, portanto, o servidor está vendo uma taxa de empacotador muito menor com a qual ainda pode lidar parcialmente. Você deve poder confirmar esta hipótese verificando os contadores de pacotes RX / TX no cliente e no servidor
você mencionou que aumentou o tamanho de recebimento / envio do buffer UDP, poderia detalhar como? É importante que no servidor você altere rmem_max e rmem_default, exemplo:
sysctl -w net.core.rmem_max=524287 sysctl -w net.core.wmem_max=524287 sysctl -w net.core.rmem_default=524287 sysctl -w net.core.wmem_default=524287
Testando suas configurações
Pare o statsd e o aplicativo do nó e, com o sistema inativo, use o iperf para testar a taxa de pacotes que a rede / kernel pode manipular. Se você pode transmitir 40K pacotes / s com o iperf, mas não com o statsd, concentre seus esforços no ajuste do statsd.
Outros ajustáveis
Lembre-se também de ajustar net.core.netdev_max_backlog : número máximo de pacotes que podem enfileirar quando uma interface específica recebe pacotes mais rapidamente do que o kernel pode processá-los.
fonte