Load Balancer

L4 versus L7, algoritma pembagian beban, dan health check sebagai gerbang trafik.

Daftar isi

Load balancer adalah komponen yang menerima permintaan (request) dari klien dan membagikannya ke sekumpulan server di belakangnya. Topik ini membahas dua jenis load balancer menurut lapisan kerjanya, beberapa algoritma pembagian beban beserta simulasi perbandingannya dalam Python, dan health check sebagai gerbang yang menentukan server mana yang boleh menerima trafik. Setelah membacanya, pemilihan jenis load balancer dan algoritmanya dapat disertai alasan yang terukur.

Peran load balancer dalam arsitektur#

Klien hanya perlu mengenal satu alamat, sedangkan kumpulan server di belakangnya dapat tumbuh, menyusut, dan mengalami kerusakan tanpa klien mengetahuinya. Pemisahan inilah peran utama load balancer: trafik masuk melalui satu pintu, lalu pintu itu mengarahkan setiap permintaan ke salah satu anggota kumpulan. Server yang mati cukup dilewati, server baru cukup diperkenalkan, dan tidak ada klien yang perlu mengubah konfigurasinya.

Pembagian lewat DNS saja tidak memadai sebagai satu-satunya mekanisme. Jawaban DNS dapat tersimpan lama di klien maupun di resolver antara, sehingga perubahan daftar alamat tidak segera terasa. DNS juga tidak mengetahui beban maupun kesehatan tiap server, sehingga alamat server yang mati tetap terbagikan sampai catatannya diperbarui. Load balancer menjawab kedua kekurangan itu karena keputusannya diambil setiap permintaan dengan melihat keadaan server saat itu.

klienLoad balancerpintu masuk tunggalServer AServer BServer Cpermintaansatu serverper permintaan
Posisi load balancer sebagai pintu masuk tunggal bagi kumpulan server yang setara

L4 versus L7#

Load balancer bekerja pada lapisan yang berbeda-beda, dan dua tingkatan yang paling sering dibahas adalah L4 dan L7.

Load balancer L4 mengambil keputusan hanya dari alamat IP dan port tanpa membaca isi permintaan, sehingga prosesnya cepat dan murah, tetapi routing berbasis isi tidak mungkin dilakukan. Koneksi TLS dapat dialirkan apa adanya karena isi terenkripsi tidak perlu dibuka. Load balancer L7 membaca permintaan HTTP secara utuh, sehingga keputusan dapat berdasarkan jalur URL, header, maupun cookie, dan TLS dapat diterminasi di load balancer agar server tidak perlu mengurus sertifikat. Kemampuan tambahan itu dibayar dengan kerja pemrosesan yang lebih berat pada setiap permintaan.

AspekL4L7
Lapisan kerjatransport, TCP dan UDPaplikasi, HTTP
Dasar keputusanalamat IP dan portjalur URL, header, cookie
Akses isi permintaantidak adamembaca isi HTTP
Koneksi TLSdialirkan apa adanyadapat diterminasi di load balancer
Contoh pemakaiantrafik TCP non-HTTP dengan throughput tinggiaplikasi web dan API

Algoritma pembagian beban#

Algoritma menentukan server mana yang menerima permintaan berikutnya. Round robin memutar pilihan secara bergilir sehingga jumlah permintaan tiap server sama, tetapi ia tidak melihat beban yang sedang berjalan. Least connections memilih server dengan koneksi aktif paling sedikit, sehingga server yang sedang menangani pekerjaan panjang dihindari. Selain keduanya terdapat weighted round robin yang memberi server besar porsi lebih banyak, serta pemetaan berbasis hash yang menempatkan klien yang sama pada server yang sama secara konsisten.

Simulasi berikut membandingkan round robin dan least connections pada sembilan permintaan yang datang berurutan, dengan dua permintaan berdurasi panjang dan tujuh berdurasi pendek. Setiap permintaan menahan satu koneksi selama durasinya, dan perbandingan dilihat dari jumlah permintaan, total durasi, serta puncak koneksi serentak per server.

