Saya memiliki aplikasi yang kehabisan deskriptor file, tampaknya dengan membuka soket, tetapi saya tidak dapat mengetahui dengan tepat apa yang dilakukan soket ini. Ini muncul di output lsof sebagai
java 9689 appuser 1010u sock 0,5 263746675 can't identify protocol
java 9689 appuser 1011u sock 0,5 263746676 can't identify protocol
java 9689 appuser 1012u sock 0,5 263746677 can't identify protocol
java 9689 appuser 1014u sock 0,5 263746678 can't identify protocol
java 9689 appuser 1015u sock 0,5 263746679 can't identify protocol
java 9689 appuser 1016u sock 0,5 263746681 can't identify protocol
dan di / proc / $ PID / fd as
lrwx------ 1 appuser appuser 64 Jun 23 11:49 990 -> socket:[263732085]
lrwx------ 1 appuser appuser 64 Jun 23 11:49 991 -> socket:[263732086]
lrwx------ 1 appuser appuser 64 Jun 23 11:49 992 -> socket:[263735307]
lrwx------ 1 appuser appuser 64 Jun 23 11:49 993 -> socket:[263732088]
lrwx------ 1 appuser appuser 64 Jun 23 11:49 995 -> socket:[263735308]
lrwx------ 1 appuser appuser 64 Jun 23 11:49 996 -> socket:[263735309]
lrwx------ 1 appuser appuser 64 Jun 23 11:49 997 -> socket:[263745434]
lrwx------ 1 appuser appuser 64 Jun 23 11:49 998 -> socket:[263745435]
lrwx------ 1 appuser appuser 64 Jun 23 11:49 999 -> socket:[263745436]
tetapi tidak ada keluaran serupa di netstat -a
.
Apa soket ini dan bagaimana saya bisa mengetahui apa yang mereka lakukan?
Sunting : Saya telah mencoba menjalankan grep $SOCKET /proc/net
, seperti yang direkomendasikan di FAQ lsof , di mana $ SOCKET misalnya 263746679, tetapi itu tidak memberikan hasil juga.
Sebagai latar belakang, aplikasi adalah wadah untuk banyak tugas yang, antara lain, melakukan panggilan jaringan. Saya perlu memilih yang mengamuk, tetapi sampai saya tahu dengan siapa soket itu berkomunikasi, saya terjebak.
Jawaban:
Ini dapat terjadi jika Anda membuat soket, tetapi tidak pernah menghubungkan () atau mengikat () dengannya. Taruhan terbaik Anda mungkin untuk strace (-fF) aplikasi, dan kemudian referensi silang dengan output lsof untuk menentukan soket mana yang menyebabkan masalah. Sebagai metode bonus untuk debugging: jika Anda membungkus panggilan socket Anda dengan informasi debugging dan menuliskannya ke / dev / null, itu akan muncul dalam strace tanpa memberi Anda file-file log besar yang lucu.
sumber
Menggunakan Python, saya mengalami masalah yang sama pada soket SSL:
Solusinya adalah membuka bungkusan lapisan SSL sebelum ditutup:
Ini menutup soket dengan benar di aplikasi saya.
sumber
Hal pertama yang akan saya lakukan adalah menambahkan jika batas deskriptor file Anda:
Selanjutnya saya akan memastikan sistem Anda mutakhir, ini mencakup semua perpustakaan dan server. Kemungkinan server aplikasi Java Anda kedaluwarsa (jika Anda menggunakannya). Ini juga kemungkinan bahwa server aplikasi Anda salah konfigurasi, Anda harus melihat file konfigurasi Anda dan menurunkan Anda
connectionTimeout
dan / atau AndamaxKeepAliveRequests
(Saya tidak yakin server aplikasi apa yang Anda gunakan atau jika Anda menggunakan salah satu ...).Saya tidak yakin apa yang aplikasi ini lakukan, tetapi jika Anda tidak berpikir itu membutuhkan puluhan ribu soket maka ini hampir pasti merupakan "file descriptor leak" di aplikasi Java Anda. Anda mungkin harus mengirim laporan bug ke vendor. Dalam laporan bug ini Anda harus memasukkan informasi tentang cara membuat kembali masalah.
Berikut adalah beberapa cara untuk men-debug masalah ini.
Wireshark (atau twireshark untuk cli) adalah alat terbaik untuk melihat bagaimana soket ini digunakan. Wireshark akan memberi Anda rincian jenis lalu lintas yang dilemparkan ke kawat. Kemungkinan beberapa koneksi pertama akan berhasil dan kemudian akan mencapai batas deskriptor file. Setelah batas deskriptor file tercapai, Wireshark tidak akan mengambil apa-apa (dan lebih rapi adalah netstat dalam hal ini), tetapi ini akan membantu mempersempit masalah. Mungkin ada kasus di mana banyak SYN keluar sedang dikirim, namun tidak ada SYN / ACK yang diterima sehingga banyak koneksi tcp hanya macet di negara SYN_WAIT.
Jika Anda memiliki akses ke kode sumber dan Anda tahu jenis soket yang dibuat (seperti menggunakan strace atau hanya mencari kode) maka Anda dapat membuka proyek di Eclipse (atau IDE lain) dan menetapkan titik istirahat pada fungsi yang sedang membuat soket ini. Ketika breakpoint terkena, maka Anda dapat melihat jejak tumpukan. Deskriptor file ini bocor mungkin infinite loop sederhana atau mungkin nilai timeout soket terlalu besar. Kemungkinan lain adalah aplikasi java tidak melakukan
socket.close()
untuk membersihkan koneksi. Melakukan penutupan biasanya dilakukan difinely
blok atry/catch
(Ya soket harus selalu mencoba / menangkap di Jawa atau tidak akan membangun :). Pada akhirnya, kemungkinan aplikasi Java tidak menangani IOException dengan benar.sumber