Bali, Indonesia
Insights

Mendiagnosis TCP Retransmission dan Kernel Buffer Bloat pada Edge PoP Multi-Kota neuCentrIX

October 15, 2026
0:00
Ketika kami mendistribusikan reverse proxy Envoy ke 17 edge PoP neuCentrIX yang tersebar dari Medan, Batam, Semarang, Surabaya, Denpasar, Balikpapan, hingga Makassar, hipotesis awal tim kami sangat optimis: memindahkan terminasi TLS dan caching layer sedekat mungkin ke eyeball network ISP lokal akan secara otomatis memangkas p99 tail latency di bawah 25 milidetik. Kenyataan di lapangan berkata lain. Pada jam sibuk (pukul 19.30 hingga 22.00 WIB), grafik telemetri Prometheus kami menyala merah. Sementara p50 latency tetap stabil di 12 ms, p99 tail latency meledak hingga menembus 1.850 ms pada koneksi dinamis yang memerlukan proxy pass ke origin server di Jakarta. Tingkat TCP retransmission melonjak dari baseline normal 0,2% menjadi 7,8% di PoP non-Jawa. Server edge tidak mengalami saturasi CPU (utilisasi core < 35%), kapasitas bandwidth uplink masih tersisa 40%, dan tidak ada packet drop fisik pada switch interface. Masalah sebenarnya tersembunyi jauh di dalam kernel space Linux: fenomena buffer bloat pada lapisan socket TCP yang dipicu oleh interaksi destruktif antara asimetri jalur backhaul antarpulau, ukuran auto-tuning memory buffer kernel yang kelewat agresif, serta algoritma congestion control konvensional yang memperlakukan delay antrian sebagai packet loss.
TEXT
+-----------------------------------------------------------------------------------------+
|                       TOPOLOGI ALIRAN TRAFIK EDGE NEUCENTRIX POP                        |
+-----------------------------------------------------------------------------------------+

 [ Eyeball Client ]                                                       [ Origin DC ]
 (Telkomsel/Indihome)                                                    (Tersentralisasi)
     |                                                                           |
     | RTT: 2 - 8ms                                                              | RTT: 35 - 70ms
     | BtlBw: 20 - 100 Mbps                                                      | BtlBw: 1 - 10 Gbps
     v                                                                           v
