tcpdump aumenta o desempenho do udp

tcpdump aumenta o desempenho do udp

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)

Resumindo, 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. Em seguida, observo 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, percebi que às vezes obtinha taxas de queda de pacotes muito grandes (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, visto que 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 ocorreu essa queda. E é aqui que as coisas ficam estranhas.

estou a usartcpdumppara criar um arquivo de captura que eu inspeciono após a conclusão do teste. Mas sempre que executo os testes com o tcpdump rodando, a perda de pacotes é quase inexistente! Parece que o tcpdump está de alguma forma 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 40.000 métricas/s. O teste durante a execução do tcpdump tem uma perda de pacotes de cerca de 4%, enquanto aquele sem tem uma perda de pacotes de cerca de 20%.

Ambos os sistemas estão rodando como VMs Xen com a seguinte configuração:

  • Intel Xeon E5-2630 v2 a 2,60 GHz
  • 2 GB de RAM
  • Ubuntu 14.04 x86_64

Coisas que já verifiquei para possíveis causas:

  • Aumentando o tamanho de recebimento/envio do buffer UDP.
  • Carga da CPU afetando o teste. (carga máxima de 40-50%, tanto do lado do cliente quanto do servidor)
  • Executando o tcpdump em interfaces específicas em vez de 'qualquer'.
  • Executando 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 impactar os testes.
  • Executando o tcpdump apenas no cliente. Isso resultou em aumento de desempenho.
  • Aumentando netdev_max_backlog e netdev_budget para 2^32-1. Isto não fez diferença.
  • Tentei todas as configurações possíveis de modo promíscuo em cada nic (servidor ligado e cliente desligado, servidor desligado e cliente ligado, ambos ligados, ambos desligados). Isto não fez diferença.

Responder1

Quando o tcpdump estiver em execução, ele será bastante rápido na leitura dos quadros recebidos. Minha hipótese é que as configurações do buffer de anel de pacotes da NIC podem ser um pouco pequenas; quando o tcpdump está em execução, ele é esvaziado de maneira mais oportuna.

Se você é assinante da Red Hat, este artigo de suporte é muito útilVisão geral da recepção de pacotes. Tem algumas coisas aí 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, há problemas/soluções alternativas conhecidas em relação à escalabilidade).

Aumente o buffer de quadros da NIC (usando o ethtoolcomando - veja os --set-ringargumentos etc.).

Observe o 'escalamento lateral de recebimento' e use pelo menos esse número de threads de recebimento para ler o tráfego.

Eu me pergunto se o tcpdump está fazendo algo legal, como usar o suporte do kernel parabuffers de anel de pacotes. Isso ajudaria a explicar o comportamento que você está vendo.

Responder2

Qual governador de energia você está usando? Já vi comportamentos semelhantes com governadores “sob demanda” ou “conservadores”.

Tente usar o regulador de "desempenho" e desabilitar quaisquer recursos de economia de energia no BIOS do servidor.

Isso muda alguma coisa?

Responder3

Outra forma é ip_conntarcko módulo. Tem certeza de que sua caixa Linux pode aceitar uma nova conexão? teste através de:

root@debian:/home/mohsen# sysctl net.ipv4.netfilter.ip_conntrack_max
net.ipv4.netfilter.ip_conntrack_max = 65536
root@debian:/home/mohsen# sysctl  net.ipv4.netfilter.ip_conntrack_count
net.ipv4.netfilter.ip_conntrack_count = 29

Você tem que testar

net.ipv4.netfilter.ip_conntrack_max >  net.ipv4.netfilter.ip_conntrack_count

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 ip_conntrack, você pode carregar facilmente viamodprobe ip_conntrack

Responder4

Suspeito que o lado receptor simplesmente não seja capaz de lidar com a taxa de pacotes e aqui está o porquê:

  1. usando tcpdumpno clientereduz os pacotes descartados: o tcpdump está deixando o cliente mais lento e, portanto, o servidor está vendo uma taxa de empacotamento muito mais baixa, que ainda pode controlar parcialmente. Você deve ser capaz de confirmar esta hipótese verificando os contadores de pacotes RX/TX no cliente e no servidor

  2. você mencionou que aumentou o tamanho de recebimento/envio do buffer UDP, poderia detalhar como? É importante que no servidor você altere tanto rmem_maxermem_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, em seguida, com o uso ocioso do sistemaperfeitopara testar a taxa de pacotes que a rede/kernel pode suportar. Se você consegue transmitir pacotes/s de 40K com o iperf, mas não consegue com o statsd, então você deve concentrar seus esforços no ajuste do statsd.

Outros ajustáveis

Lembre-se também de sintonizarnet.core.netdev_max_backlog: número máximo de pacotes permitidos na fila quando uma determinada interface recebe pacotes mais rápido do que o kernel pode processá-los.

informação relacionada