Skip to main content
System design langkah demi langkah · Pelajaran 1 dari 7 · 12 menit

Cara Menghitung Kebutuhan Server: Estimasi System Design

Cara menghitung kebutuhan server: dari user harian ke request per detik saat puncak, storage, dan jumlah server, plus latency lewat Little's law.

Oleh Matthews WongDitinjau pada

Poin utama

Estimasi system design adalah hitungan sederhana yang mengubah asumsi tertulis menjadi angka yang harus dipenuhi desain: user harian menjadi request per hari, request per detik rata-rata dan saat puncak, storage, bandwidth, dan jumlah server. Little's law, L = λW, lalu menghubungkan throughput dengan latency: berapa request yang sedang diproses bersamaan, dan seberapa cepat jumlah itu naik saat respons melambat.

Setelah pelajaran ini, Anda bisa

  • Mengubah jumlah user harian menjadi request per detik rata-rata dan saat puncak, dengan setiap asumsi ditulis di samping angkanya.
  • Mengestimasi storage, bandwidth, dan jumlah server, lalu menentukan mana yang paling menentukan desain.
  • Memakai Little's law untuk memperkirakan bagaimana respons yang melambat mengubah konkurensi yang dibutuhkan trafik yang sama.
Lihat cara kerjanya

Ikuti diagramnya langkah demi langkah

Tekan Putar, atau melangkah dengan panah. Setiap langkah juga ditulis di bawah diagram.

Dari user harian ke jumlah server: estimasi langkah demi langkah

User harian dikali request memberi request per hari; dibagi 86.400 memberi laju rata-rata, faktor puncak memberi laju desain, kapasitas satu server memberi jumlah server, byte per user memberi storage, dan Little's law memberi jumlah request yang sedang diproses.

Langkah 1 dari 7. Estimasi adalah sebuah rantai. Setiap kotak akan berisi satu angka dan setiap kabel satu asumsi tertulis, jadi mengubah satu asumsi mengubah semua kotak sesudahnya.

Tombol: ← → langkah · Home / End · K putar atau jeda

  1. Estimasi adalah sebuah rantai. Setiap kotak akan berisi satu angka dan setiap kabel satu asumsi tertulis, jadi mengubah satu asumsi mengubah semua kotak sesudahnya.

  2. Mulai dari asumsi yang Anda tulis: 1.000.000 user harian, masing-masing membuat 30 request. Kalikan, dan sistem melayani 30.000.000 request per hari.

  3. Satu hari punya 86.400 detik, jadi 30.000.000 request sehari rata-rata sekitar 350 request per detik. Untuk hitungan di kepala, bulatkan 86.400 menjadi 100.000.

    Tebak langkah berikutnya Server harus diukur untuk laju yang mana? (Rata-rata harian, 350 per detik · Laju di jam tersibuk)
  4. Trafik menumpuk di jam-jam sibuk. Kalikan dengan faktor puncak dari metrik Anda sendiri, di sini diasumsikan 3, lalu rancang untuk sekitar 1.040 request per detik.

  5. Bagi angka puncak dengan kemampuan aman satu server, diasumsikan 250 per detik: hasilnya 4,2, jadi 5 server. Tambahkan satu cadangan agar satu kegagalan tidak membuat kapasitas kurang.

  6. Byte dihitung dengan cara yang sama. Sekitar 2 KB per user per hari berarti 2 GB sehari, 730 GB setahun, dan sekitar 2,2 TB kalau Anda menyimpan 3 salinan.

    Tebak langkah berikutnya Latency naik dari 0,1 detik ke 0,5 detik, trafik sama. Request aktif? (Kurang lebih tetap · Naik sekitar lima kali · Turun menjadi seperlima)
  7. Little's law: request yang sedang diproses sama dengan laju kedatangan dikali waktu di dalam sistem. 1.040 per detik × 0,1 detik ≈ 104. Pada 0,5 detik, trafik yang sama menahan 520.

    L = λ × W

Apa yang diputuskan system design sebelum kotak-kotaknya digambar?

System design adalah proses memutuskan bagaimana bagian-bagian sistem, datanya, dan antarmukanya saling terhubung agar memenuhi requirements yang bisa dinyatakan dengan jelas. Satuan kerjanya adalah keputusan, dan setiap keputusan punya harga di tempat lain: cache mempercepat baca tetapi membuat data basi, queue mempercepat respons tetapi hasilnya baru tersedia belakangan.

Baca selengkapnya (2)

Karena itu pekerjaannya dimulai dari requirements dan angka, bukan dari komponen. Tuliskan apa yang harus dilakukan sistem, seberapa cepat, seberapa tersedia, dan seberapa benar. Lalu estimasi bebannya. Scaling bukan langkah tersendiri; ia muncul dari estimasi itu, dan kalau hasilnya muat di satu server, jumlah komponen baru yang tepat adalah nol.

