Prompt dan Peran yang Berlaku
Sebuah layanan API Linux berjalan di bawah lalu lintas stabil selama beberapa jam, kemudian mulai menolak koneksi baru. Panggilan ke layanan upstream dan upaya membuka file log juga mulai gagal. Anda mengetahui bahwa:
- proses layanan memiliki
RLIMIT_NOFILEsoft sebesar 8.192 dan hard limit sebesar 65.536; - proses dimulai dengan sekitar 400 file descriptor yang terbuka, kemudian bertambah sekitar 25 per menit;
- tepat sebelum insiden,
/proc/<pid>/fdberisi hampir 8.192 entri dan log berisiEMFILE: Too many open files; - me-restart proses langsung memulihkan layanan, tetapi pertumbuhannya kembali terjadi;
/proc/sys/fs/file-nrmilik host tetap jauh di bawah/proc/sys/fs/file-max.
Jelaskan hubungan antara file descriptor, tabel file-descriptor proses, dan open file description. Jelaskan mengapa file reguler, socket, pipe, dan epoll semuanya menggunakan descriptor, serta bedakan EMFILE dari ENFILE. Kemudian berikan urutan diagnostik yang aman untuk produksi, putuskan apakah ini merupakan kebocoran FD atau konkurensi sah di luar kapasitas, usulkan mitigasi dan perbaikan jangka panjang, serta jelaskan bagaimana Anda membuktikan bahwa insiden tersebut telah terselesaikan.
Pertanyaan ini cocok untuk wawancara backend, SRE, infrastruktur, sistem, dan rekayasa perangkat lunak umum. Nilai 8.192, 65.536, 400, dan 25 per menit adalah input wawancara hipotetis, bukan rekomendasi universal. Jawaban nyata juga harus memperhitungkan service manager, container runtime, izin proses, dan model konkurensi aplikasi.
Hal yang Diuji oleh Pewawancara
Pertama, dapatkah kandidat menjelaskan bahwa file descriptor adalah indeks bilangan bulat kecil di dalam sebuah proses, bukan pathname, inode, atau objek kernel itu sendiri? Jawaban yang kuat menggambarkan rantai “tabel FD proses → open file description → file, socket, pipe, atau objek lainnya” dan memahami bahwa descriptor yang dibuat oleh dup atau diwariskan melalui fork dapat merujuk ke open file description yang sama.
Kedua, dapatkah kandidat memisahkan cakupan batasan (limit scopes)? EMFILE berarti proses saat ini mencapai RLIMIT_NOFILE; ENFILE berarti batas file terbuka di seluruh sistem telah tercapai. Baik fs.file-max saja maupun ulimit -n di shell yang tidak terkait tidak membuktikan batas efektif proses yang gagal.
Ketiga, apakah diagnosis mencakup jumlah, komposisi, dan tren? Satu snapshot lsof hanya menunjukkan satu momen waktu. Untuk memastikan adanya kebocoran, diperlukan pengambilan sampel total dan jenis objek di bawah lalu lintas yang stabil, lalu mengorelasikan pertumbuhan dengan connection pool, siklus hidup permintaan, rotasi log, child process, dan jalur kegagalan.
Keempat, dapatkah kandidat memisahkan kapasitas sementara dari perbaikan akar masalah? Menaikkan limit dapat menciptakan ruang tanggap insiden atau menjadi bagian dari perencanaan kapasitas yang valid, tetapi tidak menutup sumber daya yang kepemilikannya telah hilang. Slope positif yang tetap pada akhirnya akan menghabiskan batas yang lebih besar juga.
Terakhir, apakah ada loop verifikasi? “Kesalahan berhenti muncul” tidaklah cukup. Jawaban yang kuat memvalidasi utilisasi dan slope FD, jenis objek, error permintaan, tail latency, status pool, dan peristiwa siklus hidup yang berulang di bawah beban puncak target serta kegagalan yang diinjeksikan.
Pertanyaan yang Perlu Diklarifikasi Sebelum Menjawab
- Berapa errno tepatnya? Konfirmasikan
EMFILEatauENFILEdari error aplikasi atau system-call alih-alih menyimpulkan cakupannya dari pesan yang dapat dibaca manusia. - PID mana yang gagal? Supervisor, worker, sidecar, dan child yang berumur pendek dapat mewarisi limit yang berbeda dan memegang sumber daya yang berbeda.
- Apa yang meluncurkan layanan? Shell interaktif, systemd, container runtime, dan process manager dapat menetapkan soft dan hard limit yang berbeda. Perintah shell tidak dapat mengubah layanan yang sedang berjalan secara retroaktif.
- Apa yang bergerak seiring pertumbuhan FD? Selaraskan dengan koneksi konkuren, permintaan upstream, kedalaman antrean, rotasi log, reload, jumlah child, dan tingkat error.
- Jenis objek mana yang bertambah? Socket, file reguler, pipe,
anon_inode:[eventpoll], objek inotify, dan file yang dihapus mengarah ke jalur kepemilikan yang berbeda. - Apa model kapasitas yang sah? Proxy dengan konkurensi tinggi secara valid mungkin membutuhkan banyak socket. Jumlah yang besar tidak otomatis merupakan kebocoran; itu harus sesuai dengan konkurensi yang dikonfigurasi dan mendatar/turun saat beban berkurang.
- Bisakah
/procdiperiksa dengan aman? Membaca descriptor milik pengguna lain mungkin dibatasi oleh izin dan aturan ptrace. Investigasi produksi harus menggunakan hak istimewa minimum yang diperlukan dan menghindari tracing jangka panjang dengan overhead tinggi.
Jawaban 30 Detik
“File descriptor adalah indeks bilangan bulat non-negatif di tabel FD suatu proses. Entri tabel merujuk ke open file description di seluruh sistem, yang menyimpan file offset dan status flag, lalu menunjuk ke file reguler, socket, pipe, atau objek I/O kernel lainnya. EMFILE berarti proses ini mencapai RLIMIT_NOFILE; ENFILE berarti host mencapai batas file terbuka di seluruh sistemnya.
Saya akan mengonfirmasi PID dan errno yang gagal, membaca /proc/<pid>/limits, menghitung dan mengklasifikasikan /proc/<pid>/fd, mengambil sampel kategori dari waktu ke waktu, dan memeriksa /proc/sys/fs/file-nr. Slope positif yang tetap di bawah lalu lintas yang stabil, yang direset oleh restart dan terkonsentrasi pada satu jenis objek, mengindikasikan kebocoran. Jumlah yang mengikuti konkurensi, mencapai batas stabil (plateau) yang ditentukan, dan turun setelahnya mengindikasikan tekanan kapasitas. Saya dapat menerapkan rate-limit, me-roll instance, dan menaikkan limit layanan nyata setelah validasi kapasitas, tetapi perbaikan permanennya adalah kepemilikan sumber daya, pembersihan jalur kegagalan, pool yang dibatasi, dan pewarisan yang benar. Saya membuktikannya dengan utilisasi dan slope FD, pelepasan objek, serta nol error terkait pada beban puncak.”
Pembahasan Mendalam Langkah demi Langkah
Langkah 1: Bangun Model Referensi Tiga Lapis
Jika berhasil, open() mengembalikan bilangan bulat non-negatif. Linux biasanya memilih nomor descriptor terendah yang saat ini tidak digunakan oleh proses tersebut. Secara konvensi, 0, 1, dan 2 adalah standard input, standard output, dan standard error. Nomor-nomor setelahnya tetap hanya merupakan indeks dalam proses tersebut.
Hubungan intinya adalah:
process FD-table entry → open file description → underlying object
Lapisan-lapisan tersebut menyimpan state yang berbeda:
| Lapisan | Apa yang disimpannya | Properti penting |
|---|---|---|
| Entri tabel FD proses | Nomor descriptor dan flag descriptor seperti close-on-exec | Nomor tersebut hanya bermakna dalam konteks tabel FD proses itu |
| Open file description | File offset saat ini dan status flag file yang terbuka | Objek di seluruh sistem yang dapat dibagikan oleh beberapa descriptor |
| Objek yang mendasari | Inode, socket, pipe, perangkat, atau objek kernel anonim | Menentukan perilaku I/O sebenarnya |
Dua panggilan independen ke open() pada jalur yang sama biasanya membuat open file description terpisah. Descriptor yang dikembalikan oleh dup() merujuk ke open file description yang sama, sehingga kedua descriptor berbagi offset dan status flag file. Setelah fork(), descriptor parent dan child yang bersangkutan juga merujuk ke open file description yang sama. Flag khusus descriptor seperti close-on-exec terpisah dari state bersama tersebut.
Inilah sebabnya mengapa “FD 42” tidak memiliki makna lintas proses yang stabil dan mengapa mengelompokkan hanya berdasarkan pathname dapat menyembunyikan masalah. Jalur yang sama dapat dibuka secara independen berkali-kali, sementara nomor descriptor yang berbeda dapat berbagi satu open state.
Langkah 2: Pahami Sumber Daya Mana yang Mengonsumsi Descriptor
Antarmuka bergaya Unix mengekspos banyak sumber daya I/O melalui descriptor yang dapat dibaca, ditulis, atau ditunggu:
- file reguler dan direktori;
- socket TCP, UDP, dan Unix-domain;
- anonymous pipe dan named FIFO;
- terminal, perangkat, dan beberapa pseudo-file;
- objek kernel anonim seperti
epoll,eventfd,timerfd,signalfd, dan inotify.
/proc/<pid>/fd berisi satu symbolic link per descriptor yang terbuka di dalam proses. File reguler biasanya menampilkan sebuah path. Socket dan pipe umumnya muncul sebagai socket:[inode] dan pipe:[inode]. Objek tanpa inode yang sesuai dapat muncul sebagai anon_inode:[eventpoll] atau tipe anon_inode lainnya.
Membuat satu descriptor epoll untuk event loop tidak berarti ribuan koneksi yang dipantau berhenti mengonsumsi descriptor. Setiap socket yang dipantau tetap memiliki FD-nya sendiri. Sebaliknya, beberapa entri anon_inode:[eventpoll] tidak secara otomatis membuktikan adanya kebocoran event-loop; identifikasi kategori yang jumlahnya benar-benar bertambah.
Langkah 3: Pisahkan EMFILE, ENFILE, dan Batas Tertinggi (Limit Ceilings)
RLIMIT_NOFILE memiliki soft limit dan hard limit. Kernel memberlakukan soft limit. Hard limit adalah batas atas di mana proses yang tidak memiliki hak istimewa (unprivileged) dapat menaikkan soft limit. Linux mendefinisikan nilainya sebagai satu angka lebih besar dari nomor descriptor terbesar yang boleh dibuka oleh proses.
Batasan utamanya adalah:
| Sinyal | Arti | Bukti pertama yang harus diperiksa |
|---|---|---|
EMFILE | Proses ini mencapai RLIMIT_NOFILE | /proc/<pid>/limits dan /proc/<pid>/fd |
ENFILE | Host mencapai batas file terbuka di seluruh sistem | /proc/sys/fs/file-nr, file-max, dan log kernel |
/proc/sys/fs/nr_open | Batas atas kernel untuk menaikkan RLIMIT_NOFILE | Periksa saat menaikkan hard limit gagal |
Field pertama di /proc/sys/fs/file-nr adalah jumlah file handle yang dialokasikan; field ketiga sesuai dengan file-max. Ini adalah hitungan open file description di seluruh sistem, sehingga tidak harus sama dengan jumlah hitungan FD setiap proses: beberapa descriptor dapat berbagi satu open file description.
Prompt secara eksplisit melaporkan EMFILE, sementara penggunaan di seluruh sistem tetap jauh di bawah file-max. Oleh karena itu, jalur utamanya adalah batasan per proses. Mengubah fs.file-max tidak mengatasi kegagalan ini.
Langkah 4: Kumpulkan Bukti yang Sebanding dan Berisiko Rendah Terlebih Dahulu
Setelah mengonfirmasi PID dan izin, mulailah dengan snapshot /proc beroverhead rendah:
pid=12345
grep 'Max open files' /proc/"$pid"/limits
find /proc/"$pid"/fd -maxdepth 1 -type l 2>/dev/null | wc -l
find /proc/"$pid"/fd -maxdepth 1 -type l -exec readlink {} \; 2>/dev/null |
sed -E 's/socket:\[[0-9]+\]/socket:[id]/; s/pipe:\[[0-9]+\]/pipe:[id]/' |
sort | uniq -c | sort -nr | head -20
cat /proc/sys/fs/file-nr
cat /proc/sys/fs/file-max/proc adalah tampilan langsung (live view). Proses dapat membuka atau menutup descriptor selama penelusuran, dan entri yang berumur pendek dapat menghilang. Perlakukan perintah-perintah ini sebagai diagnostik tren, bukan audit atomik. Ambil sampel total dan kategori pada interval tetap beserta stempel waktu (timestamp), lalu selaraskan dengan metrik aplikasi.
Jika socket mendominasi peningkatan, periksa arah koneksi, tujuan, dan status TCP. Jika file reguler bertambah, kelompokkan path di sekitar log, file sementara, atau reload konfigurasi. Jika pipe bertambah, periksa child process dan siklus hidup IPC. Jika objek anon_inode bertambah, cari pendaftaran dan pembuangan event-loop, watcher, atau timer.
Alat seperti lsof -p <pid>, ss -tanp, atau penelusuran system-call yang dibatasi dapat menambahkan detail setelah /proc dan metrik aplikasi mempersempit pencarian. Tracing jangka panjang dapat menambah overhead produksi dan mungkin tetap tidak lengkap tanpa izin yang memadai.
Langkah 5: Gunakan Jumlah, Komposisi, Slope, dan Pemulihan untuk Mengklasifikasikan Masalah
Jumlah saat ini yang tinggi saja tidak membuktikan adanya kebocoran. Ajukan empat pertanyaan:
- Apakah jumlahnya sesuai dengan konkurensi yang diharapkan? Anggaran mencakup listening socket, koneksi yang diterima, pool outbound, file, pipe, objek event, dan safety headroom.
- Apakah komposisinya sesuai dengan arsitektur? Jika upstream pool dibatasi pada 500 tetapi descriptor untuk tujuan tersebut mencapai 5.000, selidiki jalur pengembalian dan penutupan (return and close paths).
- Apakah slope tetap positif di bawah beban yang stabil? Jika rasio permintaan dan konkurensi datar tetapi FD masih bertambah 25 per menit, bukti kebocoran sangat kuat.
- Apakah penggunaan kembali mendatar ke batas stabil saat beban turun? File dengan cakupan permintaan (request-scoped), koneksi pendek, dan pipe sementara harus dilepaskan. Koneksi pool yang berumur panjang mungkin tetap ada, tetapi pada batas yang eksplisit.
Dalam prompt, layanan dimulai sekitar 400, tumbuh pada laju yang tetap, tereset saat restart, dan berulang. Pola tersebut sangat mengarah pada kebocoran. Klasifikasi objek tetap diperlukan agar pemanasan connection pool yang alami tidak disalahartikan sebagai file yang tidak ditutup.
Kapasitas yang tidak memadai biasanya terlihat berbeda: penggunaan mengikuti konkurensi, mencapai batas stabil di dekat batas pool dan koneksi yang dikonfigurasi, dan turun setelah beban atau timeout mereda. Campuran objek sesuai dengan desain, dan kegagalan muncul hanya ketika permintaan puncak yang sah melebihi anggaran awal. Menaikkan batas, menambah proses, atau mengurangi biaya per koneksi kemudian dapat menjadi perubahan kapasitas yang bertahan lama.
Langkah 6: Lacak Kepemilikan Sumber Daya Melalui Jalur Kebocoran Umum
Jawaban yang kuat menanyakan “siapa yang membuatnya, siapa yang memilikinya, dan siapa yang menutupnya setelah terjadi kegagalan?” alih-alih berhenti pada perintah. Penyebab umum meliputi:
- klien HTTP tidak menutup response body, sehingga koneksi tidak dapat digunakan kembali maupun dilepaskan dengan segera;
- koneksi database, cache, atau upstream di-checkout tetapi tidak dikembalikan setelah timeout atau exception;
- rotasi log atau reload konfigurasi berulang kali membuka file baru tanpa menutup handle yang lama;
- setiap permintaan membuat timer, watcher, pipe, atau objek event tetapi pembatalan (cancellation) melewatkan pembersihan;
- proses parent dan child membiarkan ujung standard stream atau pipe IPC yang tidak terpakai tetap terbuka;
- sebuah descriptor bertahan dari
execsecara tidak terduga, sehingga proses lain menjaga sumber daya tetap hidup; - logika percobaan ulang (retry) membuat koneksi baru sementara upaya sebelumnya masih tertunda.
Buat kepemilikan masa pakai terlihat dalam struktur kode. Gunakan defer, finally, RAII, atau scoped resource management milik framework. Tetapkan pembersihan segera setelah akuisisi. Batasi pool, konkurensi, antrean, dan retry. Arahkan jalur pembatalan, timeout, dan early-return melalui logika pembersihan yang sama.
Dalam program multithreaded, memanggil open() dan menyetel FD_CLOEXEC dalam operasi berikutnya menciptakan celah di mana thread lain dapat melakukan fork dan exec. Jika didukung, setel O_CLOEXEC secara atomik pada saat pembuatan. Itu mencegah race condition pewarisan; ini tidak menggantikan kepemilikan close() biasa.
Langkah 7: Pisahkan Mitigasi Insiden dari Perbaikan Jangka Panjang
Tergantung pada risikonya, mitigasi insiden dapat mencakup:
- melakukan rate-limiting pada pekerjaan baru atau mengurangi konkurensi per instance sebelum proses kehilangan kemampuan untuk membuka log, koneksi kontrol, dan file konfigurasi;
- me-roll instance yang bocor sambil mempertahankan setidaknya satu sampel diagnostik dan menghindari restart serentak;
- menaikkan soft dan hard limit proses layanan yang sebenarnya setelah memeriksa memori, overhead kernel, dan kapasitas downstream;
- menambahkan instance sehingga konkurensi yang sah didistribusikan ke lebih banyak proses.
Mengubah ulimit -n di terminal saat ini tidak memengaruhi layanan yang sudah berjalan. Modifikasi service manager, container, atau runtime yang sebenarnya membuat proses, restart, dan verifikasi /proc/<new-pid>/limits. Pengeditan file konfigurasi saja bukanlah bukti bahwa limit baru telah aktif.
Perbaikan permanen harus menargetkan objek yang terkonfirmasi bertambah: selesaikan jalur penutupan, batasi pool dan konkurensi, perbaiki siklus hidup rotasi atau watcher, tetapkan timeout yang berguna, cegah pewarisan yang tidak diinginkan, dan ekspos hitungan saat ini ditambah counter create/release untuk kategori sumber daya utama.
Langkah 8: Buktikan Perbaikan dengan Anggaran Kapasitas dan Slope
Buat anggaran FD per instance:
baseline FDs + peak inbound connections + peak outbound connections + pools and files + IPC/event objects + safety headroom
Anggaran harus berasal dari arsitektur nyata dan uji beban (load test). Tidak ada persentase utilisasi universal untuk setiap layanan. Batas tersebut juga harus menyisakan ruang untuk diagnostik, health check, logging, dan koneksi kontrol selama insiden terjadi.
Verifikasi setidaknya harus mencakup:
- di bawah target lalu lintas puncak dan kegagalan yang diinjeksikan, total penggunaan FD naik ke batas stabil;
- setelah beban turun dan timeout berakhir, descriptor berumur pendek kembali ke baseline yang diharapkan;
- jenis objek yang sebelumnya bertambah tidak lagi memiliki slope positif yang persisten;
EMFILE,ENFILE, kegagalan koneksi, dan kegagalan pembukaan file tetap di angka nol;- p95/p99 permintaan, waktu tunggu pool, dan volume retry tidak mengalami regresi karena batasan yang terlalu agresif;
- deploy berulang, rotasi log, reload konfigurasi, dan peluncuran child-process tidak menciptakan pertumbuhan bertingkat (staircase growth);
- pemantauan mencakup
process_open_fds,process_max_fds, utilisasi, laju pertumbuhan, dan pool objek utama.
“Uji beban sepuluh menit berhasil” dapat melewatkan kebocoran lambat. Jalankan cukup lama untuk mencakup jumlah pertumbuhan yang menyebabkan insiden awal, atau perbesar jalur yang dicurigai dan buktikan bahwa counter create dan release seimbang.
Contoh Jawaban yang Kuat
“Pertama-tama saya akan mengonfirmasi bahwa errno-nya adalah EMFILE dan bahwa worker API itu sendiri yang mengalami kegagalan. File descriptor adalah indeks non-negatif di tabel FD proses. Entri tabel merujuk ke open file description di seluruh sistem, yang menyimpan offset dan file-status flag, lalu merujuk ke file reguler, socket, pipe, atau objek kernel anonim. dup dan fork dapat membuat beberapa descriptor berbagi satu open file description, sehingga jumlah FD proses dan jumlah file-handle di seluruh sistem merupakan metrik yang berbeda.
EMFILE berarti proses ini mencapai RLIMIT_NOFILE; ENFILE berarti host mencapai file-max. Di sini, soft limit adalah 8.192, jumlah sebelum insiden mendekati nilai tersebut, dan file-nr berada jauh di bawah file-max, jadi mengubah batas di seluruh sistem bukanlah sasaran yang tepat.
Saya akan membaca /proc/<pid>/limits, lalu mengambil sampel jumlah dan target symlink di /proc/<pid>/fd, yang dikelompokkan ke dalam socket, pipe, file reguler, dan objek anon_inode. Saya akan menyelaraskan slope setiap kategori dengan koneksi inbound, pool upstream, rotasi file, child process, dan error. Dimulai mendekati 400 dan bertambah 25 per menit di bawah lalu lintas yang stabil, yang tereset saat restart, sangat mengindikasikan kebocoran. Jika socket dari satu upstream mendominasi, saya akan memeriksa penutupan response-body, pembatalan timeout, dan jalur pengembalian ke pool alih-alih berasumsi bahwa setiap koneksi mencerminkan lalu lintas yang valid.
Untuk mitigasi, saya akan menerapkan rate-limit dan me-roll instance sambil mempertahankan sampel diagnostik. Jika analisis kapasitas memungkinkan, saya dapat menaikkan limit untuk sementara di service manager nyata atau konfigurasi container, tetapi saya harus memverifikasi /proc/<pid>/limits dari proses baru. Perbaikan jangka panjang membuat kepemilikan dan pembersihan sumber daya menjadi struktural, membatasi pool, retry, timer, dan watcher, serta mencegah pewarisan yang tidak diinginkan dengan close-on-exec.
Saya akan memverifikasi di bawah beban puncak target dan jalur kegagalan. Penggunaan FD harus mencapai batas stabil yang direncanakan dan kembali ke baseline saat beban turun. Kategori yang sebelumnya bertambah harus berhenti menumpuk, EMFILE harus tetap nol, serta tail latency dan waktu tunggu pool tidak boleh mengalami regresi. Hasil tersebut membuktikan perbaikan; restart atau limit yang lebih besar hanya membuktikan bahwa habisnya sumber daya berhasil ditunda.”
Kesalahan Umum
- Memperlakukan FD sebagai path atau inode → itu adalah indeks dalam tabel proses → jelaskan tabel FD, open file description, dan objek yang mendasarinya.
- Berasumsi hanya file disk yang mengonsumsi FD → socket, pipe,
epoll, timer, dan watcher juga menggunakannya → klasifikasikan target/proc/<pid>/fd. - Mengubah
fs.file-maxuntuk setiap error Too many open files →EMFILEdanENFILEmemiliki cakupan yang berbeda → konfirmasikan errno dan PID yang gagal terlebih dahulu. - Menggunakan
ulimit -nshell saat ini sebagai limit layanan → layanan yang berjalan mungkin diluncurkan di tempat lain → baca/proc/<pid>/limits. - Menyatakan kebocoran hanya karena jumlahnya tinggi → konkurensi tinggi yang valid dapat menciptakan batas stabil (plateau) yang tinggi → bandingkan model kapasitas, campuran tipe, slope, dan pemulihan setelah beban selesai.
- Hanya menaikkan 8.192 menjadi 65.536 → slope kebocoran yang tetap akan menghabiskan limit baru juga → perlakukan peningkatan sebagai kapasitas yang tervalidasi atau headroom sementara.
- Hanya memeriksa jalur pengembalian normal → timeout, pembatalan, retry, dan early return biasanya melewatkan pembersihan → definisikan pembuat, pemilik, dan pembersihan jalur kegagalan untuk setiap sumber daya.
- Menggunakan satu snapshot
lsof→ snapshot tidak dapat membuktikan akumulasi → ambil sampel pada interval tetap dan korelasikan dengan beban kerja serta pool. - Menerima hilangnya error untuk sementara → restart dan limit yang lebih tinggi dapat menunda kekambuhan → verifikasi jenis objek, slope, pemulihan, dan peristiwa siklus hidup yang berulang.
Pertanyaan Lanjutan
Lanjutan 1: Mengapa ulimit -n menunjukkan 65.536 sedangkan layanan masih gagal pada 8.192?
ulimit biasanya melaporkan shell saat ini dan memengaruhi proses turunan yang dibuat setelahnya. Layanan yang sudah diluncurkan oleh systemd, container runtime, atau process manager lain tidak diubah secara retroaktif. Supervisor dan worker-nya juga dapat memiliki pengaturan yang berbeda. Baca /proc/<pid>/limits milik PID yang gagal, perbarui batas peluncuran yang sebenarnya, dan verifikasi PID yang baru.
Lanjutan 2: Mengapa dua descriptor untuk file yang sama dapat memengaruhi posisi baca satu sama lain?
Jika descriptor tersebut berasal dari dup, atau dari descriptor yang sama sebelum fork, keduanya merujuk ke open file description yang sama dan oleh karena itu berbagi offset dan status flag file. Jika program memanggil open() dua kali, path yang sama biasanya menghasilkan dua open file description independen dengan offset independen. Pathname bersama tidak membuktikan adanya open state bersama.
Lanjutan 3: Mengapa suatu proses masih dapat menggunakan file melalui FD setelah file tersebut dihapus?
Descriptor merujuk ke open file description; I/O tidak me-resolve pathname lagi setiap saat. Menghapus entri direktori tidak membatalkan referensi yang ada. Objek yang mendasarinya dapat tetap ada sampai referensi terakhir ditutup. Rotasi log yang menghapus (unlink) file lama tanpa membuat proses menutupnya dapat mengonsumsi descriptor dan ruang disk sekaligus.
Lanjutan 4: Mengapa menaikkan RLIMIT_NOFILE ke angka yang sangat besar bisa gagal?
Proses tanpa hak istimewa (unprivileged) tidak dapat menaikkan soft limit di atas hard limit atau menaikkan hard limit-nya secara bebas. Linux juga membatasi RLIMIT_NOFILE dengan /proc/sys/fs/nr_open. Service manager, container, atau batas izin dapat menambahkan batasan. Periksa error saat startup dan batas efektif proses yang baru setelah setiap perubahan.
Lanjutan 5: Jika satu instance epoll memantau banyak koneksi, mengapa proses masih bisa kehabisan FD?
Instance epoll itu sendiri mengonsumsi satu FD dan muncul sebagai anon_inode:[eventpoll]. Setiap socket yang dipantau tetap menjadi FD terpisah. epoll membuat penantian pada banyak koneksi menjadi efisien; ia tidak menggabungkan ribuan socket menjadi satu descriptor atau menutupnya untuk aplikasi.
Lanjutan 6: Bagaimana Anda mengatur peringatan (alert) pada penggunaan FD?
Pantau descriptor terbuka saat ini, batas maksimum proses, utilisasi, dan laju pertumbuhan per instance. Utilisasi mendeteksi kedekatan dengan batas kehabisan; slope mendeteksi kebocoran lambat lebih awal. Connection pool, file, dan watcher juga harus mengekspos hitungan saat ini masing-masing. Tetapkan ambang batas dari anggaran puncak, waktu penskalaan, dan lead time tanggap insiden alih-alih menyalin persentase universal.