Aumentando o número máximo de conexões tcp / ip no linux

Estou programando um servidor e parece que meu número de conexões está sendo limitado, já que minha largura de banda não está saturada, mesmo quando defini o número de conexões como “ilimitado”.

Como posso aumentar ou eliminar um número máximo de conexões que minha checkbox do Ubuntu Linux pode abrir de cada vez? O SO limita isso, ou é o roteador ou o ISP? Ou é outra coisa?

O número máximo de conexões é afetado por certos limites no lado do cliente e do servidor, embora um pouco diferente.

No lado do cliente: Aumente o intervalo de portas epérmicas e diminua o tcp_fin_timeout

Para descobrir os valores padrão:

 sysctl net.ipv4.ip_local_port_range sysctl net.ipv4.tcp_fin_timeout 

O intervalo de portas ephérmicas define o número máximo de sockets de saída que um host pode criar a partir de um endereço IP específico. O fin_timeout define o tempo mínimo que esses sockets permanecerão no estado TIME_WAIT (inutilizável depois de ser usado uma vez). Os padrões usuais do sistema são:

  • net.ipv4.ip_local_port_range = 32768 61000
  • net.ipv4.tcp_fin_timeout = 60

Isso basicamente significa que seu sistema não pode garantir consistentemente mais de (61000 - 32768) / 60 = 470 sockets por segundo. Se você não está feliz com isso, você pode começar aumentando o port_range . Definir o intervalo para 15000 61000 é bastante comum nos dias de hoje. Você pode aumentar ainda mais a disponibilidade diminuindo o fin_timeout . Suponha que você faça as duas coisas e verá mais de 1500 conexões de saída por segundo, mais prontamente.

Para alterar os valores :

 sysctl net.ipv4.ip_local_port_range="15000 61000" sysctl net.ipv4.tcp_fin_timeout=30 

O acima não deve ser interpretado como os fatores que afetam a capacidade do sistema de fazer conexões de saída por segundo. Mas, em vez disso, esses fatores afetam a capacidade do sistema de lidar com conexões simultâneas de maneira sustentável por grandes períodos de “atividade”.

Os valores padrão de Sysctl em uma checkbox linux típica para tcp_tw_recycle & tcp_tw_reuse seriam

 net.ipv4.tcp_tw_recycle=0 net.ipv4.tcp_tw_reuse=0 

Eles não permitem uma conexão de um soquete “usado” (no estado de espera) e forçam os sockets a durarem o ciclo completo de time_wait . Eu recomendo definir:

 sysctl net.ipv4.tcp_tw_recycle=1 sysctl net.ipv4.tcp_tw_reuse=1 

Isso permite um ciclo rápido de sockets no estado time_wait e reutilizando-os. Mas antes de fazer essa alteração, certifique-se de que isso não esteja em conflito com os protocolos que você usaria para o aplicativo que precisa desses sockets.

No lado do servidor: O valor de net.core.sumxconn tem uma function importante. Ele limita o número máximo de solicitações enfileiradas em um soquete de escuta. Se você tem certeza da capacidade do seu aplicativo de servidor, aumente do padrão 128 para algo como 128 a 1024. Agora você pode aproveitar esse aumento modificando a variável listen backlog na chamada de escuta do seu aplicativo, para um inteiro igual ou maior.

 sysctl net.core.sumxconn=1024 

txqueuelen parâmetro txqueuelen das suas placas ethernet também tem um papel a desempenhar. Os valores padrão são 1000, então aumente para 5000 ou até mais se o seu sistema puder lidar com isso.

 ifconfig eth0 txqueuelen 5000 echo "/sbin/ifconfig eth0 txqueuelen 5000" >> /etc/rc.local 

Da mesma forma, net.ipv4.tcp_max_syn_backlog os valores para net.core.netdev_max_backlog e net.ipv4.tcp_max_syn_backlog . Seus valores padrão são 1000 e 1024, respectivamente.

 sysctl net.core.netdev_max_backlog=2000 sysctl net.ipv4.tcp_max_syn_backlog=2048 

Agora lembre-se de iniciar tanto o cliente quanto os aplicativos do lado do servidor, aumentando os ulimts FD no shell.

Além do acima, uma técnica mais popular usada pelos programadores é reduzir o número de chamadas de gravação de tcp . Minha própria preferência é usar um buffer no qual eu envio os dados que desejo enviar para o cliente e, em seguida, em pontos apropriados, escrevo os dados armazenados em buffer no soquete real. Essa técnica me permite usar pacotes de dados grandes, reduzir a fragmentação, reduzir minha utilização de CPU tanto no nível do usuário quanto no nível do kernel.