Framework arsitektur mendaftar kualitas yang harus dipertanggungjawabkan sebuah desain. AWS Well-Architected Framework menyebut enam pilar: operational excellence, security, reliability, performance efficiency, cost optimization, dan sustainability. Menambah satu pilar, misalnya reliability lewat server cadangan, biasanya mengorbankan pilar lain, misalnya biaya. Karena itu trade-off-nya perlu ditulis di samping angka-angkanya.

Bagaimana mengubah jumlah user harian menjadi request per detik?

Kalikan jumlah user harian dengan jumlah request tiap user, lalu bagi dengan 86.400 detik dalam sehari. Satu juta user yang masing-masing membuat 30 request berarti 30.000.000 request sehari, atau sekitar 350 per detik. Untuk hitungan di kepala, bulatkan 86.400 menjadi 100.000: hasilnya sekitar 14 persen lebih rendah, dan itu masih wajar untuk tingkat ketelitian ini.

Baca selengkapnya (3)

Angka rata-rata itu bukan yang dipakai untuk menentukan ukuran, karena trafik menumpuk di jam sibuk. Kalikan dengan faktor puncak dari metrik Anda sendiri; dengan asumsi 3, desain harus sanggup menampung sekitar 1.040 request per detik. Sekalian pisahkan baca dan tulis: 150 baca untuk setiap tulis mengarah ke cache dan replica, sedangkan rasio mendekati 1 mengarah ke jalur tulis.

Lalu bagi angka puncak dengan kemampuan satu server. Angka per server inilah yang paling lemah di seluruh rantai, karena handler yang menjalankan satu query ber-index dan handler yang me-resize gambar bisa berbeda beberapa orde besaran. Tandai sebagai asumsi, ganti dengan hasil load test begitu memungkinkan, dan tambahkan satu cadangan agar satu kegagalan tidak membuat kapasitas kurang.

Tebakan saling mengalikan. Tiga input yang masing-masing meleset 2 kali membuat hasil akhirnya meleset 8 kali, jadi perlakukan hasilnya sebagai orde besaran dan simpan setiap asumsi di samping angkanya, supaya siapa pun bisa menunjuk asumsi yang keliru.

Bagaimana storage dan bandwidth mengubah desain?

Byte mengikuti rantai yang sama. Storage adalah jumlah record per hari, dikali byte per record, dikali lama penyimpanan dalam hari, dikali jumlah salinan yang disimpan. Dengan 2 KB per user per hari, satu juta user menulis 2 GB sehari dan 730 GB setahun, dan tiga salinan membuatnya sekitar 2,2 TB. Lupakan salinannya, maka storage Anda kurang tepat sebanyak jumlah salinan itu.

Baca selengkapnya (1)

Bandwidth adalah laju puncak dikali byte per respons. Sekitar 1.040 respons per detik masing-masing 100 KB berarti 104 megabyte per detik. Kapasitas link dihitung dalam bit, jadi kalikan 8: sekitar 830 megabit per detik, hampir sendirian menghabiskan port 1 Gbit/s. Kalau egress melampaui port, jawabannya CDN atau object storage dengan edge sendiri, bukan server aplikasi yang lebih besar, dan ke sanalah modul berikutnya berlanjut.

Apa beda latency dan throughput, dan bagaimana Little's law menghubungkan keduanya?

Latency adalah lama satu request selesai; throughput adalah jumlah request yang selesai per detik. Yang satu durasi, yang lain laju. Menambah server menaikkan throughput tetapi tidak menolong satu request yang lambat, sedangkan mengurangi pekerjaan dalam satu request menurunkan latency-nya tanpa menambah kapasitas. Laporkan latency sebagai persentil: p99 adalah nilai yang dikalahkan 99 persen request, jadi ekor yang lambat tidak bisa bersembunyi di balik rata-rata yang tampak sehat.

Baca selengkapnya (2)

Little's law mengikat keduanya: rata-rata jumlah request di dalam sistem sama dengan laju kedatangan dikali rata-rata waktu yang dihabiskan tiap request di sana, L = λW, apa pun pola kedatangannya. Pada 1.040 request per detik dan 0,1 detik per request, sekitar 104 request sedang diproses. Kalau query yang lambat mendorong latency ke 0,5 detik, trafik yang sama menahan sekitar 520 request sekaligus, lima kali lipat konkurensinya. Begitulah connection pool dan batas worker bisa habis tanpa trafik bertambah sedikit pun.

