Scaling & Resource Allocation #
Mengoperasikan Apache Kafka Connect di lingkungan produksi skala besar menuntut pemahaman mendalam tentang bagaimana performa didistribusikan secara paralel lintas kluster. Ketika volume data meningkat dari gigabyte menjadi terabyte per hari, pipeline integrasi kita harus mampu ditingkatkan kapasitasnya (scaled up) tanpa membebani sistem target atau broker Kafka. Untuk mencapai efisiensi ini, kita harus mengoptimalkan batas paralelisme melalui penyetelan parameter tasks.max, mengatur alokasi memori JVM dan Garbage Collector pada worker, serta merancang arsitektur penskalaan elastis di Kubernetes. Artikel ini akan membedah secara menyeluruh strategi penskalaan dan alokasi resource pada Kafka Connect agar pipa data kita dapat beroperasi dengan performa maksimal dan latensi seminimal mungkin.
Penentuan Batas Paralelisme Utama (tasks.max) #
Pilar pertama dalam penskalaan Kafka Connect adalah parameter tasks.max. Parameter ini ditentukan di setiap konfigurasi connector dan bertugas membatasi jumlah maksimum tugas paralel (task) yang boleh dijalankan oleh kluster Connect untuk connector tersebut.
Bagaimana Hubungan tasks.max dengan Skalabilitas? #
Ketika kita menyetel tasks.max, leader worker di kluster Connect akan mencoba membagi pekerjaan menjadi beberapa bagian yang mandiri (task) dan menyebarkannya ke seluruh worker yang aktif secara merata. Namun, paralelisme aktual sering kali dibatasi secara fisik oleh sistem sumber (untuk Source) atau partisi topik (untuk Sink):
flowchart TD
subgraph KafkaTopic ["Kafka Topic: orders (4 Partisi)"]
P0["Partition 0"]
P1["Partition 1"]
P2["Partition 2"]
P3["Partition 3"]
end
subgraph ConnectCluster ["Connect Cluster (tasks.max = 6)"]
T0["Sink Task 0"]
T1["Sink Task 1"]
T2["Sink Task 2"]
T3["Sink Task 3"]
T4["Sink Task 4 (IDLE)"]
T5["Sink Task 5 (IDLE)"]
end
P0 --> T0
P1 --> T1
P2 --> T2
P3 --> T3
1. Aturan Paralelisme pada Sink Connector #
Paralelisme Sink Connector dibatasi secara mutlak oleh jumlah partisi topik Kafka yang dibacanya.
- Jika kita menyetel
"tasks.max": "6", tetapi topik Kafka yang dibaca hanya memiliki 4 partisi, maka Kafka Connect hanya akan membuat 4 task aktif. Dua task lainnya akan berstatus idle (menganggur) karena tidak ada partisi topik tersisa yang bisa dialokasikan untuk mereka. - Rasio Ideal: Setel
tasks.maxsama dengan jumlah partisi topik Kafka yang dikonsumsi untuk throughput maksimal.
2. Aturan Paralelisme pada Source Connector #
Paralelisme Source Connector dibatasi oleh logika pembagian unit data di sistem eksternal sumber.
- JDBC Source: Jika kita melakukan polling terhadap 10 tabel, maka kita dapat menyetel
tasks.maxhingga10(masing-masing task menyalin 1 tabel). Jika tabel hanya ada 1, menyeteltasks.max=5tidak akan berguna karena 1 tabel tidak dapat dibagi pembacaannya lintas task. - Debezium CDC: Log transaksi database (WAL/Binlog) bersifat linier dan hanya dapat dibaca oleh satu thread pembaca tunggal untuk menjaga urutan event transaksi. Oleh karena itu, Debezium CDC Connector selalu memaksa eksekusi hanya 1 task saja (
tasks.max=1), terlepas dari seberapa besar kita menyetel nilai parameter tersebut.
Detail Threading Model di Kafka Connect Workers #
Untuk memahami bottlenecks CPU di dalam cluster Connect, kita perlu mengupas bagaimana thread dialokasikan di dalam JVM worker Connect. Setiap instansi worker mengelola beberapa kategori utas eksekusi yang berbeda:
1. Leader Coordinator Thread #
Thread ini bertanggung jawab untuk berkoordinasi dengan broker Kafka (Group Coordinator) untuk keanggotaan kluster Connect. Thread ini mengelola proses heartbeat dan mendengarkan sinyal rebalancing. Jika GC pause menghentikan thread ini terlalu lama, worker akan ditendang dari kluster.
2. Task Execution Threads #
Setiap task (baik Source Task maupun Sink Task) dieksekusi di dalam thread tersendiri yang diisolasi.
- Pada Source Task, thread ini menjalankan method
poll()dalam loop tidak terbatas. - Pada Sink Task, thread ini mengambil data dari consumer internal dan mengeksekusi method
put(). - CPU Spikes: Jika kita menjalankan 50 task di dalam satu node worker yang hanya memiliki 8 core CPU, maka akan terjadi persaingan thread yang parah (CPU context switching). Hal ini menyebabkan penurunan performa secara drastis.
3. Client Network Threads #
Kafka Producer internal (pada Source) dan Kafka Consumer internal (pada Sink) mempekerjakan thread jaringan (network threads) tambahan untuk mengirim dan menerima byte data via TCP/IP socket.
- Kebocoran Thread (Thread Leaks): Custom connector yang ditulis secara buruk sering kali tidak menutup koneksi database, HTTP client, atau file descriptor dengan benar saat task dihentikan (
stop()). Hal ini mengakibatkan jumlah thread terus bertambah dan memicu errorjava.lang.OutOfMemoryError: unable to create new native thread.
Desain Topologi Cluster Connect dan Isolasi Beban Kerja #
Dalam merancang infrastruktur data pipeline berskala perusahaan, salah satu keputusan arsitektural terpenting adalah menentukan jumlah kluster Connect fisik yang harus di-deploy.
Bahaya Menggunakan Satu Cluster Connect Raksasa (Unified Cluster) #
Menyatukan semua jenis connector (misalnya Debezium CDC untuk database ERP, S3 Sink untuk log audit, dan Elasticsearch Sink untuk pencarian produk) ke dalam satu kluster Connect logis tunggal adalah anti-pattern yang sangat berbahaya di lingkungan produksi:
- Blast Radius yang Luas: Jika salah satu Sink task mengalami OutOfMemory karena lonjakan beban data, seluruh JVM worker Connect tempat task itu berjalan akan crash. Hal ini mengganggu jalannya task lain yang tidak bersalah.
- Rebalance Storms: Menambahkan atau mengubah konfigurasi satu connector saja akan memicu rebalancing untuk seluruh connector di kluster tersebut. Jika kluster kita menjalankan 50 connector dengan total 200 task, proses rebalancing akan memakan waktu lama dan menyebabkan degradasi latensi global.
- Tabrakan group.id: Jika dua kluster Connect yang dideploy secara terpisah di VM yang berbeda secara tidak sengaja menggunakan
group.idyang sama, mereka akan bergabung menjadi satu kluster Connect raksasa yang tidak stabil. Mereka akan saling memperebutkan task dan memicu loop rebalancing tanpa henti.
Rekomendasi Topologi: Isolasi Kluster Berbasis Workload #
Kita sangat disarankan untuk memisahkan kluster Connect menjadi beberapa kluster fisik independen berdasarkan karakteristik beban kerjanya:
flowchart LR
DB["Database Subnet"] --> CDC["Connect CDC Cluster (group.id=connect-cdc)"] --> Kafka["Kafka Cluster"]
Kafka --> Sink["Connect Sink Cluster (group.id=connect-sink)"] --> Storage["Target Storage"]
- CDC Source Cluster: Didedikasikan khusus untuk Debezium/JDBC Connector. Cluster ini memiliki prioritas resource CPU/Memory tertinggi karena bertugas menangkap transaksi bisnis utama.
- Bulk Sink Cluster: Didedikasikan untuk S3, GCS, atau Snowflake Sink. Cluster ini dituning khusus untuk throughput besar (buffer memory besar) dan toleran terhadap latensi.
- Real-time Search/Cache Cluster: Didedikasikan untuk Elasticsearch dan Redis Sink. Dituning untuk latensi rendah (low latency).
Network Zoning dan Optimalisasi Biaya Lintas Zona (Cross-AZ Traffic) #
Untuk menjamin keamanan, kluster Connect harus ditempatkan pada subnet khusus (DMZ/private subnet) dengan aturan firewall yang ketat:
- REST API port
8083hanya boleh dibuka untuk subnet manajemen internal yang terpercaya. - Batasi koneksi keluar port database (seperti 5432 PostgreSQL atau 3306 MySQL) hanya ke alamat IP server database operasional.
- Biaya Transfer Data Lintas AZ (Cross-AZ Egress Cost): Cloud provider mengenakan biaya untuk transfer data antar Availability Zone. Jika database berada di AZ-a, pastikan pod worker Connect yang membaca database tersebut juga dideploy di AZ-a. Mengalirkan gigabyte data mentah CDC melintasi batas zona sebelum dikompresi dapat menghasilkan pembengkakan biaya jaringan yang tidak terduga.
Alokasi Resource Worker JVM: Memori & CPU Optimization #
Karena Kafka Connect berjalan di atas mesin virtual Java (JVM), performanya sangat bergantung pada konfigurasi alokasi memori heap, alokasi thread sistem, dan pengaturan Garbage Collector (GC).
1. Mengoptimalkan Heap Memory #
Worker Connect menangani banyak objek sementara selama proses deserialisasi dan transformasi data (SMT). Jika alokasi memori heap JVM terlalu kecil, JVM akan sering menjalankan proses Garbage Collection intensif yang memicu kondisi Stop-The-World (STW). Selama STW, worker tidak dapat mengirimkan detak jantung (heartbeat) ke broker Kafka, sehingga broker menganggap worker Connect mati dan memicu proses rebalancing yang mengganggu jalannya kluster.
- Rekomendasi Produksi: Gunakan setelan heap minimal 4 GB hingga 8 GB untuk kluster distributed worker menengah, dan pastikan nilai minimum (
-Xms) sama dengan nilai maksimum (-Xmx) untuk menghindari overhead resizing memori runtime:export KAFKA_HEAP_OPTS="-Xms8G -Xmx8G"
2. Menggunakan Garbage Collector G1 (G1GC) #
Hindari GC bawaan Java yang lama (Parallel GC) karena rentan menyebabkan pause panjang pada memori besar. Gunakan G1 Garbage Collector yang dirancang untuk pause pendek yang dapat diprediksi:
export KAFKA_JVM_PERFORMANCE_OPTS="-XX:+UseG1GC -XX:MaxGCPauseMillis=20 -XX:InitiatingHeapOccupancyPercent=35 -XX:+ExplicitGCInvokesConcurrent"
3. Pemakaian Memori Off-Heap #
Converters (terutama format Avro dan Parquet) sering kali mengalokasikan buffer byte di luar memori heap JVM (off-heap direct buffers) untuk mempercepat I/O disk dan jaringan. Pastikan sistem operasi server kita memiliki kapasitas memori fisik yang cukup di luar setelan heap JVM Connect agar tidak terkena pembunuhan proses oleh kernel Linux (Out Of Memory / OOM Killer).
4. Tuning Jetty HTTP Thread Pool #
REST API HTTP pada worker dijalankan oleh server tertanam Jetty. Secara default, Jetty mengalokasikan kumpulan thread pembaca HTTP yang dinamis. Jika tim kita sering melakukan kueri status cluster atau ada sistem otomatisasi yang memantau performa via REST API secara agresif, kita harus mengonfigurasi batas thread Jetty agar tidak mencuri CPU milik pemrosesan data utama:
# Ditulis pada connect-distributed.properties
# Batas maksimum thread Jetty untuk menangani REST API requests
rest.threads.max=100
Analisis JMX Metrics untuk Monitoring Skalabilitas #
Penskalaan elastis yang andal hanya dapat dicapai jika kita memiliki pemantauan (monitoring) metrik yang akurat. Kafka Connect mengekspos berbagai metrik internal via JMX (Java Management Extensions).
Berikut adalah metrik JMX krusial yang wajib kita pantau dan gunakan sebagai pemicu (trigger) alert atau scaling:
| Nama Metrik JMX | Kategori | Penjelasan Metrik |
|---|---|---|
source-record-poll-rate |
Source Task | Jumlah record per detik yang berhasil dibaca oleh Source Task dari sistem sumber eksternal. |
source-record-write-rate |
Source Task | Jumlah record per detik yang sukses ditulis ke Kafka. Jika angka ini jauh lebih kecil dibanding poll rate, terjadi hambatan internal di worker. |
poll-batch-time-ms |
Source Task | Waktu rata-rata yang dihabiskan task untuk sekali polling data dari sistem sumber. Kenaikan drastis menandakan overload di database sumber. |
sink-record-read-rate |
Sink Task | Jumlah record per detik yang dibaca task dari topik Kafka. |
put-batch-time-ms |
Sink Task | Waktu rata-rata yang dihabiskan task untuk sekali mengeksekusi penulisan data (put()) ke sistem target. Kenaikan menandakan overload di target (misal S3 atau Elasticsearch). |
offset-commit-failure-percentage |
Global | Persentase kegagalan komit offset. Angka di atas 0% menandakan masalah koordinasi transaksional atau timeout broker. |
Strategi Penskalaan Worker secara Horizontal #
Penskalaan horizontal dilakukan dengan menambahkan node instansi worker Connect baru ke dalam kluster distributed yang ada. Proses ini berjalan sangat mulus:
- Kita menjalankan kontainer Docker atau VM baru dengan konfigurasi
group.idyang sama. - Worker baru akan mendeteksi coordinator group di Kafka dan mengirimkan sinyal bergabung (JoinGroup).
- Kluster Connect memicu rebalance bertahap menggunakan protokol Incremental Cooperative Rebalancing.
- Sebagian task dari worker lama akan dipindahkan secara asinkron ke worker baru tanpa menghentikan jalannya task lain yang sehat.
Autoscaling di Kubernetes Menggunakan KEDA #
Di lingkungan cloud modern (seperti Amazon EKS atau Google GKE), kita dapat mengotomatiskan proses penskalaan horizontal pod worker Connect menggunakan KEDA (Kubernetes Event-driven Autoscaling).
KEDA bertindak sebagai autoscaler cerdas yang dapat memantau metrik di luar Kubernetes (seperti consumer lag langsung dari broker Kafka) dan menyesuaikan jumlah pod replika deployment Connect secara otomatis.
flowchart LR
subgraph KubernetesCluster ["Kubernetes Cluster"]
KEDAAgent["KEDA Controller"]
ConnectDeployment["Kafka Connect Pods (Replica: 2 to 10)"]
end
KafkaBroker["(\"Kafka Broker Cluster\")"] -->|Pantau Consumer Lag| KEDAAgent
KEDAAgent -->|Picu Scaling horizontal| ConnectDeployment
Contoh Manifest ScaledObject KEDA untuk Kafka Connect #
Di bawah ini adalah contoh manifest YAML Kubernetes kustom untuk mengonfigurasi KEDA agar menskalakan pod worker Connect (antara minimal 2 pod hingga maksimal 10 pod) berdasarkan jumlah akumulasi consumer lag pada topik orders-topic:
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: kafka-connect-autoscaler
namespace: data-pipeline
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: kafka-connect-worker-deployment
minReplicaCount: 2
maxReplicaCount: 10
cooldownPeriod: 300
pollingInterval: 30
triggers:
- type: kafka
metadata:
bootstrapServers: kafka-broker-1:9092,kafka-broker-2:9092
consumerGroup: connect-elasticsearch-sales-sink
topic: mysql-db-orders
# Picu penambahan 1 pod baru untuk setiap kelipatan 5000 consumer lag
lagThreshold: "5000"
activationLagThreshold: "100"
Dengan KEDA, jika sistem target Elasticsearch mengalami kelambatan yang menyebabkan lag di Kafka melonjak melewati 5.000 pesan, KEDA akan secara instan memicu penambahan pod worker Connect baru untuk membantu mempercepat proses konsumsi data. Setelah lag kembali bersih, KEDA akan menurunkan jumlah pod replika kembali ke batas minimum secara perlahan.
Ringkasan #
- Batas Parallel — Properti
tasks.maxmenetapkan batas paralelisme eksekusi tugas. Sink task dibatasi maksimal oleh jumlah partisi topik Kafka, sedangkan Debezium Source CDC dibatasi hanya 1 task saja.- Worker Threading — Setiap task berjalan di thread-nya sendiri. Hindari thread leak dengan memastikan pembersihan file descriptor dan koneksi database target saat task distop.
- Isolasi Beban Kerja — Jangan mencampur semua jenis connector dalam satu kluster Connect yang sama. Pecah kluster menjadi kelompok-kelompok khusus (misal khusus CDC, khusus Sink) demi keamanan dan pencegahan rebalance storm.
- JVM Tuning — Hindari jeda STW GC yang memicu rebalance palsu dengan mengalokasikan memori heap minimal 4GB-8GB dan mengaktifkan G1 Garbage Collector (
-XX:+UseG1GC).- Metrik JMX — Pantau
put-batch-time-msdanpoll-batch-time-msuntuk mendeteksi degradasi performa di sistem eksternal secara dini.- Kubernetes KEDA — KEDA memungkinkan autoscaling pod worker Connect secara elastis di Kubernetes berdasarkan metrik consumer lag di broker Kafka tanpa intervensi manual.
← Sebelumnya: Integrasi Sistem Eksternal Berikutnya: Error Handling & DLQ →