Eu tenho um problema em um processo de longa duração chamado proxy-kube que faz 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 com o tempo, fazendo com que o processo se comporte mal. Eu já relatei um problema ao rastreador de erros do Kubernetes, mas gostaria de entender por que essas conexões não são fechadas pelo kernel do Linux.
De acordo com a documentação (procure tcp_fin_timeout), a conexão no estado FIN_WAIT2 deve ser fechada pelo kernel após X segundos, onde X pode ser lido em / proc. Na minha máquina, está definido como 60:
$ cat /proc/sys/net/ipv4/tcp_fin_timeout
60
então, se eu entendi direito, essas conexões devem ser fechadas em 60 segundos. Mas este não é o caso, eles são deixados nesse estado por horas.
Embora eu também entenda que as conexões FIN_WAIT2 são bastante incomuns (significa que o host está aguardando por um ACK a partir da extremidade remota da conexão que já pode ter desaparecido), não entendo por que essas conexões não são "fechadas" pelo sistema .
Existe algo que eu possa fazer sobre isso?
Observe que reiniciar o processo relacionado é um último recurso.
fonte
Respostas:
O tempo limite do kernel se aplica somente 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 ligou
shutdown
e está aguardando a conexão ser desligada corretamente. O aplicativo pode esperar o tempo que for necessário para o encerramento.O fluxo típico de desligamento limpo é assim:
O aplicativo decide desligar a conexão e encerra o lado de gravação da conexão.
O aplicativo aguarda o outro lado desligar a metade da conexão.
O aplicativo detecta o desligamento do outro lado da conexão 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 decida desligar a conexão, deve deixar de esperar que o outro lado faça um desligamento limpo após um período de tempo razoável.
fonte
Se o soquete estiver desligado (), mas ainda não fechado (), o soquete permanecerá no estado FIN_WAIT2. E como o aplicativo ainda possui o descritor de arquivo, o kernel não se incomodaria em limpar.
fonte