Melhorando o desempenho do TCP em uma rede gigabit com muitas conexões e alto tráfego de pacotes pequenos

37

Estou tentando melhorar minha taxa de transferência TCP através de uma "rede gigabit com muitas conexões e alto tráfego de pacotes pequenos". O SO do meu servidor é o Ubuntu 11.10 Server 64bit.

Existem cerca de 50.000 (e em crescimento) clientes conectados ao meu servidor por meio de soquetes TCP (todos na mesma porta).

95% dos meus pacotes têm tamanho de 1 a 150 bytes (cabeçalho TCP e carga útil). Os 5% restantes variam de 150 a 4096+ bytes.

Com a configuração abaixo, meu servidor pode lidar com tráfego de até 30 Mbps (full duplex).

Você pode aconselhar as melhores práticas para ajustar o SO de acordo com minhas necessidades?

Minha /etc/sysctl.congaparência é assim:

kernel.pid_max = 1000000
net.ipv4.ip_local_port_range = 2500 65000
fs.file-max = 1000000
#
net.core.netdev_max_backlog=3000
net.ipv4.tcp_sack=0
#
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.core.somaxconn = 2048
#
net.ipv4.tcp_rmem = 4096 87380 16777216 
net.ipv4.tcp_wmem = 4096 65536 16777216
#
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_mem = 50576   64768   98152
#
net.core.wmem_default = 65536
net.core.rmem_default = 65536
net.ipv4.tcp_window_scaling=1
#
net.ipv4.tcp_mem= 98304 131072 196608
#
net.ipv4.tcp_timestamps = 0
net.ipv4.tcp_rfc1337 = 1
net.ipv4.ip_forward = 0
net.ipv4.tcp_congestion_control=cubic
net.ipv4.tcp_tw_recycle = 0
net.ipv4.tcp_tw_reuse = 0
#
net.ipv4.tcp_orphan_retries = 1
net.ipv4.tcp_fin_timeout = 25
net.ipv4.tcp_max_orphans = 8192

Aqui estão os meus limites:

$ ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 193045
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1000000
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 1000000

[ADICIONADO]

Minhas NICs são as seguintes:

$ dmesg | grep Broad
[    2.473081] Broadcom NetXtreme II 5771x 10Gigabit Ethernet Driver bnx2x 1.62.12-0 (2011/03/20)
[    2.477808] bnx2x 0000:02:00.0: eth0: Broadcom NetXtreme II BCM57711E XGb (A0) PCI-E x4 5GHz (Gen2) found at mem fb000000, IRQ 28, node addr d8:d3:85:bd:23:08
[    2.482556] bnx2x 0000:02:00.1: eth1: Broadcom NetXtreme II BCM57711E XGb (A0) PCI-E x4 5GHz (Gen2) found at mem fa000000, IRQ 40, node addr d8:d3:85:bd:23:0c

[ADICIONADO 2]

ethtool -k eth0
Offload parameters for eth0:
rx-checksumming: on
tx-checksumming: on
scatter-gather: on
tcp-segmentation-offload: on
udp-fragmentation-offload: off
generic-segmentation-offload: on
generic-receive-offload: on
large-receive-offload: on
rx-vlan-offload: on
tx-vlan-offload: on
ntuple-filters: off
receive-hashing: off

