L
Event-Driven Architecture âąī¸ Interactive 15-Minute Recipe â€ĸ Literally Web ID

Membangun Sistem Real-Time Jutaan Koneksi dengan Event-Driven Architecture

âąī¸ 15 menit baca â€ĸ 📅 20 Oct 2026 â€ĸ đŸ‘ī¸ 1 views
Membangun Sistem Real-Time Jutaan Koneksi dengan Event-Driven Architecture
🔊 Dengarkan Artikel Ini

Dalam 15 menit ke depan, kita akan merakit sebuah sistem real-time berkapasitas jutaan koneksi simultan dari nol sampai berjalan mulus. Pengalaman di lapangan membuktikan bahwa menjaga koneksi WebSocket tetap hidup di angka jutaan bukanlah perkara menambah RAM server semata, melainkan bagaimana kita mendistribusikan beban menggunakan Event-Driven Architecture berbasis Node.js, Redis Pub/Sub, dan Nginx sebagai Reverse Proxy yang dikonfigurasi secara presisi. Mari kita mulai meraciknya di atas meja kerja kita.

1. Menu Kita Hari Ini & Alat yang Perlu Disiapkan

Sebelum tangan kita kotor dengan baris kode, mari pastikan semua bahan di atas meja siap. Kita tidak sedang membangun aplikasi todo list abal-abal; kita merancang sistem industri yang harus tahan banting.

Bahan-bahan yang wajib ada di server staging atau lokal Anda:

  • Node.js (v18+): Mesin utama penarik I/O asinkron kita.
  • Redis (v7+): Pipa saraf pusat (Pub/Sub) untuk komunikasi lintas cluster instance backend.
  • Nginx: Gerbang tol terdepan yang menangani SSL termination dan HTTP Upgrade ke protokol WebSocket.
  • Linux Kernel (Ubuntu/Debian): Dengan beberapa penyesuaian parameter sysctl untuk membebaskan batas file descriptor.

[!IMPORTANT] Jangan pernah mencoba menguji jutaan koneksi dari satu mesin klien yang sama karena Anda akan kehabisan port TCP lokal (ephemeral ports). Gunakan beberapa mesin generator beban seperti Artillery atau skrip kustom berbasis Go.

Begitu infrastruktur dasar ini menyala, mari kita petakan bagaimana alur data mengalir dari satu klien ke klien lainnya tanpa membuat server megap-megap.

2. Peta Jalan Singkat: Apa yang Sedang Kita Rakit

Bayangkan arsitektur kita seperti sebuah gedung perkantoran super besar. Nginx adalah satpam di lobi utama yang menyaring ribuan tamu masuk secara bersamaan. Node.js adalah para resepsionis yang melayani percakapan langsung, sementara Redis adalah sistem interkom kilat yang menghubungkan resepsionis di lantai 1 dengan resepsionis di lantai 10.

Langkah kerja kita hari ini:

  1. Menyetel parameter sistem operasi Linux agar tidak membatasi jumlah soket jaringan.
  2. Merakit server WebSocket Node.js yang terhubung ke Redis Pub/Sub agar bisa diskalakan secara horizontal (multi-instance).
  3. Memasang konfigurasi Nginx untuk melakukan load balancing dan menjaga koneksi persisten (keep-alive).
  4. Menguji ketahanan sistem secara langsung.

Melompat langsung ke langkah pertama, mari kita buka terminal dan mulai menjinakkan sistem operasinya.

3. Langkah 1: Mempersiapkan Fondasi & Environment

Secara default, sistem operasi Linux membatasi jumlah file yang bisa dibuka oleh satu proses (biasanya hanya 1024). Untuk menangani jutaan koneksi, setiap koneksi WebSocket dihitung sebagai satu file descriptor. Jika kita tidak mengubahnya, server akan langsung meneriakkan error EMFILE: too many open files dalam hitungan detik.

Buka konfigurasi pembatas sistem di /etc/security/limits.conf menggunakan editor favorit Anda, lalu tambahkan baris berikut:

* soft nofile 1000000
* hard nofile 1000000
root soft nofile 1000000
root hard nofile 1000000

Setelah itu, kita sesuaikan juga parameter kernel jaringan di /etc/sysctl.conf agar memori pengelolaan TCP dioptimalkan untuk trafik tinggi dan koneksi persisten:

# Memperbesar ukuran antrean koneksi masuk
net.core.somaxconn = 65535

