Qual parâmetro do kernel ou outras configurações controlam o número máximo de soquetes TCP que podem ser abertos em um servidor Linux? Quais são as vantagens de permitir mais conexões?
Percebi durante o teste de carga de um servidor Apache com ab que é muito fácil maximizar as conexões abertas no servidor. Se você deixar de fora a opção -k do ab, que permite a reutilização da conexão, e enviar mais de cerca de 10.000 solicitações, o Apache atenderá as primeiras 11.000 solicitações e, em seguida, interromperá por 60 segundos. Uma olhada na saída netstat mostra 11.000 conexões no estado TIME_WAIT. Aparentemente, isso é normal. As conexões são mantidas abertas por padrão de 60 segundos mesmo depois que o cliente termina com elas por motivos de confiabilidade do TCP .
Parece que esta seria uma maneira fácil de DoS um servidor e estou querendo saber quais são os ajustes e precauções usuais para isso.
Aqui está minha saída de teste:
# ab -c 5 -n 50000 http://localhost/
This is ApacheBench, Version 2.0.40-dev <$Revision: 1.146 $> apache-2.0
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright 2006 The Apache Software Foundation, http://www.apache.org/
Benchmarking localhost (be patient)
Completed 5000 requests
Completed 10000 requests
apr_poll: The timeout specified has expired (70007)
Total of 11655 requests completed
Aqui está o comando netstat que executo durante o teste:
# netstat --inet -p | grep "localhost:www" | sed -e 's/ \+/ /g' | cut -d' ' -f 1-4,6-7 | sort | uniq -c
11651 tcp 0 0 localhost:www TIME_WAIT -
1 tcp 0 1 localhost:44423 SYN_SENT 7831/ab
1 tcp 0 1 localhost:44424 SYN_SENT 7831/ab
1 tcp 0 1 localhost:44425 SYN_SENT 7831/ab
1 tcp 0 1 localhost:44426 SYN_SENT 7831/ab
1 tcp 0 1 localhost:44428 SYN_SENT 7831/ab
Finalmente encontrei a configuração que realmente limitava o número de conexões:
net.ipv4.netfilter.ip_conntrack_max
. Isso foi definido como 11.776 e o que quer que eu configure é o número de solicitações que posso atender no meu teste antes de ter que esperartcp_fin_timeout
segundos para que mais conexões fiquem disponíveis. Aconntrack
tabela é o que o kernel usa para rastrear o estado das conexões, então, quando estiver cheia, o kernel começará a descartar pacotes e imprimir isso no log:O próximo passo foi fazer com que o kernel reciclasse todas essas conexões no
TIME_WAIT
estado em vez de descartar pacotes. Eu poderia fazer isso acontecer ativandotcp_tw_recycle
ou aumentandoip_conntrack_max
para ser maior que o número de portas locais disponibilizadas para conexões peloip_local_port_range
. Eu acho que uma vez que o kernel está fora das portas locais, ele começa a reciclar as conexões. Isso usa mais conexões de rastreamento de memória, mas parece ser a melhor solução do que ligar,tcp_tw_recycle
pois os documentos implicam que isso é perigoso.Com esta configuração eu posso rodar ab o dia todo e nunca ficar sem conexões:
A
tcp_max_orphans
configuração não teve nenhum efeito nos meus testes e não sei por quê. Eu pensaria que fecharia as conexões noTIME_WAIT
estado uma vez que houvesse 8192 deles, mas não faz isso para mim.Você realmente quer ver o que o sistema de arquivos /proc tem a oferecer a esse respeito.
Nessa última página, você pode achar o seguinte de seu interesse:
Eu não acho que há um ajuste para definir isso diretamente. Isso se enquadra na categoria de ajuste TCP/IP. Para descobrir o que você pode ajustar, tente 'man 7 tcp'. O sysctl ( 'man 8 sysctl' ) é usado para definir isso. 'sysctl -a | grep tcp' mostrará a maior parte do que você pode ajustar, mas não tenho certeza se mostrará todos eles. Além disso, a menos que isso tenha mudado, os soquetes TCP/IP abertos se parecem com descritores de arquivo. Portanto, esta e a próxima seção nesse link podem ser o que você está procurando.
Tente configurar o seguinte também configurando tcp_fin_timeout. Isso deve encerrar TIME_WAIT mais rapidamente.
O estoque apache(1) costumava vir predefinido para suportar apenas 250 conexões simultâneas - se você quisesse mais, havia um arquivo de cabeçalho para modificar para permitir mais sessões simultâneas. Não sei se isso ainda é verdade com o Apache 2.
Além disso, você precisa adicionar uma opção para permitir cargas de descritores de arquivos mais abertos para a conta que executa o Apache - algo que os comentários anteriores não apontam.
Preste atenção às configurações do seu trabalhador e que tipo de tempo limite de manutenção de atividade você tem dentro do próprio Apache, quantos servidores sobressalentes você tem em execução ao mesmo tempo e com que rapidez esses processos extras estão sendo eliminados.
Você pode reduzir o tempo gasto no estado TIME_WAIT (Set net.ipv4.tcp_fin_timeout). Você pode substituir o Apache por YAWS ou nginx ou algo semelhante.
As compensações de mais conexões geralmente envolvem o uso de memória e, se você tiver um processo de bifurcação, muitos processos filhos que sobrecarregam sua CPU.
O número absoluto de soquetes que podem ser abertos em um único endereço IP é 2^16 e é definido pelo TCP/UDP, não pelo kernel.
A ferramenta de benchmarking do servidor Apache HTTP, ab , na versão 2.4 tem a opção -s timeout . Consulte também erro ab (Apache Bench): apr_poll: O tempo limite especificado expirou (70007) no Windows .
Esta opção resolve seu problema.