+-----------------------------------------------------------------------------------------+
| Edge Node (neuCentrIX Edge PoP - misal: Makassar / Balikpapan)                          |
|                                                                                         |
|  +-----------------------+                         +----------------------------------+ |
|  | Ingress NIC (Client)  |                         | Egress NIC (DCI Backhaul)        | |
|  +-----------+-----------+                         +-----------------+----------------+ |
|              |                                                       ^                  |
|              v                                                       |                  |
|  +-----------------------+                         +-----------------+----------------+ |
|  | Downstream Socket     |                         | Upstream Socket                  | |
|  | (sk_rcvbuf / TCP Win) |                         | (sk_sndbuf / fq qdisc)           | |
|  | Bloat: 4MB default    |                         | Bloat: Akumulasi antrian BDP     | |
|  +-----------+-----------+                         +-----------------+----------------+ |
|              |                                                       ^                  |
|              +------------> [ Envoy Proxy Worker ] ------------------+                  |
|                             (User Space Ring Buffer)                                    |
+-----------------------------------------------------------------------------------------+
Edge PoP regional di Indonesia menghadirkan karakteristik topologi yang sangat unik. Di sisi downstream (client ke Edge Envoy), koneksi didominasi oleh akses last-mile 4G/5G dan FTTH domestik dengan RTT sangat rendah (2 hingga 8 ms) namun memiliki jitter tinggi akibat penjadwalan radio nirkabel. Sebaliknya, di sisi upstream (Edge Envoy ke Origin Core di Jakarta), paket melintasi link fiber optic submarine (DCI - Data Center Interconnect) dengan latensi deterministik 35 hingga 70 ms. Di sinilah petaka performa bermula. Ketika client mengirimkan HTTP POST atau request API dinamis berukuran besar, atau ketika Edge harus men-streaming non-cacheable response payload kembali ke client, Envoy bertindak sebagai mediator antara dua koneksi TCP dengan Bandwidth-Delay Product (BDP) yang jomplang secara ekstrem:
TEXT
BDP = Bottleneck Bandwidth (BtlBw) × Round Trip Time (RTprop)
Secara default, kernel modern Linux (kernel 5.15/6.1 LTS) mengaktifkan TCP autotuning (tcp_moderate_rcvbuf = 1). Parameter default bawaan distribusi enterprise kerap menyetel batas atas memory socket seperti berikut:
TEXT
net.ipv4.tcp_rmem = 4096 131072 6291456
net.ipv4.tcp_wmem = 4096 16384 4194304
Dengan nilai batas atas 4 MB hingga 6 MB per socket, kernel mencoba memaksimalkan throughput dengan terus memperbesar TCP Receive Window (rcv_wnd) dan Congestion Window (cwnd). Pada link berkapasitas tinggi dengan delay sedang, hal ini masuk akal. Namun, ketika downstream eyeball mengalami kongesti sesaat pada Base Transceiver Station (BTS) operator lokal, laju pengurasan socket di sisi client anjlok drastis. Karena Envoy membaca dari upstream dengan kecepatan gigabit, namun terhambat saat menulis ke downstream, kernel Linux di edge node mulai menimbun paket di dalam sk_sndbuf (socket send buffer). Kernel tidak menjatuhkan paket (no drops), melainkan terus memperbesar antrian buffer transmisi. Paket-paket tersebut tertahan di antrian memori hingga ratusan milidetik. Akibatnya, RTT yang diukur oleh TCP stack membengkak secara artifisial dari 8 ms menjadi 1.200 ms. Ini adalah definisi tekstual dari Buffer Bloat. Begitu buffer bloat terjadi, timeout RTO (Retransmission Timeout) downstream terpicu secara salah (spurious timeouts). Klien mengira paket hilang dan mengirimkan duplikat request, yang makin memperparah saturasi antrian memory socket di edge proxy.
Banyak system engineer berasumsi bahwa jika batas tcp_wmem disetel ke 4 MB, maka satu socket TCP hanya akan mengonsumsi maksimal 4 MB RAM fisik. Asumsi ini keliru dan berakibat fatal pada stabilitas memori edge server yang menangani puluhan ribu concurrent connection. Di dalam kernel Linux, setiap segmen TCP dibungkus oleh struktur data struct sk_buff (socket buffer descriptor) ditambah metadata pendukung struct skb_shared_info. Ukuran struktural ini memakan alokasi slab kmalloc tersendiri di luar payload data aktual:
TEXT
+-------------------------------------------------------------------+
|                    ANATOMI MEMORI sk_buff LINUX                   |
+-------------------------------------------------------------------+
| struct sk_buff (head)        | ~224 - 256 bytes (slab kmalloc-256)|
+------------------------------+------------------------------------+
| Data Buffer (linear payload) | Alokasi page kmalloc (misal: 2048B)|
+------------------------------+------------------------------------+
| struct skb_shared_info       | ~320 bytes di akhir data buffer    |
|   - skb_frag_t frags[]       | (frag array untuk scatter-gather)  |
+------------------------------+------------------------------------+
Kernel melacak konsumsi memori ini menggunakan metrik truesize. Jika sebuah segmen TCP membawa payload data sebesar 1.460 byte (standard Ethernet MTU 1500 minus IP/TCP header), kernel mengalokasikan slab memori 2.048 byte untuk payload dan skb_shared_info, ditambah slab 256 byte untuk sk_buff. Rasio overhead (truesize / data_len) sering kali mencapai 1,5x hingga 2,4x lipat:
TEXT
truesize = SKB_DATA_ALIGN(payload + sizeof(struct skb_shared_info)) + SKB_TRUESIZE(sizeof(struct sk_buff))
Ketika 40.000 koneksi TCP secara simultan mengalami buffer bloat dan masing-masing memegang antrian teoritis 3 MB payload, memori fisik aktual yang terkunci di non-swappable kernel space via sk_wmem_alloc dan sk_forward_alloc melesat hingga mendekati 180 GB RAM. Kondisi ini memicu starvation memori subsistem jaringan, mengaktifkan tcp_enter_memory_pressure(), dan mematikan mekanisme alokasi socket baru tanpa pernah tercatat sebagai saturasi RAM user-space standar di metrik monitoring biasa. Bagi arsitek sistem yang juga mengelola service discovery dan resolution layer, kondisi tekanan soket dan OOM memori di level kernel ini memiliki konsekuensi serupa dengan yang kami bahas saat menjinakkan OOM killer dan UDP drops CoreDNS via cgroups v2.
Langkah pertama dalam membuktikan keberadaan buffer bloat dan spurious retransmissions adalah melakukan inspeksi langsung pada status internal TCP socket menggunakan utility ss dengan flag internal -ti (TCP internal info):
BASH
# Memeriksa status koneksi downstream yang bermasalah di interface 10G edge
ss -tiepm 'sport = :443' | awk 'NR%2{printf "%s ", $0; next} {print}' | head -n 5
Output telemetri riil dari salah satu node edge kami di neuCentrIX Makassar menunjukkan rincian kritis berikut:
TEXT
ESTAB 0 3145728 103.147.x.x:443 180.252.y.y:49211 timer:(on,482ms,0) ino:892341 sk:28a1f 
  cubic wscale:7,7 rto:680 rtt:584.21/212.18 ato:40 mss:1410 rcvspace:14600 rcv_ssthresh:64088 
  notsent:2097152 segs_out:14201 segs_in:8912 data_segs_out:13980 
  send 1547890bps lastsnd:12 lastrcv:140 lastack:12 
  pacing_rate 2476624bps delivery_rate 1120400bps 
  busy:14200ms rwnd_limited:1200ms(8.4%) sndbuf:4194304 unacked:1840 
  retrans:42/180 lost:12 reordering:3
