Server konvensional biasanya memiliki satu listening socket untuk satu alamat dan port lokal. SO_REUSEPORT mengubah batas kepemilikan tersebut: beberapa socket yang memenuhi syarat dapat melakukan bind ke alamat yang sama, kemudian Linux memilih anggota reuseport group saat trafik tiba.

Mekanisme ini cocok untuk beberapa worker thread atau process yang perlu menerima trafik tanpa berbagi satu accept queue atau receive queue. Perubahannya terjadi pada pemilihan socket di kernel, bukan pada protokol transport di jaringan.

Setiap anggota harus mengaktifkannya sebelum bind

Linux mendukung SO_REUSEPORT untuk socket IPv4 dan IPv6 sejak kernel 3.9. Setiap socket, termasuk socket pertama, harus mengaktifkan opsi ini sebelum bind().

int one = 1;
if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one)) == -1) {
    /* tangani error */
}
if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
    /* tangani error */
}

Aturannya bukan sekadar mengizinkan alamat yang sudah ditempati socket lain. Linux juga mensyaratkan process yang melakukan bind pada alamat reuseport yang sama memiliki effective UID yang sama. Pembatasan ini mencegah process yang tidak terkait masuk ke group dan menerima trafik milik service.

SO_REUSEPORT juga berbeda dari SO_REUSEADDR. Opsi kedua melonggarkan pemeriksaan tertentu terkait pemakaian ulang alamat, sedangkan reuseport secara eksplisit mengizinkan beberapa socket peserta berbagi endpoint lokal identik sesuai aturan group.

TCP membagi koneksi sebelum accept

Pada server TCP, setiap worker dapat memiliki listening socket terpisah yang terikat ke alamat yang sama. Koneksi masuk dipilihkan ke satu listener, lalu accept queue milik listener tersebut menerima koneksi.

Struktur ini menghilangkan keharusan semua worker berebut satu file descriptor listening. Arsitektur dengan satu acceptor yang menerima seluruh koneksi lalu menyerahkan descriptor hasil accept ke worker lain juga tidak wajib digunakan.

Pemilihan terjadi sebelum aplikasi memanggil accept(). Setelah koneksi menjadi milik suatu listener dan diterima, semantik TCP normal tetap berlaku. Reuseport tidak membagi byte dari satu koneksi established ke beberapa socket.

UDP membagi datagram ke anggota group

Pada UDP, opsi yang sama memungkinkan beberapa socket melakukan bind ke satu endpoint lokal. Datagram masuk dipilihkan ke socket dalam group sehingga worker tidak harus berebut satu receive queue.

Pemilihan tersebut tidak menggandakan setiap datagram ke seluruh anggota. Reuseport merupakan mekanisme distribusi, bukan mekanisme broadcast. Software yang memerlukan pemetaan tertentu perlu memakai selector eksplisit dan tidak bergantung pada detail implementasi yang kebetulan berlaku.

BPF dapat mengganti selector default

Linux menyediakan SO_ATTACH_REUSEPORT_CBPF dan SO_ATTACH_REUSEPORT_EBPF untuk reuseport group. Program yang dipasang dapat memilih socket penerima dengan mengembalikan indeks group yang valid. Indeks tidak valid dari selector classic BPF atau socket-filter eBPF membuat Linux kembali memakai pemilihan reuseport biasa.

Indeks socket mengikuti urutan keanggotaan group. Untuk UDP, urutannya mengikuti pemanggilan bind(); untuk TCP, urutannya mengikuti listen(). Saat satu socket dikeluarkan, Linux dapat memindahkan anggota terakhir ke indeks yang kosong. Selector karena itu tidak boleh menganggap satu indeks selalu mewakili process yang sama.

Dukungan pemilihan reuseport dengan BPF tersedia untuk UDP sejak Linux 4.5 dan TCP sejak Linux 4.6. BPF_PROG_TYPE_SK_REUSEPORT, tersedia sejak Linux 4.19, menyediakan tipe program khusus reuseport dan dapat memakai bpf_sk_select_reuseport untuk memilih socket.

Keanggotaan group menjadi bagian dari topologi server

Desain reuseport memindahkan sebagian distribusi request ke kernel. Hal ini dapat mengurangi contention pada queue bersama, tetapi lifecycle socket ikut menjadi bagian dari perilaku load balancing.

Menambah atau menghentikan worker mengubah keanggotaan group. Selector BPF harus tetap valid saat anggota berubah, dan metrik operasional sebaiknya dikumpulkan per worker serta secara agregat.

Opsi ini tidak menyediakan health check aplikasi. Process yang masih menjadi anggota group tetapi tidak lagi memproses pekerjaan dengan baik tetap dapat memengaruhi service. Readiness, draining, lifecycle worker, dan penanganan kegagalan tetap menjadi tanggung jawab aplikasi atau supervisor.

SO_REUSEPORT adalah primitive demultiplexing socket dengan kontrak terbatas: beberapa socket yang memenuhi syarat dapat memiliki satu endpoint lokal, lalu Linux memilih penerima untuk pekerjaan yang masuk. Pemilihan BPF tersedia ketika kebijakan distribusi default tidak memadai.