[ADICIONADO 3]

 sudo ethtool -S eth0|grep -vw 0
 NIC statistics:
      [1]: rx_bytes: 17521104292
      [1]: rx_ucast_packets: 118326392
      [1]: tx_bytes: 35351475694
      [1]: tx_ucast_packets: 191723897
      [2]: rx_bytes: 16569945203
      [2]: rx_ucast_packets: 114055437
      [2]: tx_bytes: 36748975961
      [2]: tx_ucast_packets: 194800859
      [3]: rx_bytes: 16222309010
      [3]: rx_ucast_packets: 109397802
      [3]: tx_bytes: 36034786682
      [3]: tx_ucast_packets: 198238209
      [4]: rx_bytes: 14884911384
      [4]: rx_ucast_packets: 104081414
      [4]: rx_discards: 5828
      [4]: rx_csum_offload_errors: 1
      [4]: tx_bytes: 35663361789
      [4]: tx_ucast_packets: 194024824
      [5]: rx_bytes: 16465075461
      [5]: rx_ucast_packets: 110637200
      [5]: tx_bytes: 43720432434
      [5]: tx_ucast_packets: 202041894
      [6]: rx_bytes: 16788706505
      [6]: rx_ucast_packets: 113123182
      [6]: tx_bytes: 38443961940
      [6]: tx_ucast_packets: 202415075
      [7]: rx_bytes: 16287423304
      [7]: rx_ucast_packets: 110369475
      [7]: rx_csum_offload_errors: 1
      [7]: tx_bytes: 35104168638
      [7]: tx_ucast_packets: 184905201
      [8]: rx_bytes: 12689721791
      [8]: rx_ucast_packets: 87616037
      [8]: rx_discards: 2638
      [8]: tx_bytes: 36133395431
      [8]: tx_ucast_packets: 196547264
      [9]: rx_bytes: 15007548011
      [9]: rx_ucast_packets: 98183525
      [9]: rx_csum_offload_errors: 1
      [9]: tx_bytes: 34871314517
      [9]: tx_ucast_packets: 188532637
      [9]: tx_mcast_packets: 12
      [10]: rx_bytes: 12112044826
      [10]: rx_ucast_packets: 84335465
      [10]: rx_discards: 2494
      [10]: tx_bytes: 36562151913
      [10]: tx_ucast_packets: 195658548
      [11]: rx_bytes: 12873153712
      [11]: rx_ucast_packets: 89305791
      [11]: rx_discards: 2990
      [11]: tx_bytes: 36348541675
      [11]: tx_ucast_packets: 194155226
      [12]: rx_bytes: 12768100958
      [12]: rx_ucast_packets: 89350917
      [12]: rx_discards: 2667
      [12]: tx_bytes: 35730240389
      [12]: tx_ucast_packets: 192254480
      [13]: rx_bytes: 14533227468
      [13]: rx_ucast_packets: 98139795
      [13]: tx_bytes: 35954232494
      [13]: tx_ucast_packets: 194573612
      [13]: tx_bcast_packets: 2
      [14]: rx_bytes: 13258647069
      [14]: rx_ucast_packets: 92856762
      [14]: rx_discards: 3509
      [14]: rx_csum_offload_errors: 1
      [14]: tx_bytes: 35663586641
      [14]: tx_ucast_packets: 189661305
      rx_bytes: 226125043936
      rx_ucast_packets: 1536428109
      rx_bcast_packets: 351
      rx_discards: 20126
      rx_filtered_packets: 8694
      rx_csum_offload_errors: 11
      tx_bytes: 548442367057
      tx_ucast_packets: 2915571846
      tx_mcast_packets: 12
      tx_bcast_packets: 2
      tx_64_byte_packets: 35417154
      tx_65_to_127_byte_packets: 2006984660
      tx_128_to_255_byte_packets: 373733514
      tx_256_to_511_byte_packets: 378121090
      tx_512_to_1023_byte_packets: 77643490
      tx_1024_to_1522_byte_packets: 43669214
      tx_pause_frames: 228

Algumas informações sobre o SACK: Quando desativar o TCP SACK?

Trabalhador
fonte
Qual é o fator limitante? Sua CPU atinge o limite máximo? Nesse caso, você está latindo na árvore errada. Você precisa ver o que a CPU está fazendo.
David Schwartz
Qual placa de rede você possui?
SaveTheRbtz
1
BTW: Por que você desativa o SACK?
Nils
1
Você deveria reconsiderar usando Broadcom NICs ...
Hubert Kario

Respostas:

21

O problema pode ser que você esteja recebendo muitas interrupções na sua placa de rede. Se a largura de banda não for o problema, a frequência é o problema:

  • Ativar buffers de envio / recebimento na placa de rede

    ethtool -g eth0
    