Pecahkan data di atas:
  1. 0 3145728: Recv-Q bernilai 0, tetapi Send-Q mencapai 3,14 MB tertahan di socket memory.
  2. rtt:584.21/212.18: Smoothed RTT mencapai 584 ms dengan variansi 212 ms pada koneksi FTTH lokal yang seharusnya berada di angka 10-15 ms.
  3. notsent:2097152: Lebih dari 2 MB data sudah diserahkan oleh Envoy ke kernel buffer, namun belum di-pacing keluar oleh TCP scheduler.
  4. retrans:42/180: Tingkat retransmisi mencapai ~23% pada koneksi tunggal ini, didorong oleh RTO timeout yang kolaps.
Untuk membuktikan bahwa retransmisi terjadi bukan karena drop pada link fisik antar pulau, melainkan akibat timer kernel yang kedaluwarsa saat antrian buffer menumpuk, kami menulis script BPF kprobe sederhana menggunakan bpftrace:
TEXT
#!/usr/bin/env bpftrace

#include <net/sock.h>
#include <net/tcp.h>

kprobe:tcp_retransmit_skb
{
    $sk = (struct sock *)arg0;
    $tp = (struct tcp_sock *)arg0;
    $inet = (struct inet_sock *)arg0;

    saddr = ntop(inet->inet_saddr);
    daddr = ntop(inet->inet_daddr);
    dport = bswap(inet->inet_dport);

    srtt_ms =tp->srtt_us >> 3 >> 10;
    snd_una =tp->snd_una;
    snd_nxt =tp->snd_nxt;
    wmem_queued =sk->sk_wmem_queued;

    if (dport == 443 ||dport > 1024) {
        printf("SRC: %s | DST: %s:%d | sRTT: %d ms | wmem_queued: %d KB | inflight: %d\
",
            saddr,daddr, dport,srtt_ms, wmem_queued / 1024, (snd_nxt - $snd_una));
    }
}
Jalankan script tersebut selama pengujian beban:
BASH
sudo bpftrace tcp_retransmit_monitor.bt
Output telemetri terminal memperlihatkan pola sistemik:
TEXT
Attaching 1 probe...
SRC: 103.147.x.x | DST: 180.252.y.y:49211 | sRTT: 612 ms | wmem_queued: 3210 KB | inflight: 184
SRC: 103.147.x.x | DST: 114.125.z.z:53190 | sRTT: 489 ms | wmem_queued: 2890 KB | inflight: 142
SRC: 103.147.x.x | DST: 36.88.a.a:19402   | sRTT: 740 ms | wmem_queued: 3950 KB | inflight: 210
Korelasi terbukti secara mutlak: setiap kali retransmisi terjadi, wmem_queued berada di level gigantik (> 2,8 MB), dan sRTT melambung hingga 40-50 kali lipat dari RTT propagasi murni link. Algoritma CUBIC menginterpretasikan penundaan antrian ini sebagai kehilangan paket, memangkas cwnd, lalu masuk ke fase pemulihan yang lambat, sementara socket buffer tetap tersumbat.
Algoritma TCP CUBIC berbasis kehilangan paket (loss-based congestion control). CUBIC beroperasi dengan filosofi: terus menaikkan cwnd secara agresif sampai terjadi packet drop, lalu mundur drastis. Pada link edge asimetris dengan buffer switch yang besar di sisi provider last-mile, CUBIC akan mengisi setiap megabyte buffer yang tersedia sebelum akhirnya menjatuhkan satu paket. Kita membutuhkan algoritma berbasis model: BBR (Bottleneck Bandwidth and RTT). BBR tidak menggunakan packet drop sebagai indikator kongesti primer. BBR membangun model eksplisit dari path jaringan dengan mengukur dua parameter independen:
  1. BtlBw (Bottleneck Bandwidth): Laju transmisi maksimum yang dapat diterima link.
  2. RTprop (Round-Trip Propagation Time): Latensi delay fisik murni dari fiber optik tanpa antrian.