python simulasi-load-balancer.py
# Simulasi algoritma round robin dan least connections.
# Sembilan permintaan datang berurutan: permintaan i datang pada detik i
# dan menahan satu koneksi selama durasinya (dalam detik).

SERVER = ["A", "B", "C"]
DURASI = [6, 1, 6, 1, 1, 1, 1, 1, 1]  # durasi koneksi tiap permintaan


def round_robin():
    return [SERVER[i % len(SERVER)] for i in range(len(DURASI))]


def least_connections():
    penugasan = []
    for i in range(len(DURASI)):
        aktif = {s: 0 for s in SERVER}
        for j in range(i):
            if j + DURASI[j] > i:  # koneksi dari permintaan j belum selesai
                aktif[penugasan[j]] += 1
        # pilih server dengan koneksi aktif paling sedikit; bila seri, urutan alfabet
        penugasan.append(min(SERVER, key=lambda s: (aktif[s], s)))
    return penugasan


def puncak_serentak(penugasan, server):
    """Jumlah koneksi serentak terbanyak yang pernah ditangani satu server."""
    batas = sum(DURASI)
    return max(
        sum(1 for j in range(len(DURASI))
            if penugasan[j] == server and j <= t < j + DURASI[j])
        for t in range(batas)
    )


def ringkas(nama, penugasan):
    print(nama)
    for i, durasi in enumerate(DURASI):
        print(f"  permintaan {i + 1} (t={i}, durasi {durasi}) -> server {penugasan[i]}")
    jumlah = {s: penugasan.count(s) for s in SERVER}
    beban = {s: sum(DURASI[i] for i in range(len(DURASI)) if penugasan[i] == s)
             for s in SERVER}
    teks_jumlah = ", ".join(f"{s}={jumlah[s]}" for s in SERVER)
    teks_beban = ", ".join(f"{s}={beban[s]}" for s in SERVER)
    teks_puncak = ", ".join(f"{s}={puncak_serentak(penugasan, s)}" for s in SERVER)
    print(f"  jumlah permintaan       : {teks_jumlah}")
    print(f"  total durasi per server : {teks_beban}")
    print(f"  puncak koneksi serentak : {teks_puncak}")


ringkas("ALGORITMA ROUND ROBIN", round_robin())
print()
ringkas("ALGORITMA LEAST CONNECTIONS", least_connections())
text Keluaran
ALGORITMA ROUND ROBIN
  permintaan 1 (t=0, durasi 6) -> server A
  permintaan 2 (t=1, durasi 1) -> server B
  permintaan 3 (t=2, durasi 6) -> server C
  permintaan 4 (t=3, durasi 1) -> server A
  permintaan 5 (t=4, durasi 1) -> server B
  permintaan 6 (t=5, durasi 1) -> server C
  permintaan 7 (t=6, durasi 1) -> server A
  permintaan 8 (t=7, durasi 1) -> server B
  permintaan 9 (t=8, durasi 1) -> server C
  jumlah permintaan       : A=3, B=3, C=3
  total durasi per server : A=8, B=3, C=8
  puncak koneksi serentak : A=2, B=1, C=2

ALGORITMA LEAST CONNECTIONS
  permintaan 1 (t=0, durasi 6) -> server A
  permintaan 2 (t=1, durasi 1) -> server B
  permintaan 3 (t=2, durasi 6) -> server B
  permintaan 4 (t=3, durasi 1) -> server C
  permintaan 5 (t=4, durasi 1) -> server C
  permintaan 6 (t=5, durasi 1) -> server C
  permintaan 7 (t=6, durasi 1) -> server A
  permintaan 8 (t=7, durasi 1) -> server A
  permintaan 9 (t=8, durasi 1) -> server A
  jumlah permintaan       : A=4, B=2, C=3
  total durasi per server : A=9, B=7, C=3
  puncak koneksi serentak : A=1, B=1, C=1