Mostrará as configurações atuais (256 ou 512 entradas). Você provavelmente pode aumentá-las para 1024, 2048 ou 3172. Mais provavelmente não faz sentido. Este é apenas um buffer de anel que só é preenchido se o servidor não puder processar pacotes de entrada com rapidez suficiente.

Se o buffer começar a encher, o controle de fluxo é um meio adicional de dizer ao roteador ou ao switch para diminuir a velocidade:

  • Ative o controle de fluxo de entrada / saída no servidor e as portas do switch / roteador às quais está conectado.

    ethtool -a eth0
    

Provavelmente mostrará:

Pause parameters for eth0:
Autonegotiate:  on
RX:             on
TX:             on

Verifique / var / log / messages para a configuração atual de eth0. Verifique algo como:

eth0: O link está ativo em 1000 Mbps, full duplex, controle de fluxo tx e rx

Se você não vê tx e rx, os administradores da rede precisam ajustar os valores no switch / roteador. Na Cisco, o controle de fluxo de recepção / transmissão está ativado.

Cuidado: alterar esses valores reduzirá e aumentará seu link por um período muito curto (menos de 1s).

  • Se tudo isso não ajudar - você também pode diminuir a velocidade da placa de rede para 100 MBit (faça o mesmo nas portas do switch / roteador)

    ethtool -s eth0 autoneg off && ethtool -s eth0 speed 100
    

Mas no seu caso, eu diria - aumente os buffers de recebimento no buffer de anel da NIC.

Nils
fonte
Olhando para os seus números, ethtooleu diria - defina os buffers de recebimento da placa de rede ao máximo para evitar as devoluções do RX. Espero que o seu Broadcom tenha o suficiente.
Nils
1
Aumentar o buffer com o TCP quase nunca é uma boa idéia. Já temos buffer demais: bufferbloat.net/projects/bloat/wiki/Introduction
rmalayter
3
Esse buffer é um buffer de hardware diretamente na NIC. Vou atualizar minha resposta com mais detalhes. Como você está perdendo pacotes recebidos, você precisa desse buffer. Eu tenho um servidor semelhante no qual tive que mudar para uma NIC diferente (da Broadcom integrada à PCIe Intel) para poder aumentar esses buffers. Depois disso, nunca mais encontrei pacotes RX perdidos.
Nils
@malayter: este é um buffer de anel na camada 2. Veja minha resposta atualizada.
Nils
1
Finalmente, temos 1 GB. Havia muita sintonia em lugares diferentes, então não posso realmente dizer que havia um único problema.
trabalhador
5

A seguir, pode não ser a resposta definitiva, mas certamente apresentará algumas idéias

Tente adicioná-los ao sysctl.conf

##  tcp selective acknowledgements. 
net.ipv4.tcp_sack = 1
##enable window scaling
net.ipv4.tcp_window_scaling = 1
##
net.ipv4.tcp_no_metrics_save = 1

Embora o tcp ack seletivo seja bom para o desempenho ideal no caso de rede de alta largura de banda. Mas tenha cuidado com outras desvantagens . Os benefícios do dimensionamento de janelas são descritos aqui . Quanto à terceira opção sysctl: Por padrão, o TCP salva várias métricas de conexão no cache de rota quando a conexão é fechada, para que as conexões estabelecidas em um futuro próximo possam usá-las para definir condições iniciais. Geralmente, isso aumenta o desempenho geral, mas às vezes pode causar degradação no desempenho. Se definido, o TCP não armazenará métricas em cache ao fechar as conexões.

Verificar com

ethtool -k ethX

para ver se o descarregamento está ativado ou não. A descarga de soma de verificação TCP e a descarga de grandes segmentos são suportadas pela maioria das NICs Ethernet atuais e, aparentemente, a Broadcom também suporta.

Tente usar a ferramenta

powertop

