Dengan SO_REUSEPORT, beberapa socket TCP Linux dapat listen pada alamat lokal dan port yang sama secara bersamaan. Koneksi masuk ditetapkan ke salah satu anggota reuseport group sebelum aplikasi memanggil accept(). Aplikasi tidak lagi membutuhkan satu listening socket bersama sebagai satu-satunya titik handoff antara network stack dan banyak worker.
Perubahan ini lebih dari sekadar kelayakan bind(). Distribusi koneksi dipindahkan ke kernel dan setiap listener memiliki identitas socket serta jalur accept sendiri. Arsitektur yang dihasilkan memiliki sifat queueing, lifecycle, dan routing yang berbeda dari desain ketika banyak worker berebut satu listening socket.
Opsi ini membentuk grup listener yang tetap terpisah
Linux mengizinkan beberapa socket AF_INET atau AF_INET6 melakukan bind ke alamat yang identik jika SO_REUSEPORT diaktifkan pada setiap socket peserta sebelum bind(). Untuk TCP, setiap socket kemudian masuk ke listening state secara independen.
Socket tersebut bukan alias untuk satu file description. Setiap listener adalah socket terpisah. Sebuah proses dapat menutup satu listener tanpa menutup listener lain, memasang state khusus listener bila interface mendukungnya, dan memanggil accept() pada satu anggota alih-alih descriptor bersama.
Linux juga membatasi keanggotaan grup. Proses yang melakukan bind ke alamat yang sama melalui mekanisme ini harus memiliki effective user ID yang sama, sehingga user yang tidak terkait tidak dapat masuk ke reuseport group yang sudah ada hanya dengan mengaktifkan opsi tersebut.
Jadi, batas arsitekturnya adalah sekumpulan listener yang memenuhi syarat untuk satu local endpoint, bukan satu listener yang direferensikan oleh beberapa worker.
Pemilihan terjadi sebelum accept
Tanpa reuseport, susunan multi-worker yang umum memakai satu listening socket bersama untuk thread atau process. Koneksi yang selesai menjadi tersedia melalui socket tersebut, lalu worker bersaing atau berkoordinasi di sekitar pemanggilan accept().
Reuseport group mengubah titik pemilihan. Linux memilih satu listening socket dari grup untuk traffic masuk. Worker yang memiliki atau memantau listener tersebut kemudian menerima koneksi yang sudah ditetapkan kepadanya.
Artinya, accept() bukan operasi load balancing. Saat suatu listener melaporkan koneksi yang dapat diterima, kernel-side selection sebelumnya sudah menempatkan koneksi itu pada jalur listener tersebut.
Perbedaan ini penting ketika mendiagnosis imbalance. Satu worker dapat memiliki accept path kosong sementara listener lain memiliki pekerjaan tertunda. Memperlakukan grup sebagai satu queue yang sepenuhnya dapat dipertukarkan menyembunyikan fakta bahwa assignment sudah terjadi lebih awal.
Alamat bind yang sama tidak berarti kontrak distribusi yang portabel
SO_REUSEPORT adalah socket option Linux dengan perilaku selection yang implementation-specific. Interface ini memungkinkan distribusi oleh kernel di seluruh grup, tetapi aplikasi tidak boleh menyimpulkan adanya kontrak round-robin universal hanya dari alamat bersama.
Penempatan koneksi dapat bergantung pada kernel selection logic dan informasi packet atau flow yang tersedia bagi logic tersebut. Properti stabil yang penting untuk desain aplikasi adalah bahwa kernel memilih satu anggota dari grup yang memenuhi syarat, bukan bahwa setiap anggota mendapat fraksi koneksi yang persis sama pada interval tertentu.
Hal ini membatasi kesimpulan yang dapat dibuat server dari jumlah listener dalam jangka pendek. Jumlah yang tidak sama tidak dengan sendirinya membuktikan listener rusak, dan jumlah yang sama bukan invariant yang dijamin kontrak.
Kehati-hatian yang sama berlaku lintas operating system. Socket option dengan nama serupa dapat memiliki semantics binding atau distribusi yang berbeda. Kode yang mengandalkan perilaku reuseport Linux memerlukan batas platform yang eksplisit.
BPF dapat mengubah selection default menjadi policy
Linux menyediakan hook classic BPF dan extended BPF untuk reuseport group. Program reuseport BPF dapat memengaruhi socket mana yang menerima traffic, sesuai program type dan return semantics yang didokumentasikan.
Untuk interface berbasis indeks, socket diberi nomor sesuai urutan masuk ke grup: bind order untuk UDP dan listen order untuk TCP. Keanggotaan grup tidak memiliki indeks permanen. Ketika satu socket keluar, Linux dapat memindahkan socket terakhir ke posisi anggota yang dihapus.
Aturan lifecycle ini membuat indeks menjadi posisi dalam grup saat ini, bukan identitas worker yang permanen. Policy yang menganggap indeks 2 selalu berarti satu process tertentu dapat menjadi salah setelah perubahan keanggotaan jika desain di sekitarnya tidak memperhitungkan reindexing.
Socket baru yang ditambahkan ke reuseport group mewarisi program BPF milik grup. Mengganti program melalui salah satu anggota menerapkan program saat ini pada grup. Jadi, attachment policy berorientasi pada grup walaupun setiap listener tetap merupakan socket terpisah.
Lifecycle listener menjadi bagian dari perilaku routing
Dalam desain shared-listener, menambah worker dapat dilakukan tanpa mengubah listening socket itu sendiri. Worker baru mulai menerima dari endpoint yang sudah ada.
Dengan satu reuseport listener per worker, lifecycle worker juga dapat mengubah keanggotaan grup. Memulai worker dapat menambah listener; menghentikannya dapat menghapus listener. Jika kernel selection atau program BPF yang terpasang bergantung pada komposisi grup, kejadian tersebut mengubah routing set.
Ini menciptakan batas antara connection assignment dan deployment state aplikasi. Koneksi yang sudah diterima tetap terkait dengan socket established masing-masing, sedangkan kedatangan berikutnya dipilih dari listener yang memenuhi syarat pada saat itu.
Graceful shutdown karena itu setidaknya memiliki dua concern berbeda: berhenti menerima assignment baru dan menguras koneksi yang sudah dimiliki worker. Menutup atau menghapus listener menangani concern pertama, tetapi tidak menghapus koneksi established yang sudah diterima oleh process tersebut.
Queue per-listener mengubah visibilitas overload
Listener terpisah juga berarti accept path terpisah. Server yang hanya mengekspor connection count agregat dapat gagal melihat konsentrasi pada satu anggota grup.
Misalkan empat worker masing-masing memiliki satu reuseport listener. Jika satu worker berhenti memanggil accept() tetapi masih menjadi anggota grup yang eligible, traffic masih dapat ditetapkan ke listener-nya sesuai selection policy aktif. Worker sehat yang menerima dengan cepat tidak otomatis mengambil pending connection dari listener tersebut seolah keempatnya berbagi satu accept queue.
Perilaku TCP queue dan konsekuensi overflow yang tepat bergantung pada kernel state, konfigurasi, dan protocol processing. Konsekuensi pada tingkat desain lebih sempit: listener independen menciptakan tempat independen di mana pending work dan application progress dapat berbeda.
Karena itu, operational signal lebih informatif bila mempertahankan identitas listener atau worker daripada merangkum seluruh grup menjadi satu angka endpoint.
Reuseport adalah distribusi, bukan koordinasi aplikasi
Kernel-side listener selection tidak mengoordinasikan application state antar-worker. Mekanisme ini tidak menserialisasi update, berbagi cache, mempertahankan session affinity di luar properti selection mechanism, atau membuat worker-local state terlihat secara global.
Service yang memerlukan koneksi menuju worker stateful tertentu membutuhkan routing rule yang benar-benar mengodekan kebutuhan tersebut, atau perlu memindahkan state relevan keluar dari local memory worker. Distribusi reuseport default tidak memberi salah satu jaminan tersebut.
Reuseport juga tidak menggantikan admission control. Banyak listener dapat mendistribusikan arrival work sementara semua worker tetap bergantung pada database, file descriptor budget, memory pool, atau kapasitas CPU yang sama.
Opsi ini mengubah lokasi satu keputusan routing. Ia tidak menghapus batas kapasitas setelah keputusan tersebut.
Listener menjadi bagian dari scheduling topology
Satu shared listening socket membuat kompetisi worker terlihat pada accept(). Reuseport group memindahkan keputusan scheduling yang lebih awal ke kernel dan menjadikan keanggotaan listener bagian dari topologi server.
Ini dapat menghapus application-level accept handoff dan menyelaraskan satu listener dengan satu worker, tetapi juga menciptakan listener state terpisah yang harus diamati dan dikelola sebagai state terpisah. Perubahan membership dapat memengaruhi assignment berikutnya, policy BPF harus memperhitungkan indeks yang dapat berubah, dan overload pada satu listener tidak sama dengan backlog pada satu shared socket.
Abstraksi yang berguna bukan sekadar beberapa process yang bind ke satu port. Ini adalah kernel-managed routing group dengan anggota yang tetap berupa listening socket terpisah.