BBR membatasi jumlah data yang melayang di jaringan (inflight) tepat pada batas saturasi ideal:
TEXT
Target inflight = BtlBw × RTprop
Namun, BBRv1 memiliki kelemahan terkenal: sifatnya yang terlalu agresif dalam memperebutkan buffer terhadap aliran CUBIC konvensional, serta kecenderungannya untuk tetap mempertahankan antrian buffer jika terjadi kompresi ACK nirkabel. Solusi mutakhir yang kami terapkan pada kernel edge cluster kami adalah BBRv2. BBRv2 menyempurnakan kelemahan BBRv1 dengan mengintegrasikan sinyal eksplisit ECN (Explicit Congestion Notification) serta metrik packet loss terukur untuk menetapkan plafon dinamis inflight_hi. Ketika BBRv2 mendeteksi bahwa antrian mulai terbentuk pada router hop terakhir di jaringan lokal, BBRv2 segera membatasi rate transmisi (pacing) tanpa menunggu buffer penuh dan pecah.
TEXT
+-----------------------------------------------------------------------+
|                   DINAMIKA BBRv2 VS CUBIC PADA BUFFER                 |
+-----------------------------------------------------------------------+

 Kapasitas Buffer Router/Socket
  ^ 
  |======================== BUFFER LIMIT ============================== (Loss Drop CUBIC)
  |                                                    /\\     /\\
  |                                                   /  \\   /  \\
  |           CUBIC: Selalu mengisi buffer           /    \\ /    \\
  |           sampai batas maksimal                 /      V      \\
  |                                                /               \\
  |-----------------------------------------------/----------------- (BBRv1 inflight overshoot)
  | 
  |  - - - - - - - - - - BBRv2 OPERATING POINT - - - - - - - - - - - (Optimal BtlBw × RTprop)
  |  (Menjaga antrian buffer mendekati nol, inflight tepat terukur)
  | 
  +------------------------------------------------------------------> Waktu
BBR tidak dapat beroperasi secara optimal menggunakan antrian FIFO default Linux (pfifo_fast). BBR mewajibkan penggunaan Qdisc (Queueing Discipline) berbasis pacing, yaitu Fair Queueing (FQ). FQ memecah ledakan paket (bursts) menjadi aliran kontinu berjarak waktu presisi (rate-paced packet delivery) sesuai estimasi BBR, melenyapkan micro-bursts yang kerap membuat switch penyedia transit drop seketika. Terapkan konfigurasi kernel berikut di /etc/sysctl.d/99-edge-pop-tuning.conf pada seluruh server edge neuCentrIX:
INI
# ====================================================================
# TUNING KERNEL SYSCTL UNTUK EDGE POP POP-NEUCENTRIX (HIGH CONCURRENCY)
# ====================================================================

