HAProxy + nginx atingindo numtcpsock máximo em cerca de 24 horas

2

Estou executando um VPS relativamente simples (um Media Temple (ve)) com alguns sites baseados em PHP e (eventualmente) alguns Node servidores. Para habilitar o suporte a WebSockets, estou usando o HAProxy na porta 80, que direciona para o nginx ou para um processo específico do Node.

Recentemente tive um problema, no qual, ao longo de cerca de 24 horas, meu servidor atinge o número máximo permitido de conexões TCP abertas ( numtcpsock no Parallels Power Panel, que é definido como 1.000). Executar o nginx sozinho não causa esse problema e atualmente não tenho servidores de backend do nó ativos. O Nginx se conecta ao PHP através de um soquete de domínio UNIX (e, novamente, o problema não ocorre apenas com o nginx). Qualquer pensamento sobre o que poderia causar isso? Minha configuração:

global
    ## 00-base
    maxconn     500
    nbproc      2
defaults
    ## 00-base
    mode        http
frontend all
    ## 00-ports
    bind 0.0.0.0:80
    ## 10-config
    timeout client 86400000
    default_backend nginx
backend nginx
    ## 00-timeouts
    timeout http-keep-alive 5000
    timeout server 10000
    timeout connect 4000
    ## 10-servers
    server main localhost:8000

Obrigado antecipadamente!

UPDATE : depois de um pouco de lsof ing, eu consegui determinar que mais de 90% dos soquetes TCP abertos são de fato de propriedade do HAProxy, e a esmagadora maioria deles são nos estados CLOSE_WAIT ou FIN_WAIT2 . Isso é um bug HAProxy? Parece um vazamento de descritor de arquivo de algum tipo, a menos que seja um erro de configuração da minha parte.

UPDATE 2 : notei um padrão na saída lsof . Parece-me que o que está acontecendo é que o nginx está fechando uma conexão interna com o HAProxy, mas antes que o HAProxy feche formalmente, ele tenta fechar a conexão externa com o cliente (colocando-o em FIN_WAIT2 ). Como o FIN nunca vem, a conexão entre nginx e HAProxy permanece em CLOSE_WAIT para sempre. Agora a única pergunta é: por que isso está acontecendo?

    
por Matt Patenaude 21.05.2012 / 00:36

2 respostas

1

O problema é causado pelo seu tempo limite extremamente grande. Com um tempo limite de 24 horas e um limite para 1.000 conexões simultâneas, você pode claramente esperar que isso seja preenchido com clientes desconectando a maneira suja. Por favor, use um tempo limite mais razoável, de minutos a horas, no máximo, não faz sentido usar tempos limite de 1 dia na internet. Como o DukeLion disse, o sistema está aguardando o haproxy fechar a conexão, porque o haproxy não recebeu o fechamento do cliente.

Haproxy está trabalhando em modo de túnel para TCP e WebSocket, segue o usual 4-way close:

- receive a close on side A
- forward the close on side B
- receive the close on side B
- forward the close on side A

No seu caso, suponho que o lado A seja o servidor e o lado B o cliente. Então nginx fechou depois de algum tempo, soquete foi para CLOSE_WAIT, haproxy encaminhou o fechamento para o cliente, esse soquete foi para FIN_WAIT1, o cliente ACKed, passando o soquete para FIN_WAIT2 e então nada acontece porque o cliente desapareceu, o que é algo muito comum na rede. E o seu tempo limite significa que você quer que isso continue assim por 24 horas.

Após 24 horas, suas sessões começarão a exceder o tempo no lado do cliente, então o haproxy irá matá-las e encaminhará o próximo ao lado do nginx, livrando-se dele também. Mas, claramente, você não quer que isso aconteça, o WebSocket foi projetado para que a conexão inativa possa ser reaberta de maneira transparente, portanto, não há motivo para manter uma conexão inativa aberta por 24 horas. Nenhum firewall irá mantê-lo ao longo do caminho!

    
por 21.05.2012 / 23:17
1

muitos soquetes em CLOSE_WAIT são extremamente ruins para o seu servidor. Isso acontece quando o kernel aguarda que o software userspace aceite o fechamento de soquete. Se muitos soquetes permanecerem nesse estado por um longo tempo - significa que o software que o utiliza não responde. Normalmente, o socket neste estado consome uma quantidade relativamente alta de tempo de CPU do kernel.

Suponho que CLOSE_WAITs no seu caso seja secundário a FIN_WAIT2 - o HAproxy está aguardando a conexão do cliente para fechar e fechar a conexão com o NGINX logo após isso.

FIN_WAIT2 é o estado de espera do outro lado para confirmar o fechamento do soquete. Não é tão ruim ter muitos deles, mas pode indicar congestionamento na rede ou grandes perdas.

Você pode tentar a opção nolinger com haproxy para fechar a conexão mais rapidamente. Mas tenha cuidado, isso vai quebrar o mecanismo tcp de entrega garantida.

    
por 21.05.2012 / 07:03