Anatomi 'Silent Socket Leak' di Balik Reverse Proxy
TEXT
+----------------+ +---------------+ +-----------------+
| Client Pool | | Envoy Proxy | | PostgreSQL / DB |
| (App Server) | | (L4 TCP/Mesh) | | Engine |
+----------------+ +---------------+ +-----------------+
| | |
|====== Downstream TCP ===>|====== Upstream TCP =====>|
| | |
| (Client Pool Idle: 10m) | (Envoy Idle Timeout: 5m)|
| | |
| x [Envoy idle_timeout!] |
| |--- FIN/RST ------------->|
|<-- FIN ------------------| |
| (Masuk CLOSE_WAIT) | |
v v vMengapa TCP Keepalive Gagal Membantu?
tcp_keepalive di Envoy listener atau cluster configuration. Harapannya, paket probe keepalive akan menjaga koneksi tetap hidup selamanya. Ini adalah perangkap logika. Envoy mengukur keaktifan koneksi berdasarkan aliran data aktual (payload data transfer), bukan paket probe L4 TCP.
Probe TCP keepalive ditangani sepenuhnya oleh stack TCP kernel host tanpa melibatkan Envoy event loop. Karena Envoy tidak melihat adanya bytes yang diproses di L7 (atau data L4 yang diteruskan), internal timer Envoy tetap berdetik menuju batas timeout. Dari sudut pandang Envoy, koneksi tersebut tetap menganggur. Akibatnya, Envoy akan tetap mengeksekusi penutupan koneksi secara sepihak, menabrak probe keepalive yang sibuk lalu lalang di kernel.
Lebih parah lagi jika di antara Envoy dan database terdapat NAT gateway atau stateful firewall (misalnya AWS NAT Gateway atau cloud load balancer). Perangkat-perangkat perantara ini memiliki connection tracking table (conntrack) dengan batas idle time yang ketat. Jika conntrack table menghapus mapping sesi karena dianggap idle tanpa mengirimkan FIN/RST ke kedua belah pihak, socket upstream akan masuk ke kondisi half-open. Upstream database masih menganggap koneksi aktif, sementara Envoy atau client yang mencoba mengirim query berikutnya akan terjebak dalam lubang hitam retransmisi TCP hingga akhirnya menerima timeout error yang lambat.
Menyelaraskan Hirarki Timeout: Aturan Emas
/proc/sys/net/ipv4/tcp_keepalive_*, melainkan pada sinkronisasi hierarki umur koneksi di tiga titik: Client Pool, Proxy, dan Database Server.
Prinsip dasarnya sederhana: Koneksi harus selalu dimatikan secara proaktif oleh pihak yang paling dekat dengan inisiator (Client Pool), sebelum perantara atau server hilir kehabisan kesabaran. Rumus aman untuk menentukan timeout adalah:
Pool Max Lifetime < Proxy Idle Timeout < Database Server Idle Timeout
YAML
# Snippet konfigurasi Envoy cluster
clusters:
- name: postgres_backend
connect_timeout: 2s
type: STRICT_DNS
dns_lookup_family: V4_ONLY
typed_extension_protocol_options:
envoy.extensions.upstreams.net.generic.v3.GenericConnectionPoolProto:
"@type": type.googleapis.com/envoy.extensions.upstreams.net.generic.v3.GenericConnectionPoolProto
# Pastikan idle_timeout L4 lebih longgar dari client pool idle time
common_network_config:
idle_timeout: 900sidle_timeout: 900s (15 menit), maka connection pool di sisi aplikasi (misalnya HikariCP) harus disetel dengan maxLifetime maksimal 10 atau 12 menit, dan idleTimeout di kisaran 5 hingga 8 menit. Dengan begitu, client pool akan menutup koneksi secara elegan melalui protokol database native sebelum Envoy atau middlebox memutuskan sambungan secara sepihak.
Beralih ke Heartbeat Aplikasi Native
keepalives_idle, keepalives_interval, dan keepalives_count memang menyentuh socket option TCP_KEEPIDLE, tapi driver modern menyediakan mekanisme validasi koneksi yang jauh lebih superior. HikariCP memiliki fitur keepaliveTime yang secara periodik mengirimkan query ping ringan atau mengeksekusi JDBC isValid() pada koneksi yang sedang menganggur di pool. Karena ping ini membawa payload data riil, event loop di Envoy akan mendeteksinya sebagai aktivitas transfer yang valid, mereset idle timer Envoy, dan sekaligus memverifikasi bahwa query engine di database memang masih sanggup merespons.
Menjaga stabilitas infrastruktur modern yang dipenuhi layer proxy dan abstraction bukan tentang menumpuk lebih banyak timeout defensif, melainkan menyelaraskan siklus hidup koneksi secara sadar dari layer soket kernel hingga runtime aplikasi. Dengan mengonfigurasi TCP socket buffer secara proporsional dan mengaktifkan heartbeat aktif di level protokol database, ancaman silent socket leak dapat dieliminasi secara tuntas dari arsitektur produksi.