# 1. Gunakan Fair Queueing (FQ) sebagai qdisc default untuk mendukung pacing BBR/BBRv2
net.core.default_qdisc = fq

# 2. Tetapkan algoritma congestion control ke BBRv2 (jatuh ke BBR jika v2 belum terkompilasi)
net.ipv4.tcp_congestion_control = bbr2

# 3. Pangkas batas atas memory buffer soket untuk mencegah buffer bloat ekstrim
# Format: min default max (dalam bytes)
# Default max dipangkas dari 4MB/6MB menjadi 1MB (cukup untuk BDP 100Mbps @ 80ms RTT)
# BDP = (100.000.000 / 8) * 0.080 = 1.000.000 bytes (~1MB)
net.ipv4.tcp_rmem = 4096 87380 1048576
net.ipv4.tcp_wmem = 4096 65536 1048576

# 4. Batasi alokasi global TCP memory pages (satuan adalah memory pages, biasanya 4KB)
# Mengatur memory pressure threshold agar kernel mengontrol socket bloat sebelum OOM killer aktif
# min, pressure, max
net.ipv4.tcp_mem = 262144 524288 786432

# 5. Batasi jumlah byte yang belum terkirim di antrian soket sebelum Envoy berhenti menulis
# tcp_notsent_lowat memastikan kernel hanya meminta data dari aplikasi jika antrian transmisi < 16KB
net.ipv4.tcp_notsent_lowat = 16384

# 6. Mitigasi SYN flood dan optimasi lifecycle socket di edge
net.ipv4.tcp_max_syn_backlog = 16384
net.core.somaxconn = 16384
net.ipv4.tcp_slow_start_after_idle = 0
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 15

# 7. Aktifkan ECN untuk memungkinkan interoperabilitas feedback kongesti downstream
net.ipv4.tcp_ecn = 1
Muat parameter baru tanpa reboot:
BASH
sudo sysctl --system
Periksa apakah FQ dan BBRv2 telah aktif pada antarmuka jaringan utama:
BASH
tc qdisc show dev eth0
Output yang benar harus menampilkan model FQ aktif dengan metrik pacing pacing:
TEXT
qdisc fq 8001: root refcnt 2 limit 10000p flows 1024 quantum 3028 target 4ms ceil unlimited 
  refill_delay 40ms orphan_mask 1023 pacing plimit 8000p
Parameter tcp_notsent_lowat = 16384 di atas adalah instrumen paling ampuh dalam mengatasi buffer bloat. Alih-alih membiarkan Envoy menuangkan puluhan megabyte ke dalam sk_sndbuf kernel secara membabi-buta, parameter ini memaksa fungsi sistem poll() / epoll_wait() pada Envoy untuk menandai socket sebagai non-writable sampai data yang belum terkirim (notsent) di dalam buffer turun di bawah 16 KB. Sisa antrian data tetap berada di user space, di mana Envoy dapat menerapkan backpressure secara elegan.
Konfigurasi kernel yang ketat tidak akan maksimal jika layer proxy user space tidak sadar akan batasan transport di bawahnya. Secara default, Envoy mengalokasikan buffer stream HTTP/2 dan HTTP/1.1 yang sangat longgar. Pada file konfigurasi Envoy /etc/envoy/envoy.yaml, batasi ukuran buffer per koneksi dan konfigurasi TCP windowing pada cluster downstream maupun upstream:
YAML
static_resources:
  listeners:
  - name: listener_ingress_443
    address:
      socket_address:
        address: 0.0.0.0
        port_value: 443
    # Membatasi buffer memory per-koneksi di user space (128 KB)
    per_connection_buffer_limit_bytes: 131072
    filter_chains:
    - filters:
      - name: envoy.filters.network.http_connection_manager
        typed_config:
          "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
          stat_prefix: ingress_http
          # Flow control HTTP/2 untuk mencegah stream buffer bloat
          http2_protocol_options:
            initial_stream_window_size: 65536     # 64 KB per stream
            initial_connection_window_size: 262144 # 256 KB per koneksi total
            max_concurrent_streams: 100
          route_config:
            name: local_route
            virtual_hosts:
            - name: dynamic_origin
              domains: ["*"]
              routes:
              - match:
                  prefix: "/"
                route:
                  cluster: upstream_origin_jakarta
                  timeout: 15s
                  retry_policy:
                    retry_on: "5xx,gateway-error,connect-failure,reset"
                    num_retries: 2

  clusters:
  - name: upstream_origin_jakarta
    type: LOGICAL_DNS
    dns_lookup_family: V4_ONLY
    connect_timeout: 2s
    # Batasi buffer koneksi upstream ke core origin
    per_connection_buffer_limit_bytes: 524288 # 512 KB
    lb_policy: ROUND_ROBIN
    typed_extension_protocol_options:
      envoy.extensions.upstreams.http.v3.HttpProtocolOptions:
        "@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions
        explicit_http_config:
          http2_protocol_options:
            initial_stream_window_size: 131072   # 128 KB
            initial_connection_window_size: 1048576 # 1 MB
    load_assignment:
      cluster_name: upstream_origin_jakarta
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address:
                address: origin-internal.infra.internal
                port_value: 443