Existem algumas variables ​​para definir o número máximo de conexões. Provavelmente, você está ficando sem números de arquivos primeiro. Marque ulimit -n. Depois disso, existem configurações em / proc, mas as padrão são as dezenas de milhares.

Mais importante, parece que você está fazendo algo errado. Uma única conexão TCP deve ser capaz de usar toda a largura de banda entre duas partes; se não for:

  • Verifique se a configuração da janela TCP é grande o suficiente. Os padrões do Linux são bons para tudo, exceto links inet realmente rápidos (centenas de mbps) ou links rápidos via satélite. Qual é o seu produto de atraso de largura de banda *?
  • Verifique se há perda de pacotes usando ping com pacotes grandes ( ping -s 1472 …)
  • Verifique a limitação de taxa. No Linux, isso é configurado com tc
  • Confirme que a largura de banda que você acha que existe realmente existe usando, por exemplo, iperf
  • Confirme se o seu protocolo é são. Lembre-se de latência.
  • Se esta for uma LAN + gigabit, você pode usar pacotes gigantes? Você está?

Possivelmente eu tenha entendido mal. Talvez você esteja fazendo algo como Bittorrent, onde você precisa de muitas conexões. Se assim for, você precisa descobrir quantas conexões você realmente está usando (tente netstat ou lsof ). Se esse número for substancial, você poderá:

  • Tem muita largura de banda, por exemplo, 100mbps +. Nesse caso, você pode precisar atualizar o ulimit -n . Ainda assim, ~ 1000 conexões (padrão no meu sistema) são muito poucas.
  • Tem problemas de rede que estão retardando suas conexões (por exemplo, perda de pacotes)
  • Faça com que algo mais o atrapalhe, por exemplo, largura de banda de IO, especialmente se você estiver procurando. Você verificou iostat -x ?

Além disso, se você estiver usando um roteador NAT de nível de consumidor (Linksys, Netgear, DLink, etc.), tenha cuidado para não exceder suas capacidades com milhares de conexões.

Espero que isso forneça alguma ajuda. Você está realmente perguntando uma questão de rede.

Para melhorar a resposta dada por derobert,

Você pode determinar qual é o limite de conexão do sistema operacional, atribuindo nf_conntrack_max.

Por exemplo: cat / proc / sys / net / netfilter / nf_conntrack_max

Você pode usar o seguinte script para contar o número de conexões tcp para um determinado intervalo de portas tcp. Por padrão, 1-65535.

Isso confirmará se você está ou não maximizando o limite de conexão do sistema operacional.

Aqui está o roteiro.

 #!/bin/bash OS=$(uname) case "$OS" in 'SunOS') AWK=/usr/bin/nawk ;; 'Linux') AWK=/bin/awk ;; 'AIX') AWK=/usr/bin/awk ;; esac netstat -an | $AWK -v start=1 -v end=65535 ' $NF ~ /TIME_WAIT|ESTABLISHED/ && $4 !~ /127\.0\.0\.1/ { if ($1 ~ /\./) {sip=$1} else {sip=$4} if ( sip ~ /:/ ) {d=2} else {d=5} split( sip, a, /:|\./ ) if ( a[d] >= start && a[d] < = end ) { ++connections; } } END {print connections}' 

Em um nível de aplicativo, aqui está algo que um desenvolvedor pode fazer:

Do lado do servidor:

  1. Verifique se o balanceador de carga (se você tiver) funciona corretamente.

  2. Transforme os tempos limite de TCP lentos em 503 rápida resposta imediata, se você carregar o trabalho do balanceador corretamente, ele deve escolher o recurso de trabalho a ser exibido e é melhor do que ficar suspenso com massagens de erro inesperadas.

Por exemplo: Se você estiver usando o servidor do nó, você pode usar toobusy do npm. Implementação algo como:

 var toobusy = require('toobusy'); app.use(function(req, res, next) { if (toobusy()) res.send(503, "I'm busy right now, sorry."); else next(); }); 

Por que 503? Aqui estão alguns bons insights para sobrecarga: http://ferd.ca/queues-don-t-fix-overload.html

Podemos fazer algum trabalho no lado do cliente também:

  1. Tente agrupar as chamadas em lote, reduzir o tráfego e o número total de solicitações do cliente e servidor.

  2. Tente criar uma camada intermediária de cache para lidar com solicitações de duplicatas desnecessárias.