Keluarannya menunjukkan dua keputusan yang berbeda meskipun datanya sama. Round robin membagi jumlah permintaan sama rata, tiga untuk setiap server, tetapi total durasinya timpang, yaitu 8, 3, dan 8, dan dua server pernah menangani dua koneksi serentak karena permintaan pendek datang ketika permintaan panjang masih berjalan. Least connections menghindari server yang sedang menangani koneksi panjang, sehingga puncak serentak hanya satu di setiap server dan total durasi lebih merata. Jumlah permintaannya justru tidak sama rata, yaitu 4, 2, dan 3, karena algoritma ini tidak mengejar hitungan, melainkan beban yang sedang berjalan.

Health check sebagai gerbang trafik#

Load balancer tidak mengirimkan trafik ke server yang sedang tidak sehat, dan keputusan itu diambil melalui health check, yaitu pemeriksaan berkala atas kesehatan tiap server. Pada pemeriksaan aktif, load balancer mengirimkan probe, yaitu permintaan pemeriksaan kecil, secara berkala, misalnya membuka koneksi TCP atau mengirimkan permintaan HTTP ke jalur khusus. Probe yang tidak menjawab dalam batas waktu (timeout) dianggap gagal, dan setelah sejumlah kegagalan berturut-turut, server ditandai tidak sehat serta dilewati sampai pemeriksaannya kembali berhasil.

Pemeriksaan pasif bekerja tanpa probe tersendiri. Kegagalan yang teramati pada trafik nyata, misalnya koneksi yang ditolak atau respons 5xx, dihitung menuju ambang yang sama, sehingga server yang bermasalah cepat tersingkir tanpa menunggu siklus probe. Apa pun jenisnya, gerbang ini memastikan permintaan hanya tiba di server yang mampu mengerjakannya, dan kegagalan satu server tidak terasa oleh pengguna selama anggota kumpulan lainnya masih hidup.

Kesalahan umum#

  1. Health check yang terlalu dangkal. Penyebabnya, probe hanya menguji koneksi TCP, sedangkan aplikasi sebenarnya sudah mengembalikan error, sehingga server sakit tetap menerima trafik. Perbaikannya, gunakan probe yang menyentuh jalur aplikasi yang nyata tetapi ringan, misalnya satu endpoint yang memeriksa keterhubungan ke basis data.
  2. Load balancer tunggal tanpa cadangan. Penyebabnya, komponen yang menyatukan seluruh trafik menjadi satu titik kegagalan baru yang lebih berbahaya daripada server yang dibaginya. Perbaikannya, jalankan dua load balancer dalam susunan aktif-pasif sehingga kegagalan salah satunya tertangani secara otomatis.
  3. Mengandalkan sticky session sebagai pengganti penataan state. Penyebabnya, kebutuhan menyimpan session di memori server berubah menjadi masalah routing, dan session pengguna hilang ketika servernya mati. Perbaikannya, simpan session di penyimpanan terpusat sehingga setiap server mampu melayani session mana pun.

Ringkasan#

  • Load balancer memberi klien satu pintu masuk sementara kumpulan server di belakangnya bebas tumbuh, menyusut, dan pulih dari kerusakan.
  • L4 mengambil keputusan dari alamat IP dan port tanpa membaca isi, sedangkan L7 membaca permintaan HTTP sehingga routing berbasis isi dan terminasi TLS dimungkinkan.
  • Round robin membagi hitungan permintaan sama rata, least connections membagi beban aktif, dan pilihan di antara keduanya mengikuti variasi durasi permintaan.
  • Health check memeriksa kesehatan tiap server secara aktif maupun pasif dan menahan trafik dari server yang gagal pemeriksaan.

Referensi#