Dengan memangkas per_connection_buffer_limit_bytes ke 128 KB di downstream dan membatasi initial_stream_window_size, Envoy menghentikan pembacaan frame data dari upstream origin ketika client hilir tidak mampu mengonsumsi paket dengan cepat (HTTP/2 stream multiplexing backpressure). Aliran data tertahan secara elegan di sumbernya, bukan bertumpuk di memori kernel node edge.
Setelah menerapkan kombinasi tuning kernel (BBRv2 + fq + tcp_notsent_lowat = 16384 + pemangkasan tcp_wmem) dan pengetatan buffer stream Envoy di seluruh PoP neuCentrIX, kami memantau performa selama 14 hari penuh siklus trafik produksi. Berikut perbandingan metrik operasional edge cluster sebelum dan sesudah perubahan:
Parameter Metrik OperasionalSebelum Tuning (CUBIC Default)Setelah Tuning (BBRv2 + FQ + Lowat)Dampak Produksi
TCP Retransmission Rate4.82% (Peak Flash Sale: 8.1%)0.28% (Peak Flash Sale: 0.41%)Penurunan retransmisi sebesar 94.2%
RTT P99 (Edge ke Pelanggan)148 ms (Bufferbloat queuing)22 ms (Dominan propagation delay)Latensi P99 terpangkas 85%
Alokasi sk_buff Kernel per Node12.8 GB (Memicu tekanan cgroup)1.9 GB (Terkendali stabil)Eliminasi risiko OOM kernel slab
Envoy RSS Memory per Pod3.4 GB (Heap bloat tak terkendali)480 MB (Bounded stream limits)Alokasi memori datar & terprediksi
Throughput Payload Efektif1.82 Gbps (Jenuh packet stalls)3.94 Gbps (Optimal wire line-rate)Kenaikan kapasitas bandwidth 116%
Insiden ini menegaskan prinsip fundamental dalam sistem terdistribusi skala tinggi: memori tidak terbatas pada heap aplikasi runtime (Go/Node.js), melainkan hidup berdampingan di lapisan kernel transport.
  1. Jendela TCP Besar Bukan Jaminan Throughput: Membuka tcp_wmem hingga 16 MB tanpa mekanisme kontrol tcp_notsent_lowat di lingkungan BDP asimetris hanya menciptakan ilusi kapasitas, yang berujung pada bufferbloat dan degradasi RTT P99.
  2. Pentingnya Sinergi L4 Kernel dan L7 Application Gateway: Tuning kernel sehebat apa pun akan bocor apabila reverse proxy (Envoy/Nginx) membiarkan read buffer upstream membanjiri downstream yang lambat. Pengetatan per_connection_buffer_limit_bytes adalah benteng pertahanan pertama backpressure end-to-end.
  3. Observabilitas L4 Wajib Ada di Dashboard SRE: Jangan hanya bergantung pada metrik L7 HTTP status code 200 OK. Jika retransmisi TCP kernel mencapai lebih dari 1%, pengalaman pengguna di edge sudah terdegradasi secara diam-diam (silent latency penalty). Monitoring proaktif via tc -s qdisc dan ss -ntm adalah syarat mutlak keandalan multi-PoP edge.