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) |
+-----------------------------------------------------------------------------------------+Anatomi Asimetri Backhaul: BDP Mismatch dan Ilusi Zero-Loss
TEXT
BDP = Bottleneck Bandwidth (BtlBw) × Round Trip Time (RTprop)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 4194304rcv_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.
Membedah sk_buff: Jejak Overhead Memori Kernel yang Terselubung
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) |
+------------------------------+------------------------------------+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))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.
Menyingkap Retransmisi Abnormal dengan bpftrace dan ss
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 5TEXT
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:30 3145728: Recv-Q bernilai 0, tetapi Send-Q mencapai 3,14 MB tertahan di socket memory.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.notsent:2097152: Lebih dari 2 MB data sudah diserahkan oleh Envoy ke kernel buffer, namun belum di-pacing keluar oleh TCP scheduler.retrans:42/180: Tingkat retransmisi mencapai ~23% pada koneksi tunggal ini, didorong oleh RTO timeout yang kolaps.
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));
}
}BASH
sudo bpftrace tcp_retransmit_monitor.btTEXT
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: 210wmem_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.
Pergeseran Paradigma: Mengapa CUBIC Gagal dan BBRv2 Jadi Penyelamat
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:
BtlBw(Bottleneck Bandwidth): Laju transmisi maksimum yang dapat diterima link.RTprop(Round-Trip Propagation Time): Latensi delay fisik murni dari fiber optik tanpa antrian.
TEXT
Target inflight = BtlBw × RTpropinflight_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)
|
+------------------------------------------------------------------> WaktuImplementasi Tuning Kernel dan Fair Queueing (FQ)
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 = 1BASH
sudo sysctl --systemBASH
tc qdisc show dev eth0TEXT
qdisc fq 8001: root refcnt 2 limit 10000p flows 1024 quantum 3028 target 4ms ceil unlimited
refill_delay 40ms orphan_mask 1023 pacing plimit 8000ptcp_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.
Sinkronisasi Flow Control pada Lapisan Envoy Proxy
/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: 443per_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.
Hasil Empiris dan Evaluasi Telemetri Pasca-Implementasi
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 Operasional | Sebelum Tuning (CUBIC Default) | Setelah Tuning (BBRv2 + FQ + Lowat) | Dampak Produksi |
|---|---|---|---|
| TCP Retransmission Rate | 4.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 Node | 12.8 GB (Memicu tekanan cgroup) | 1.9 GB (Terkendali stabil) | Eliminasi risiko OOM kernel slab |
| Envoy RSS Memory per Pod | 3.4 GB (Heap bloat tak terkendali) | 480 MB (Bounded stream limits) | Alokasi memori datar & terprediksi |
| Throughput Payload Efektif | 1.82 Gbps (Jenuh packet stalls) | 3.94 Gbps (Optimal wire line-rate) | Kenaikan kapasitas bandwidth 116% |
Pelajaran Kunci untuk Rekayasa Jaringan Edge Multi-PoP
- Jendela TCP Besar Bukan Jaminan Throughput: Membuka
tcp_wmemhingga 16 MB tanpa mekanisme kontroltcp_notsent_lowatdi lingkungan BDP asimetris hanya menciptakan ilusi kapasitas, yang berujung pada bufferbloat dan degradasi RTT P99. - 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_bytesadalah benteng pertahanan pertama backpressure end-to-end. - 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 viatc -s qdiscdanss -ntmadalah syarat mutlak keandalan multi-PoP edge.