# Mengizinkan reuse port untuk load balancing internal
net.ipv4.tcp_tw_reuse = 1

# Memperluas rentang port lokal untuk koneksi keluar
net.ipv4.ip_local_port_range = 1024 65535

# Mengoptimalkan memori buffer TCP untuk membaca/menulis data cepat
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216

Terapkan perubahan tersebut seketika dengan menjalankan perintah keramat ini di terminal:

sysctl -p

[!TIP] Perhatikan respons di terminal. Jika tidak ada pesan error yang muncul, itu tanda bahwa kernel Anda kini sudah siap menampung beban kerja kelas berat.

Fondasi sistem operasi sudah kokoh. Sekarang, saatnya kita meracik kode jantung aplikasi dan jembatan Redis-nya.

4. Langkah 2: Meracik Konfigurasi Inti Tanpa Basa-basi

Kita akan menulis server Node.js minimalis namun sangat bertenaga menggunakan pustaka ws dan ioredis. Buat direktori baru, inisialisasi proyek, dan pasang dependensinya:

mkdir realtime-core && cd realtime-core
npm init -y
npm install ws ioredis dotenv

Buat file bernama server.js. Di sinilah keajaiban Event-Driven Architecture terjadi. Kita menggunakan arsitektur di mana instance server WebSocket lokal akan mendengarkan event dari Redis Pub/Sub, sehingga jika ada pesan broadcast dikirim ke satu instance, instance lain di server berbeda tetap bisa meneruskannya ke klien mereka.

const { WebSocketServer } = require('ws');
const Redis = require('ioredis');

// Konfigurasi port dari environment atau default ke 8080
const PORT = process.env.PORT || 8080;
const wss = new WebSocketServer({ port: PORT });

// Koneksi Redis untuk Publisher dan Subscriber
// Redis mewajibkan koneksi terpisah untuk mode pub/sub
const pub = new Redis({ host: '127.0.0.1', port: 6379 });
const sub = new Redis({ host: '127.0.0.1', port: 6379 });

const CHANNEL_NAME = 'global-cluster-room';

// Berlangganan ke channel Redis
sub.subscribe(CHANNEL_NAME, (err, count) => {
  if (err) {
    console.error('Gagal berlangganan ke Redis Pub/Sub:', err);
    return;
  }
  console.log(`Berhasil terhubung ke Redis. Mendengarkan ${count} channel.`);
});

// Ketika pesan datang dari Redis, sebarkan ke semua klien lokal
sub.on('message', (channel, message) => {
  if (channel === CHANNEL_NAME) {
    wss.clients.forEach((client) => {
      if (client.readyState === client.OPEN) {
        client.send(message);
      }
    });
  }
});

// Menangani koneksi masuk dari klien
wss.on('connection', (ws, req) => {
  const clientIp = req.socket.remoteAddress;
  console.log(`Klien baru terhubung dari IP: ${clientIp}`);

  ws.on('message', (data) => {
    // Publikasikan pesan ke Redis agar didistribusikan ke seluruh cluster node
    pub.publish(CHANNEL_NAME, data.toString());
  });

  ws.on('close', () => {
    console.log('Klien memutuskan koneksi.');
  });

  ws.on('error', (error) => {
    console.error('Error pada soket klien:', error);
  });
});

console.log(`Server WebSocket berjalan mulus di port ${PORT}`);

Jalankan server tersebut dengan perintah node server.js. Anda akan melihat log yang menandakan koneksi ke Redis berjalan lancar. Tapi ingat, di depan server Node.js ini, kita butuh satpam yang handal untuk mengatur lalu lintas web. Mari kita pasang Nginx.

5. Langkah 3: Sentuhan Akhir Keamanan & Optimasi

Nginx bertindak sebagai Reverse Proxy yang tidak hanya melakukan load balancing, tapi juga menjaga agar header HTTP Upgrade diteruskan dengan benar ke backend Node.js kita.

Buat file konfigurasi Nginx baru, misal /etc/nginx/sites-available/realtime.conf:

map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

upstream websocket_cluster {
    # Daftar instance backend Node.js Anda (bisa ditambah secara horizontal)
    server 127.0.0.1:8080;
    # server 127.0.0.1:8081; # Tambahkan jika scale-out ke port lain
    
    keepalive 64;
}

