Mengapa koneksi dalam status FIN_WAIT2 tidak ditutup oleh kernel Linux?

11

Saya memiliki masalah dalam proses jangka panjang yang disebut kube-proxy yang menjadi bagian dari Kubernetes .

Masalahnya adalah bahwa dari waktu ke waktu koneksi dibiarkan dalam status 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

Koneksi ini menumpuk dari waktu ke waktu membuat proses bertingkah buruk. Saya sudah melaporkan masalah ke pelacak bug Kubernetes tapi saya ingin mengerti mengapa koneksi seperti itu tidak ditutup oleh kernel Linux.

Menurut dokumentasinya (cari tcp_fin_timeout) koneksi dalam status FIN_WAIT2 harus ditutup oleh kernel setelah X detik, di mana X dapat dibaca dari / proc. Di komputer saya sudah diatur ke 60:

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

jadi jika saya mengerti benar koneksi seperti itu harus ditutup 60 detik. Tapi ini tidak terjadi, mereka dibiarkan dalam kondisi seperti itu selama berjam-jam.

Walaupun saya juga mengerti bahwa koneksi FIN_WAIT2 sangat tidak biasa (itu berarti tuan rumah sedang menunggu ACK dari ujung remote koneksi yang mungkin sudah hilang) Saya tidak mengerti mengapa koneksi ini tidak "ditutup" oleh sistem .

Apakah ada yang bisa saya lakukan?

Perhatikan bahwa memulai kembali proses terkait adalah pilihan terakhir.

Adam Romanek
sumber
1
Ngomong-ngomong, di FIN-WAIT2, koneksi tidak menunggu ACK (FIN yang telah dikirimkannya sudah diakui, itulah sebabnya kami tidak ada di FIN-WAIT1). Sebaliknya, ujung lainnya masih memiliki opsi untuk mengirim data dalam jumlah yang tidak terbatas.
Hagen von Eitzen

Jawaban:

14

Batas waktu kernel hanya berlaku jika koneksi menjadi yatim. Jika koneksi masih terpasang ke soket, program yang memiliki soket itu bertanggung jawab untuk menentukan waktu penghentian sambungan. Mungkin itu telah memanggil shutdowndan sedang menunggu koneksi untuk dimatikan dengan bersih. Aplikasi dapat menunggu selama ia ingin shutdown selesai.

Aliran shutdown bersih khas berjalan seperti ini:

  1. Aplikasi memutuskan untuk mematikan koneksi dan mematikan sisi penulisan koneksi.

  2. Aplikasi menunggu pihak lain untuk menutup setengah dari koneksi.

  3. Aplikasi mendeteksi pemutusan koneksi pihak lain dan menutup soketnya.

Aplikasi dapat menunggu di langkah 2 selama suka.

Sepertinya aplikasi perlu waktu tunggu. Setelah memutuskan untuk mematikan koneksi, ia harus menyerah menunggu pihak lain untuk melakukan shutdown bersih setelah beberapa waktu yang masuk akal.

David Schwartz
sumber
Saya akan memeriksa informasi ini dengan pengembang Kubernetes untuk melihat apakah batas waktu seperti itu diterapkan. Saya akan menerima jawabannya begitu saya memverifikasinya. Meskipun demikian terima kasih atas tanggapan yang cepat.
Adam Romanek
Saya ingin memahami jawaban Anda secara lebih rinci. Bisakah Anda jelaskan apa itu koneksi yatim?
Adam Romanek
1
@AdamRomanek Koneksi yatim adalah koneksi tanpa soket yang terkait, yaitu koneksi yang hanya dapat diakses oleh kernel itu sendiri dan tidak ada proses yang dapat melakukan operasi.
David Schwartz
Ini akan membantu ... " blog.cloudflare.com/…
John Greene
2

Jika soket ditutup (), tetapi belum ditutup (), soket akan tetap dalam status FIN_WAIT2. Dan karena aplikasi masih memiliki deskriptor file, kernel tidak akan repot untuk membersihkan.

L. Yan
sumber
Itu sudah disebutkan dalam jawaban yang diterima.
RalfFriedl
Saya secara khusus menambahkan bahwa close () tidak dipanggil.
L. Yan