Por que as conexões no estado FIN_WAIT2 não são fechadas pelo kernel do Linux?

8

Eu tenho um problema em um processo de longa duração chamado kube-proxy sendo parte do Kubernetes .

O problema é que, de tempos em tempos, uma conexão é deixada no estado FIN_WAIT2.

$ sudo netstat -tpn | grep FIN_WAIT2
tcp6       0      0 10.244.0.1:33132        10.244.0.35:48936       FIN_WAIT2   14125/kube-proxy
tcp6       0      0 10.244.0.1:48340        10.244.0.35:56339       FIN_WAIT2   14125/kube-proxy
tcp6       0      0 10.244.0.1:52619        10.244.0.35:57859       FIN_WAIT2   14125/kube-proxy
tcp6       0      0 10.244.0.1:33132        10.244.0.50:36466       FIN_WAIT2   14125/kube-proxy

Essas conexões se acumulam ao longo do tempo, fazendo com que o processo se comporte mal. Eu já relatei um problema ao rastreador de bugs do Kubernetes, mas gostaria de entender por que tais conexões não são fechadas por o kernel do Linux.

De acordo com a sua documentação (pesquisa por tcp_fin_timeout) a conexão no estado FIN_WAIT2 deve ser fechado pelo kernel após X segundos, onde X pode ser lido de / proc. Na minha máquina está definido para 60:

$ cat /proc/sys/net/ipv4/tcp_fin_timeout
60

então, se eu entendi corretamente, essas conexões devem ser fechadas em 60 segundos. Mas este não é o caso, eles são deixados em tal estado por horas.

Embora eu também entenda que as conexões FIN_WAIT2 são bastante incomuns (isso significa que o host está aguardando algum ACK do lado remoto da conexão que já pode ter sumido) Eu não entendo porque essas conexões não estão "fechadas" pelo sistema.

Existe algo que eu possa fazer sobre isso?

Note que reiniciar o processo relacionado é um último recurso.

    
por Adam Romanek 23.11.2015 / 11:26

1 resposta

10

O tempo limite do kernel só se aplica se a conexão for órfã. Se a conexão ainda estiver conectada a um soquete, o programa que possui esse soquete é responsável pelo tempo limite do desligamento da conexão. Provavelmente ele chamou shutdown e está aguardando a conexão ser encerrada de forma limpa. O aplicativo pode esperar o tempo que desejar até que o desligamento seja concluído.

O típico fluxo de desligamento limpo é assim:

  1. O aplicativo decide encerrar a conexão e encerra o lado de gravação da conexão.

  2. O aplicativo aguarda que o outro lado desligue sua metade da conexão.

  3. O aplicativo detecta o desligamento da conexão do outro lado e fecha seu soquete.

O aplicativo pode esperar na etapa 2 pelo tempo que desejar.

Parece que o aplicativo precisa de um tempo limite. Uma vez que ele decida desligar a conexão, ela deve desistir de esperar que o outro lado faça um desligamento limpo depois de um tempo razoável.

    
por 23.11.2015 / 12:46