Utilisasi memberi peringatan terakhir. Pada model antrean paling sederhana, satu worker dengan kedatangan acak, waktu di dalam sistem adalah 1 / (μ − λ), dengan μ laju layanan dan λ laju kedatangan. Saat λ mendekati μ, waktu tunggu membesar tanpa batas: pada utilisasi 90 persen sebuah request menghabiskan 10 kali waktu layanannya di dalam sistem, pada 95 persen 20 kali. Rencanakan beban harian jauh di bawah titik belok itu. Paper Tail at Scale dari Google menambahkan bahwa lonjakan latency sesaat, yang tidak penting di sistem berukuran sedang, bisa mendominasi sistem yang besar.

Cara situs ini melakukannya

Konfigurasi nyata di balik pelajaran ini

Kutipan dari repositori yang membangun dan men-deploy situs ini, apa adanya.

lib/api/versioning.ts:39-44
/** Requests per minute per client IP, enforced by each route. */
export const API_RATE_LIMITS = {
  chat: 20,
  followups: 30,
  contact: 5,
} as const satisfies Record<keyof typeof API_PATHS, number>;

Situs ini menuliskan batas throughput-nya sebagai angka lengkap dengan satuannya: request per menit, per IP klien. Mengonversinya sama dengan menjalankan estimasi secara terbalik: 20 request chat per menit berarti satu request setiap 3 detik per pengunjung, dan mengalikannya dengan jumlah pengunjung yang Anda perkirakan memberi batas atas beban yang bisa diterima route chat. Komentarnya membawa satuan, dan batas tanpa satuan tidak bisa dibandingkan dengan apa pun.

docker-compose.yml:27-28
    mem_limit: 512m
    cpus: "1.0"

Kotak server dalam rantai milik situs ini sendiri: seluruh web tier adalah satu container yang dibatasi satu CPU dan memori 512 MB. Repo ini tidak menyimpan estimasi trafik, jadi batas itu adalah kapasitas hasil keputusan, bukan hasil hitungan. Estimasilah yang akan memberi tahu kapan batas itu tidak lagi cukup, dan Little's law memberi tanda awalnya: kalau latency naik dua kali lipat pada trafik yang sama, jumlah request di dalam satu CPU itu juga dua kali lipat.

Yang sering rusak

Kesalahan yang benar-benar membuang waktu

  • Menentukan ukuran dari rata-rata harian

    Server yang diukur untuk 350 request per detik akan tumbang saat puncak 1.040 per detik, justru di saat yang paling penting. Ukurlah untuk puncak, dengan faktor yang diambil dari jam tersibuk Anda, dan siapkan cadangan untuk node yang mati.

  • Mencampur bit dan byte

    Ukuran data dihitung dalam byte, sedangkan link dalam bit. Lupakan faktor 8, maka egress 830 Mbit/s terlihat seperti 104, seolah muat di port yang sebenarnya hampir penuh. Tulis satuan di samping setiap angka.

  • Berjalan mendekati utilisasi penuh

    Waktu tunggu membesar tanpa batas saat utilisasi mendekati 100 persen. Pada model antrean sederhana, worker yang sibuk 95 persen menahan setiap request sekitar 20 kali waktu layanannya. Ruang cadangan bukan pemborosan; justru itulah yang menjaga tail latency tetap terkendali.

  • Memperlakukan estimasi sebagai spesifikasi

    Estimasi menentukan kelas desain: satu server atau armada server, database atau object storage. Membekukan tebakannya menjadi kontrak membuat angka yang salah terus hidup. Begitu ada trafik nyata, ganti setiap asumsi yang ditandai dengan hasil pengukuran, dimulai dari faktor puncak dan kemampuan per server.

Latency atau throughput: apa yang diukur masing-masing
Pertanyaan yang dijawabBerapa lama satu request selesai?Berapa request yang selesai tiap detik?
SatuanMilidetik per requestRequest per detik
Cara melaporkannyaPersentil: p50, p95, p99Laju rata-rata dan puncak yang sanggup ditahan
Cara memperbaikinyaMengurangi pekerjaan per request, lebih sedikit hop, cachingLebih banyak salinan, pooling, batching
Coba sendiri

Lakukan di komputer Anda sendiri

