Episode ini mengoptimalkan Envoy: threading model dan worker threads, connection limits dan buffer sizes, tuning HTTP/2 connection pool, serta best practices optimasi CPU dan memori di bootstrap.

Envoy bisa menangani jutaan request per detik jika dikonfigurasi dengan benar — dan tersendat jika tidak. Episode 15 membahas performance tuning dan resource management: model threading, worker threads, batasan koneksi, ukuran buffer, tuning pool HTTP/2, dan optimasi resource di bootstrap. Filosofinya sederhana: sebelum menambah hardware, pahami dulu di mana Envoy menghabiskan CPU dan memori.
Envoy berjalan dengan beberapa jenis thread:
Jumlah worker thread dikendalikan flag --concurrency saat Envoy dijalankan, atau otomatis mengikuti jumlah core jika tidak diatur.
envoy --concurrency 4 -c /etc/envoy/envoy.yaml
docker run -d --cpus=4 --name envoy-perf \
-v ~/envoy-lab/configs:/etc/envoy \
-p 10000:10000 -p 9901:9901 \
envoyproxy/envoy:v1.31.0Perintah envoy --concurrency 4 membuat 4 worker threads. Aturan praktis: satu worker per core. Concurrency lebih besar dari core hanya menambah biaya context switching.
Untuk memastikan beban tersebar merata antar worker:
curl -s localhost:9901/stats | grep "worker_thread"
curl -s localhost:9901/stats | grep "runtime_override_count"Jika satu worker menangani jauh lebih banyak koneksi daripada lainnya, ada kemungkinan connection skew — masalah yang sering terjadi pada listener TCP dengan keepalive panjang. Metric di admin interface adalah titik awal diagnosis.
Perhatikan connection_limit per listener dan max_connections per cluster:
listeners:
- name: listener_0
address:
socket_address:
address: 0.0.0.0
port_value: 10000
connection_limit: 10000
per_connection_buffer_limit_bytes: 32768
clusters:
- name: api_service
connect_timeout: 0.25s
type: STRICT_DNS
lb_policy: LEAST_REQUEST
per_connection_buffer_limit_bytes: 32768
circuit_breakers:
thresholds:
- max_connections: 5000
max_requests: 10000Nilai per_connection_buffer_limit_bytes: 32768 membatasi buffer read/write tiap koneksi menjadi 32 KiB. Buffer yang terlalu besar membuat memori membengkak; terlalu kecil membuat throughput turun karena banyak syscall.
Setiap koneksi memakai buffer read dan write. Dengan limit 32 KiB, 10 ribu koneksi aktif membutuhkan sekitar 640 MB hanya untuk buffer. Sesuaikan limit agar total memori buffer masuk budget container.
Untuk cluster upstream yang mendukung HTTP/2, konfigurasi pool sangat menentukan latensi:
clusters:
- name: api_service
connect_timeout: 0.25s
type: STRICT_DNS
lb_policy: LEAST_REQUEST
http2_protocol_options:
max_concurrent_streams: 100
initial_stream_window_size: 1048576
initial_connection_window_size: 6291456
connection_keepalive:
interval: 30s
timeout: 5smax_concurrent_streams: 100 mengontrol berapa stream paralel per koneksi HTTP/2. Nilai initial_connection_window_size yang lebih besar meningkatkan throughput untuk transfer besar, tapi menambah memori per koneksi. Tuning ini khas HTTP/2 dan tidak ada padanannya di HTTP/1.
connection_keepalive menjaga koneksi HTTP/2 tetap hangat dengan PING berkala, sehingga koneksi tidak mati di perangkat NAT. Ini mengurangi frekuensi pembuatan koneksi baru yang mahal.
Jika listener di edge menangani klien modern, aktifkan HTTP/3:
listeners:
- name: listener_http3
address:
socket_address:
address: 0.0.0.0
port_value: 10000
udp_listener_config:
quic_options: {}
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
http3_protocol_options: {}
stat_prefix: h3_ingress
route_config:
name: h3_routes
virtual_hosts: []
http_filters:
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.RouterBagian udp_listener_config dan http3_protocol_options mengaktifkan QUIC/HTTP/3 pada listener. HTTP/3 mengurangi latensi di jaringan yang tidak stabil — trade-off dengan kompleksitas operasional.
Beberapa pengaturan bootstrap memengaruhi penggunaan resource secara keseluruhan:
bootstrap:
idle_timeout: 300s
drain_time: 5s
parent_shutdown_time: 5s
stats_config:
stats_flush_interval: 30s
admin:
address:
socket_address:
address: 0.0.0.0
port_value: 9901Nilai idle_timeout: 300s menutup koneksi yang menganggur, membebaskan buffer. drain_time dan parent_shutdown_time mengatur perilaku saat Envoy berganti versi — penting untuk rolling update tanpa kehilangan request.
Scrape Prometheus yang terlalu sering memicu alokasi string besar. Interval 15 sampai 30 detik umumnya cukup; untuk high-cardinality metrics, episode 21 membahas strategi yang lebih detail.
Untuk mengukur peningkatan, jalankan benchmark sebelum dan sesudah tuning:
for i in $(seq 1 200); do
curl -s -o /dev/null http://localhost:10000/api/ping
done
k6 run --vus 50 --duration 30s loadtest.jsPerintah k6 run (jika terpasang) memberi metrik p50, p95, dan p99 yang lebih andal daripada loop curl. Bandingkan angka sebelum dan sesudah mengubah max_concurrent_streams atau ukuran buffer untuk memastikan perubahan benar-benar membantu.
docker stats envoy-perf
curl -s localhost:9901/stats | grep "^server.memory_allocated"server.memory_allocated menunjukkan memori yang dialokasikan Envoy. Kombinasikan dengan docker stats untuk melihat apakah tuning buffer terlihat di level OS.
Episode 15 melengkapi kalian untuk mengoptimalkan Envoy: memahami worker threads, membatasi koneksi dan buffer, menyetel pool HTTP/2, dan mengukur dampak setiap perubahan.
Inti yang harus dibawa pulang:
--concurrency mengatur jumlah worker; satu worker per core adalah aturan praktis.per_connection_buffer_limit_bytes mengontrol memori tiap koneksi.max_concurrent_streams dan window sizes.udp_listener_config dan http3_protocol_options.Di episode 16 selanjutnya kita akan membahas Envoy extensions dan WASM filters — model ekstensi Envoy, cara menulis filter WASM sederhana, serta use case untuk custom auth, telemetry enrichment, dan transformasi request.