Grande backlog TCP para o uwsgi, mas sem conexões visíveis

2

Em uma instalação com três instâncias do docker, uma executando o haproxy e duas outras executando um aplicativo python baseado em balão através do uWsgi, nos deparamos com uma situação após cerca de um dia em que nenhuma nova conexão é aceita em uma ou ambas as instâncias. p>

O uWsgi está configurado para aceitar até 100 conexões de backlog. Isso é menor que o padrão 128 configurado em /proc/sys/net/core/somaxconn . O uWsgi desiste da 101ª conexão.

ss confirma que existe um atraso de 101.

root@ad9380a94c50:/# ss -nlpt
State      Recv-Q Send-Q        Local Address:Port          Peer Address:Port 
LISTEN     101    100                       *:8080                     *:*      users:(("uwsgi",pid=25,fd=3),("uwsgi",pid=19,fd=3))
LISTEN     0      128              127.0.0.11:38230                    *:*

Não há conexão correspondente ao executar, por exemplo, netstat -npt .

O código-fonte para o uwsgi mostra que o comprimento da fila de pendências é obtido chamando getsockopt abd recuperando o campo tcpi_unacked . Em outras palavras, isso não parece ser um bug no uwsgi, parece que o kernel do linux e / ou docker literalmente pensa que existem conexões lá que não estão realmente lá. Eu suspeito que eles estavam lá uma vez, na forma de um exame de saúde feito por haproxy.

Não há criação lenta de log de retorno. Enquanto a instância está feliz, o backlog permanece em zero. Parece que algo está errado e, depois disso, o backlog chega a 100 muito rapidamente e as coisas ficam pendentes.

Estamos executando o docker em uma máquina virtual da Amazon.

    
por izak 28.06.2016 / 15:48

1 resposta

1

O processo está bloqueando um mutex (ou futex no linux speak). Portanto, o backlog é legítimo, estamos literalmente presos atrás de uma chamada de sistema e, embora as conexões estejam indo embora, nada mais está atualizando.

Para referência futura a outras pessoas que encontrem esta questão, este foi o comando de violação:

# strace -p 5340
Process 5340 attached
futex(0x223cee0, FUTEX_WAIT_PRIVATE, 0, NULL

Portanto, há algum tipo de impasse, e agora só tenho que descobrir qual processo está usando mutexes. gdb eventualmente me deu essa informação:

(gdb) bt
#0  sem_wait () at ../nptl/sysdeps/unix/sysv/linux/x86_64/sem_wait.S:85
#1  0x00007f0ecc982068 in PyThread_acquire_lock () from /usr/lib/x86_64-linux-gnu/libpython2.7.so.1.0
#2  0x00007f0ecd037b29 in gil_real_get () from /usr/lib/uwsgi/plugins/python_plugin.so
#3  0x00007f0ecd030167 in uwsgi_python_master_fixup () from /usr/lib/uwsgi/plugins/python_plugin.so
#4  0x000000000042cb66 in uwsgi_respawn_worker ()
#5  0x000000000042b38f in master_loop ()
#6  0x000000000046741e in uwsgi_run ()
#7  0x000000000041698e in main ()

Então, algum tipo de impasse na tentativa de adquirir o bloqueio de intérprete global.

Editar 2 : o enredo fica mais espesso. Quase exatamente o mesmo problema que esse cara , exceto que o nosso é com o RabbitMQ ao invés do MongoDB. A execução de um segundo thread causa problemas durante o recarregamento, algumas vezes fazendo com que o GIL não seja liberado e, em seguida, interrompido ao tentar readquiri-lo.

Basicamente, estamos fazendo algo que não deveríamos estar fazendo e só precisamos repensar a coisa toda.

    
por 30.06.2016 / 14:16