Anda hanya butuh Node 18 atau lebih baru. Tulis estimasinya sebagai kode supaya setiap asumsi terlihat, lalu ukur Little's law pada server yang Anda jalankan sendiri.

  1. Simpan estimasinya sebagai estimate.mjs lalu jalankan node estimate.mjs. Hasilnya sama dengan angka di diagram: rata-rata 347, puncak 1.042, 6 server, 2,19 TB setahun, dan egress 833 Mbit/s.

    // estimate.mjs: every input is an assumption; change one and run it again
    const a = {
      dailyUsers: 1_000_000,
      requestsPerUser: 30,
      peakFactor: 3,
      perServer: 250, // requests per second one server handles safely
      bytesPerUserPerDay: 2_000, // about 2 KB saved per user per day
      copies: 3,
      responseBytes: 100_000, // about 100 KB per response
    };
    const perDay = a.dailyUsers * a.requestsPerUser;
    const average = perDay / 86_400;
    const peak = average * a.peakFactor;
    const servers = Math.ceil(peak / a.perServer) + 1; // plus one spare
    const storageTB = (a.dailyUsers * a.bytesPerUserPerDay * 365 * a.copies) / 1e12;
    const egressMbit = (peak * a.responseBytes * 8) / 1e6;
    console.table({
      perDay,
      averagePerSecond: Math.round(average),
      peakPerSecond: Math.round(peak),
      servers,
      storageTBPerYear: Number(storageTB.toFixed(2)),
      egressMbitPerSecond: Math.round(egressMbit),
    });
  2. Ubah satu asumsi, peakFactor dari 3 menjadi 5, lalu jalankan lagi. Angka puncak, server, dan egress ikut berubah; storage tidak, karena memang tidak pernah bergantung pada puncak.

    node estimate.mjs
  3. Simpan server yang setiap responsnya memakan waktu tetap, lalu jalankan dengan delay 100 ms.

    // server.mjs: every response takes DELAY_MS milliseconds
    import http from "node:http";
    const delay = Number(process.env.DELAY_MS ?? 100);
    http
      .createServer((req, res) => setTimeout(() => res.end("ok\n"), delay))
      .listen(8080);
    
    // then, in a terminal:
    // DELAY_MS=100 node server.mjs
  4. Di terminal kedua, kirim 50 request per detik selama 10 detik dan hitung rata-rata request yang sedang diproses. Hasilnya sekitar 5, yaitu 50 × 0,1. Jalankan ulang server dengan DELAY_MS=500 lalu ulangi: hasilnya mendekati 25, lima kali lipat untuk trafik yang sama.

    // load.mjs: RATE requests per second for 10 seconds; average requests in flight
    const rate = Number(process.env.RATE ?? 50);
    let inFlight = 0;
    const samples = [];
    const sender = setInterval(() => {
      inFlight += 1;
      fetch("http://localhost:8080/")
        .then((res) => res.text())
        .finally(() => (inFlight -= 1));
    }, 1000 / rate);
    const sampler = setInterval(() => samples.push(inFlight), 50);
    setTimeout(() => {
      clearInterval(sender);
      clearInterval(sampler);
      const average = samples.reduce((a, b) => a + b, 0) / samples.length;
      console.log(`${rate} req/s -> ${average.toFixed(1)} in flight on average`);
    }, 10_000);
    
    // then: RATE=50 node load.mjs
Kuis singkat

Tiga pertanyaan sebelum lanjut

Pilih jawaban untuk melihat kenapa benar atau salah. Tidak ada yang disimpan atau dinilai, jadi tebak saja dengan bebas.

  1. 1.Aplikasi Anda memperkirakan 2.000.000 user harian yang masing-masing membuat 10 request, dengan puncak 3 kali rata-rata. Kira-kira laju berapa yang dipakai untuk menentukan ukuran?
  2. 2.Sebuah API melayani 400 request per detik dengan latency 20 ms. Sebuah query lambat menaikkan latency menjadi 100 ms pada trafik yang sama. Apa yang terjadi pada jumlah request yang sedang diproses?
  3. 3.Estimasi Anda menghasilkan egress puncak 2.400 Mbit/s, sementara server punya port 1 Gbit/s. Apa artinya?
Pikirkan dulu

Jawab dalam hati, lalu cek

  1. 1.Kenapa kemampuan per server menjadi angka paling lemah dalam estimasi?Lihat jawabannya

    Jawaban:Karena handler bisa berbeda beberapa orde besaran: satu query ber-index dibandingkan resize gambar. Tandai sebagai asumsi dan ganti dengan hasil load test.

  2. 2.Latency naik dua kali lipat padahal trafik tidak berubah. Kenapa aplikasi bisa kehabisan koneksi database?Lihat jawabannya

    Jawaban:Little's law: request yang sedang diproses sama dengan laju kedatangan dikali latency, jadi latency dua kali lipat membuat request yang memegang koneksi pada saat yang sama juga dua kali lipat.

  3. 3.Kenapa latency dilaporkan sebagai p99, bukan rata-rata?Lihat jawabannya

    Jawaban:Rata-rata menyembunyikan ekor yang lambat. Satu dari seratus request yang butuh beberapa detik hampir tidak menggeser rata-rata, sedangkan p99 langsung menunjukkannya.

Baca modulnya

Semua artikel di modul ini, berurutan

Pelajaran di atas adalah petanya. Setiap artikel membahas satu bagiannya secara mendalam, lengkap dengan contoh.