server {
    listen 80;
    server_name realtime.domainanda.com;

    # Redirect HTTP ke HTTPS untuk keamanan produksi
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    server_name realtime.domainanda.com;

    # Konfigurasi SSL/TLS (Let's Encrypt)
    ssl_certificate /etc/letsencrypt/live/realtime.domainanda.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/realtime.domainanda.com/privkey.pem;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;

    # Penanganan khusus koneksi WebSocket
    location / {
        proxy_pass http://websocket_cluster;
        proxy_http_version 1.1;
        
        # Header penting untuk upgrade protokol HTTP ke WebSocket
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        
        # Timeout panjang agar koneksi persisten tidak terputus otomatis oleh Nginx
        proxy_read_timeout 3600s;
        proxy_send_timeout 3600s;
    }
}

Uji sintaks Nginx dan lakukan reload layanan:

sudo nginx -t
sudo systemctl reload nginx

[!WARNING] Jangan lupa memastikan firewall Anda (seperti UFW atau iptables) mengizinkan port 80 dan 443, sementara port internal Node.js (8080) ditutup dari akses publik luar dan hanya bisa diakses via localhost.

Sistem sudah berdiri tegak. Sekarang saatnya kita uji rasa di dapur produksi.

6. Tes Rasa: Memastikan Semuanya Berjalan Sempurna

Untuk membuktikan racikan kita berhasil, buat skrip uji klien sederhana menggunakan Node.js di mesin terpisah (atau terminal berbeda) untuk mensimulasikan koneksi masuk.

Buat file client-test.js:

const WebSocket = require('ws');

const CLIENTS_COUNT = 100; // Ubah sesuai kebutuhan uji coba lokal
let connected = 0;

for (let i = 0; i < CLIENTS_COUNT; i++) {
  const ws = new WebSocket('ws://localhost:8080');

  ws.on('open', () => {
    connected++;
    if (connected === CLIENTS_COUNT) {
      console.log(`Sukses! ${connected} klien berhasil terhubung secara simultan.`);
      // Kirim tes pesan broadcast
      ws.send('Halo dari pengujian sistem real-time!');
    }
  });

  ws.on('message', (data) => {
    console.log(`Pesan diterima klien: ${data}`);
    ws.close();
  });

  ws.on('error', (err) => {
    console.error('Koneksi klien gagal:', err.message);
  });
}

Jalankan skrip uji tersebut:

node client-test.js

Perhatikan respons di terminal server Anda. Jika log mencetak sapaan koneksi massal dan pesan terkirim balik tanpa tersendat, racikan Event-Driven Architecture Anda resmi matang dan siap disajikan ke publik.

7. Pertolongan Pertama: Jika Terjadi Kendala Kecil

Di lapangan, terkadang ada saja gangguan kecil yang muncul mendadak. Berikut pertolongan pertama pada kecelakaan infrastruktur real-time:

  • Error EMFILE: too many open files: Ini berarti batas file descriptor sistem operasi Anda belum terbaca sempurna. Pastikan Anda merestart sesi terminal atau layanan systemd Anda setelah mengubah /etc/security/limits.conf.
  • Koneksi terputus sendiri setiap 60 detik: Perangkat router, load balancer cloud (seperti AWS ALB), atau Nginx sering kali memiliki timeout diam (idle timeout). Tambahkan pengiriman pesan ping/pong berkala (heartbeat) dari sisi klien dan server setiap 30 detik untuk menjaga jalur pipa jaringan tetap aktif.
đŸˇī¸ Tags: #Nginx #Redis #Websocket #System Architecture #Node.js

Apakah panduan tutorial ini membantu Anda?

Masukan Anda sangat berharga untuk terus memperbarui dan menyempurnakan kualitas materi teknis kami.

🎉

Terima kasih banyak atas apresiasi Anda!

Tim kami terus menyempurnakan tutorial agar selalu akurat dengan versi teknologi terbaru.

Bantu Kami Menyempurnakan Materi Ini

⚡ Literally Tech Digest

Update Tutorial & Developer Tools Terbaru Langsung ke Email Anda

Dapatkan kurasi artikel arsitektur software, tips DevOps, panduan database, serta rilis fitur developer utility gratis setiap minggu. Bebas spam, bisa berhenti kapan saja.

âŗ Mencari artikel...
Tutorial & Artikel Terkait
Developer Tools
Tidak ditemukan tutorial atau tool dengan kata kunci "".
Ketik minimal 2 karakter untuk mencari artikel atau nama tools.
Tekan ESC untuk menutup Cari di Semua Artikel →