У меня проблема с долгоживущим процессом под названием kube-proxy , который является частью Kubernetes .
Проблема в том, что время от времени соединение остается в состоянии 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
Эти соединения со временем накапливаются, что приводит к неправильной работе процесса. Я уже сообщал о проблеме в баг-трекер Kubernetes, но я Я хочу понять, почему такие соединения не закрываются ядром Linux.
Согласно его документации (поиск tcp_fin_timeout) соединение в состоянии FIN_WAIT2 должно быть закрыто ядром через X секунд, где X может читать из / proc. На моей машине установлено значение 60:
$ cat /proc/sys/net/ipv4/tcp_fin_timeout
60
, поэтому, если я правильно понимаю, такие соединения должны быть закрыты на 60 секунд. Но это не так, они остаются в таком состоянии в течение нескольких часов.
Хотя я также понимаю, что соединения FIN_WAIT2 довольно необычны (это означает, что хост ожидает некоторого ACK от удаленного конца соединения, которое может уже уйти) Я не понимаю, почему эти соединения не «закрываются» системой.
Могу ли я что-нибудь с этим сделать?
Обратите внимание, что перезапуск связанного процесса - это последнее средство.
Тайм-аут ядра применяется только в том случае, если соединение потеряно. Если соединение все еще подключено к сокету, программа, владеющая этим сокетом, отвечает за тайм-аут отключения соединения. Вероятно, он вызвал выключение
и ожидает полного завершения соединения. Приложение может ждать завершения завершения работы сколь угодно долго.
Типичный поток чистого завершения работы выглядит следующим образом:
Приложение решает закрыть соединение и закрывает сторону записи соединения.
] Приложение ожидает, пока другая сторона завершит свою половину соединения.
Приложение обнаруживает отключение соединения другой стороной и закрывает свой сокет.
Приложение может ждать на шаге 2 столько, сколько оно нравится.
Похоже, приложению требуется тайм-аут. Как только он решает закрыть соединение, он должен перестать ждать, пока другая сторона выполнит полное завершение работы через некоторое разумное время.
Если сокет отключен (), но еще не закрыт (), сокет останется в состоянии FIN_WAIT2. А поскольку приложение по-прежнему владеет файловым дескриптором, ядро не утруждает себя очисткой.