enquanto a rede estiver ociosa e quando a saturação da rede for atingida. Definitivamente, isso mostrará se as interrupções da NIC são as culpadas. A pesquisa de dispositivos é uma resposta para essa situação. O FreeBsd suporta a opção de polling dentro do ifconfig, mas o linux não tem essa opção. Consulte isso para ativar a pesquisa. Está dizendo que o BroadCom também suporta pesquisas, o que é uma boa notícia para você.

O ajuste de pacotes jumbo pode não ser bom para você, pois você mencionou que o tráfego consiste principalmente em pacotes pequenos. Mas ei, experimente mesmo assim!

kaji
fonte
2kaji, vou tentar suas sugestões amanhã. Sobre o PowerTop - devo ajustar a economia de energia se meu objetivo for desempenho?
trabalhador
Sim, claro, isso também pode ajudar. Mencionei Powertop apenas para ter certeza de que as interrupções são más. Interrupções frequência também poderia ser colhida a partir de outras ferramentas
Kaji
Vejo altas "Interrupções de reagendamento" - poderia ser uma razão? O que é "Reagendar interrupções"?
trabalhador
Sim. Eu vi esse tutorial, mas é para laptops enquanto vejo altas interrupções no servidor. Tentará aplicá-lo ao servidor.
trabalhador
2

você precisa distribuir a carga por todos os núcleos da CPU. Inicie 'irqbalance'.

user175978
fonte
1
Isso não ajudará se um único IRQ tiver uma frequência muito alta. O IRQBalance tenta distribuir IRQs únicos para adequar aos processadores lógicos - mas nunca haverá mais de um processador atendendo a um único IRQ.
Nils
2

Notei na lista de ajustes que os carimbos de data / hora estão desativados, por favor, não faça isso. Isso é uma antiga reminiscência nos dias de outrora, quando a largura de banda era muito cara e as pessoas queriam economizar alguns bytes / pacote. Atualmente, é usado, por exemplo, pela pilha TCP para saber se um pacote que chega para um soquete em "CLOSE_WAIT" é um pacote antigo para a conexão ou se é um novo pacote para uma nova conexão e ajuda nos cálculos de RTT. E salvar os poucos bytes para um carimbo de data / hora é NADA comparado aos endereços IPv6 que serão adicionados. Desativar carimbos de data e hora faz mais mal do que bem.

Esta recomendação para desativar os carimbos de data e hora é apenas uma reminiscência que continua sendo passada de uma geração de administrador de sistemas para a seguinte. Uma espécie de "lenda urbana".

GeorgeB
fonte
2

Eu proponho isso:

kernel.sem = 350 358400 64 1024
net.core.rmem_default = 262144
net.core.rmem_max = 4194304
net.core.wmem_default = 262144
net.core.wmem_max = 4194304
net.ipv4.tcp_window_scaling = 1
net.ipv4.tcp_adv_win_scale = 2
net.ipv4.tcp_moderate_rcvbuf = 1
net.ipv4.tcp_rmem = 4096 262144 4194304
net.ipv4.tcp_wmem = 4096 262144 4194304
net.ipv4.tcp_keepalive_time = 900
net.ipv4.tcp_keepalive_intvl = 900
net.ipv4.tcp_keepalive_probes = 9

Testado em servidores Oracle DB no RHEL e em software de backup.

Konrad Puchała
fonte
5
Esses números são configuráveis ​​porque não existe um modelo único. Isso significa que os números em si não são valiosos. O que poderia ser valioso é o método que você usou para decidir sobre quais números usar.
kasperd
2

No meu caso, apenas um único ajuste:

net.ipv4.tcp_timestamps = 0

fez uma alteração muito grande e útil, o tempo de carregamento do site diminuiu 50%.

avz2012
fonte
Algo deve estar gravemente quebrado na sua configuração para que isso aconteça. Os carimbos de data / hora usam menos de 1% da largura de banda em circunstâncias normais e permitem que o TCP faça retransmissões com muito mais tempo do que o contrário.
kasperd