Como reduzir o número de soquetes em TIME_WAIT?

36

Ubuntu Server 10.04.1 x86

Eu tenho uma máquina com um serviço HTTP FCGI por trás do nginx, que atende a muitas solicitações HTTP pequenas para vários clientes diferentes. (Cerca de 230 solicitações por segundo nos horários de pico, o tamanho médio da resposta com cabeçalhos é de 650 bytes, vários milhões de clientes diferentes por dia.)

Como resultado, tenho muitos soquetes pendurados em TIME_WAIT (o gráfico é capturado com as configurações TCP abaixo):

TEMPO DE ESPERA

Eu gostaria de reduzir o número de soquetes.

O que posso fazer além disso?

$ cat / proc / sys / net / ipv4 / tcp_fin_timeout
1
$ cat / proc / sys / net / ipv4 / tcp_tw_recycle
1
$ cat / proc / sys / net / ipv4 / tcp_tw_reuse
1

Atualização: alguns detalhes sobre o layout de serviço real na máquina:

cliente ----- Soquete TCP -> nginx (proxy reverso do balanceador de carga) 
       ----- Soquete TCP -> nginx (trabalhador) 
       --domain-socket -> fcgi-software
                          --single-persistent-TCP-socket -> Redis
                          --single-persistent-TCP-socket -> MySQL (outra máquina)

Provavelmente eu deveria alternar o balanceador de carga -> a conexão do trabalhador com os soquetes do domínio, mas o problema sobre os soquetes TIME_WAIT permaneceria - planejo adicionar um segundo trabalhador em uma máquina separada em breve. Nesse caso, não será possível usar soquetes de domínio.

Alexander Gladysh
fonte
Parece que Munin está mentindo descaradamente. Veja comentários à resposta de Kyle. Olhando para isso agora.
Alexander Gladysh
1
Criou uma pergunta sobre Munin: serverfault.com/questions/212200/…
Alexander Gladysh
Agora parece que Munin não está mentindo, mas estou olhando para o enredo errado ...
Alexander Gladysh

Respostas:

28

Uma coisa que você deve fazer para começar é consertar o arquivo net.ipv4.tcp_fin_timeout=1. Isso é muito baixo, você provavelmente não deve levar muito menos do que 30.

Uma vez que isso está por trás do nginx. Isso significa que o nginx está atuando como um proxy reverso? Se for esse o caso, suas conexões são 2x (uma para o cliente e outra para os servidores da web). Você sabe a que extremidade esses soquetes pertencem?

Atualização:
fin_timeout é quanto tempo eles permanecem no FIN-WAIT-2 (De networking/ip-sysctl.txtna documentação do kernel):

tcp_fin_timeout - INTEGER
        Time to hold socket in state FIN-WAIT-2, if it was closed
        by our side. Peer can be broken and never close its side,
        or even died unexpectedly. Default value is 60sec.
        Usual value used in 2.2 was 180 seconds, you may restore
        it, but remember that if your machine is even underloaded WEB server,
        you risk to overflow memory with kilotons of dead sockets,
        FIN-WAIT-2 sockets are less dangerous than FIN-WAIT-1,
        because they eat maximum 1.5K of memory, but they tend
        to live longer. Cf. tcp_max_orphans.

Eu acho que você talvez apenas precise deixar o Linux manter o número do soquete TIME_WAIT em comparação com o que parece ser talvez um limite de 32k neles e é aqui que o Linux os recicla. Este 32k é mencionado neste link :

Além disso, acho os / proc / sys / net / ipv4 / tcp_max_tw_buckets confusos. Embora o padrão seja definido como 180000, vejo uma interrupção do TCP quando tenho soquetes 32K TIME_WAIT no meu sistema, independentemente dos intervalos máximos de tw.

Esse link também sugere que o estado TIME_WAIT é de 60 segundos e não pode ser ajustado via proc.


Curiosidade : Você pode ver os timers no timewait com netstat para cada soquete comnetstat -on | grep TIME_WAIT | less

Reutilizar versus reciclar:
são interessantes, parece que a reutilização permite a reutilização de soquetes time_Wait e a reciclagem o coloca no modo TURBO:

tcp_tw_recycle - BOOLEAN
        Enable fast recycling TIME-WAIT sockets. Default value is 0.
        It should not be changed without advice/request of technical
        experts.

tcp_tw_reuse - BOOLEAN
        Allow to reuse TIME-WAIT sockets for new connections when it is
        safe from protocol viewpoint. Default value is 0.
        It should not be changed without advice/request of technical
        experts.

Eu não recomendaria o uso de net.ipv4.tcp_tw_recycle, pois isso causa problemas com os clientes NAT .

Talvez você tente não ativar os dois e ver qual é o efeito (tente um de cada vez e veja como eles funcionam por conta própria)? Eu usaria netstat -n | grep TIME_WAIT | wc -lpara um feedback mais rápido do que Munin.

Kyle Brandt
fonte
1
@ Kyle: que valor net.ipv4.tcp_fin_timeoutvocê recomendaria?
Alexander Gladysh
1
@Kyle: client --TCP-socket -> nginx (proxy reverso do balanceador de carga) --TCP-socket -> nginx (worker) --domain-socket -> fcgi-software
Alexander Gladysh
2
Eu diria 30ou talvez 20. Experimente e veja. Você tem muita carga, então muito TIME_WAIT faz sentido.
Kyle Brandt
1
@ Kyle: desculpe por uma pergunta estúpida (infelizmente estou em um nível de culto de carga até agora, infelizmente), mas o que exatamente devo esperar quando mudar net.ipv4.tcp_fin_timeoutde 1para 20?
Alexander Gladysh
4
Oh, aqui está um forro de um agradável: netstat -an|awk '/tcp/ {print $6}'|sort|uniq -c. Então, @Alex, se Munin não gostar, talvez veja como ele monitora essas estatísticas. Talvez o único problema é que Munin está dando-lhe dados ruins :-)
Kyle Brandt
1

O tcp_tw_reuse é relativamente seguro, pois permite que as conexões TIME_WAIT sejam reutilizadas.

Além disso, você pode executar mais serviços ouvindo em portas diferentes atrás do seu balanceador de carga se ficar sem portas é um problema.

andrew pate
fonte