Alto número de soquetes no estado TIME-WAIT, servidor que não responde na carga

4

Nosso aplicativo deixou de responder em cargas altas, com tempos de espera mais longos. O uso do processo foi anormalmente baixo (~ 15% de utilização da CPU por processo, nosso aplicativo é executado em 8 processos).

A saída do log de erros do Nginx mostrou vários deles:

2014/12/04 03:39:31 [crit] 24383#0: *2008067 connect() to 127.0.0.1:4567 failed (99: Cannot assign requested address) while connecting to upstream, client: 108.162.246.229, server: example.org, request: "GET /socket.io/?EIO=3&transport=polling&t=1417682366937-11501 HTTP/1.1", upstream: "http://127.0.0.1:4567/socket.io/?EIO=3&transport=polling&t=1417682366937-11501", host: "example.org", referrer: "https://example.org/unread"

O que eu vi

  • A saída de ss -tan | grep TIME-WAIT | wc -l estava em algum lugar no bairro de 30.000, ai!
  • O aplicativo seria responsivo e, em seguida:
    • Todos os processos cairiam de repente para quase 0 de uso da CPU
    • o aplicativo não responderia
    • Após cerca de 30 segundos, o aplicativo voltaria a ser exibido, repetir ad infinitum

Necessário para obter o aplicativo, então solução de band-aid:

  • echo 28000 65535 > ip_local_port_range (o MongoDB é executado no 27101, então escolhi um limite inferior acima disso)
  • echo 1 > /proc/sys/net/ipv4/tcp_tw_reuse
  • echo 1 > /proc/sys/net/ipv4/tcp_tw_recycle

Isso reduziu o número de soquetes no estado TIME-WAIT para um mais gerenciável ~ 400.

Aqui está um trecho de ss -tan | grep TIME-WAIT :

State      Recv-Q Send-Q        Local Address:Port          Peer Address:Port
TIME-WAIT  0      0                 127.0.0.1:29993            127.0.0.1:4567  
TIME-WAIT  0      0                 127.0.0.1:28522            127.0.0.1:4567  
TIME-WAIT  0      0                 127.0.0.1:29055            127.0.0.1:4567  
TIME-WAIT  0      0                 127.0.0.1:31849            127.0.0.1:4567  
TIME-WAIT  0      0                 127.0.0.1:32744            127.0.0.1:4567  
TIME-WAIT  0      0                 127.0.0.1:28304            127.0.0.1:4567  
TIME-WAIT  0      0                 127.0.0.1:34858            127.0.0.1:4567  
TIME-WAIT  0      0                 127.0.0.1:36707            127.0.0.1:4567  
TIME-WAIT  0      0                 127.0.0.1:34756            127.0.0.1:4567  
TIME-WAIT  0      0            104.131.91.122:443          108.162.250.6:55549 
TIME-WAIT  0      0                 127.0.0.1:32629            127.0.0.1:4567  
TIME-WAIT  0      0                 127.0.0.1:34544            127.0.0.1:4567  
TIME-WAIT  0      0                 127.0.0.1:34732            127.0.0.1:4567  
TIME-WAIT  0      0                 127.0.0.1:33820            127.0.0.1:4567  
TIME-WAIT  0      0                 127.0.0.1:33609            127.0.0.1:4567  
TIME-WAIT  0      0                 127.0.0.1:34504            127.0.0.1:4567  
TIME-WAIT  0      0                 127.0.0.1:32463            127.0.0.1:4567  
TIME-WAIT  0      0                 127.0.0.1:35089            127.0.0.1:4567  
TIME-WAIT  0      0                 127.0.0.1:30003            127.0.0.1:4567  
TIME-WAIT  0      0            104.131.91.122:443         199.27.128.100:36383 
TIME-WAIT  0      0                 127.0.0.1:33040            127.0.0.1:4567  
TIME-WAIT  0      0                 127.0.0.1:34038            127.0.0.1:4567  
TIME-WAIT  0      0                 127.0.0.1:28096            127.0.0.1:4567  
TIME-WAIT  0      0                 127.0.0.1:29541            127.0.0.1:4567  
TIME-WAIT  0      0                 127.0.0.1:30022            127.0.0.1:4567  
TIME-WAIT  0      0                 127.0.0.1:31375            127.0.0.1:4567  
TIME-WAIT  0      0                 127.0.0.1:29827            127.0.0.1:4567  
TIME-WAIT  0      0                 127.0.0.1:29334            127.0.0.1:4567  

Minhas perguntas:

  • Muitos deles são de 127.0.0.1 a 127.0.0.1, isso é normal? Os endereços dos pares não deveriam ser todos de IPs externos?
    • Nosso aplicativo Node.js está por trás do proxy nginx, atrás do CloudFlare DNS, isso limita o número de endereços IP de entrada exclusivos, isso pode estar relacionado?
  • Como eu reduzi o número de sockets em TIME-WAIT state?
  • Estou certo de que não temos 3000 conexões de soquete exclusivas por segundo , algo está mal configurado em nossa ponta e abrimos centenas de soquetes quando deveria abrir um?

Agradecemos antecipadamente por qualquer ajuda que você possa oferecer!

    
por Julian H. Lam 04.12.2014 / 20:10

1 resposta

2

No final, eu pesquisei mais e li esse excelente orientar na escalação de aplicativos do Node atrás de um proxy nginx.

A principal diferença veio quando adicionei o parâmetro keepalive ao bloco upstream em nginx. Acontece que os funcionários do nginx não armazenam em cache as conexões de entrada e reutilizá-las, fazendo com que muitos milhares de novas conexões sejam criadas (especialmente handshakes de w / socket.io e outros)

@ A sugestão de MichaelHampton de usar um soquete de domínio unix também resolveria isso bem.

    
por 07.12.2014 / 18:57