UTS AAT (IF4031 Arsitektur Aplikasi Terdistribusi)
Bahan belajar UTS yang disusun dari catatan 01 sampai 08. Ini studi sheet, bukan pengganti catatan asli: tiap bagian me-link ke note sumbernya untuk detail dan flashcard aslinya. Istilah singkat ada di Glosarium_AAT.
Cara pakai: baca Prasyarat dulu (istilah yang tidak dijelaskan di materi mana pun), lalu Materi inti dari atas ke bawah. Urutannya disusun menurut ketergantungan konsep, jadi sebuah konsep selalu dijelaskan sebelum dipakai. Konsep yang sudah dijelaskan tidak diulang, hanya dirujuk (“lihat 2.x”).
0. Cakupan dan Peta CPMK
Cakupan: note 01 sampai 08. Note 09 dan seterusnya belum masuk (akan ditambah di putaran berikutnya).
CPMK resmi dari slide pengantar kuliah (IF4031, 6 butir). Catatan: MOC _AAT menyebut bahwa 5 capaian di MOC disusun dari cakupan topik, bukan CPMK resmi. Peta di bawah memakai CPMK resmi.
| CPMK resmi (siswa mampu) | Bagian di file ini | Status |
|---|---|---|
| 1. Menentukan kriteria penting dalam membuat arsitektur sistem | 2.1 (lima aspek, scalability, resiliency, operations), 2.3 (stateless/stateful), 2.9 (trade-off monolith vs microservices) | Tercakup |
| 2. Kemampuan penyelesaian masalah (analisis, perancangan, implementasi) pada aplikasi terdistribusi | 2.3 (studi kasus chess.com), 2.4, 2.5 sampai 2.12 | Tercakup sebagian (konsep dan trade-off; implementasi ada di tugas) |
| 3. Memahami berbagai pattern umum pada aplikasi terdistribusi | 2.11 (messaging), 2.12 (pattern microservices), 2.10 | Tercakup |
| 4. Menerapkan konsep sistem terdistribusi untuk membuat model, merancang, dan mengimplementasikan sistem | 2.5 sampai 2.8 (server, async, API, RPC) | Tercakup sebagian |
| 5. Dekomposisi sistem kompleks menjadi komponen | 2.9, 2.12 (decomposition patterns) | Tercakup |
| 6. Mengevaluasi dan memvalidasi implementasi dengan simulasi/analisis | Hanya perhitungan kapasitas (2.1) dan benchmark (2.8) | Belum tercakup oleh note 01-08 |
1. Prasyarat: Istilah yang Harus Dipahami Dulu
Semua istilah di bagian ini tidak dijelaskan di note AAT mana pun (sudah dicek dengan pencarian di note AAT 01-18 dan folder Glosarium-Teknis; slide PDF mentah di _Materi/AAT/ belum diperiksa karena teksnya tidak bisa dicari langsung, jadi masih ada kemungkinan sebagian istilah dijelaskan di slide). Penjelasannya di bawah adalah tambahan di luar materi kuliah, ditulis singkat sebagai bekal. Kalau istilah sudah dijelaskan di materi (misalnya container, sharding, ACID, idempotent, stateless), tidak ada di sini, cukup lihat Glosarium_AAT.
1.1 Jaringan
| Istilah | Penjelasan |
|---|---|
| IP address dan port | IP address adalah alamat sebuah mesin di jaringan. Port adalah nomor “pintu” di mesin itu, supaya satu mesin bisa menjalankan banyak layanan (HTTP biasanya port 80, HTTPS 443). |
| TCP vs UDP | TCP membuat koneksi dulu, menjamin data sampai utuh dan berurutan, dengan overhead lebih besar. UDP langsung mengirim tanpa membuat koneksi dan tanpa jaminan sampai, tetapi lebih ringan. |
| Socket | Titik ujung komunikasi di program untuk mengirim dan menerima data lewat jaringan (misalnya lewat TCP). Operasi dasarnya accept, recv, send. |
| Bandwidth | Kapasitas maksimum sebuah jalur jaringan, diukur dalam bit per detik (misalnya 1 Gbps). Beda dari throughput, yaitu jumlah yang benar-benar berhasil diproses per satuan waktu. |
| Router dan hop | Router meneruskan paket antar jaringan. Satu hop adalah satu lompatan dari router ke router berikutnya. |
| ISP dan Autonomous System (AS) | ISP adalah penyedia akses Internet. Autonomous System adalah satu kumpulan jaringan di bawah satu pengelola yang punya kebijakan rutenya sendiri (misalnya Google). |
| BGP (Border Gateway Protocol) | Protokol yang dipakai antar Autonomous System untuk saling memberi tahu jaringan mana yang bisa dicapai lewat mana. Router memilih jalur berdasarkan informasi ini. |
| HTTP request/response | Pesan HTTP terdiri dari baris awal (method + path, atau status code), header (metadata berpasangan nama:nilai), lalu body (isi). |
| Wire protocol / on-the-wire | Format byte persisnya saat data dikirim di jaringan, bukan sekadar API di tingkat kode. |
| Parsing | Membaca teks atau byte mentah lalu menguraikannya jadi struktur yang bisa diproses program. |
1.2 Keamanan
| Istilah | Penjelasan |
|---|---|
| Enkripsi, TLS, HTTPS, sertifikat | Enkripsi mengacak data supaya hanya pihak berkunci yang bisa membacanya. TLS adalah protokol yang mengenkripsi koneksi. HTTPS adalah HTTP di atas TLS. Sertifikat membuktikan identitas server. |
| mTLS | TLS dua arah: server dan client sama-sama memverifikasi sertifikat lawannya. |
| Hash, HMAC, tanda tangan (signature) | Hash mengubah data jadi sidik jari tetap yang tidak bisa dibalik. HMAC adalah hash yang memakai kunci rahasia, jadi hanya pemilik kunci yang bisa membuatnya. Signature dipakai untuk membuktikan data tidak diubah dan berasal dari sumber yang sah. |
| Base64 | Cara menulis data biner sebagai teks (huruf, angka, beberapa simbol) supaya aman dikirim lewat format teks seperti header HTTP. |
| XSS dan CSRF | XSS (Cross-Site Scripting): penyerang menyisipkan JavaScript ke halaman yang dibuka korban. CSRF (Cross-Site Request Forgery): penyerang membuat browser korban mengirim request ke situs lain tanpa sepengetahuan korban, memanfaatkan cookie yang sudah login. |
| OWASP Top 10, AAA | OWASP Top 10: daftar 10 risiko keamanan aplikasi web paling umum. AAA: Authentication (siapa kamu), Authorization (boleh apa), Accounting (pencatatan aktivitas). |
1.3 Sistem operasi dan konkurensi
| Istilah | Penjelasan |
|---|---|
| Process vs thread | Process adalah program yang berjalan dengan ruang memorinya sendiri. Thread adalah alur eksekusi di dalam process, berbagi memori dengan thread lain di process yang sama. |
| Kernel space vs user space, system call | Kernel adalah inti sistem operasi yang mengatur hardware. Program biasa berjalan di user space dan meminta layanan kernel lewat system call (contoh recvfrom). Data sering harus disalin dari kernel space ke user space. |
| Context switch | CPU berhenti menjalankan satu process/thread lalu pindah ke yang lain; keadaan yang lama disimpan dan yang baru dimuat. Ada biayanya, jadi jumlah thread yang sangat banyak memperlambat. |
| Stack memory | Area memori milik tiap thread untuk variabel lokal dan alur pemanggilan fungsi. Tiap thread butuh stack sendiri, sehingga banyak thread memakan banyak memori. |
| Race condition | Hasil program bergantung pada urutan eksekusi thread yang tidak bisa diprediksi karena beberapa thread mengakses data yang sama secara bersamaan. |
| Lock dan lock contention | Lock mencegah dua thread mengubah data yang sama bersamaan. Lock contention terjadi ketika banyak thread berebut lock yang sama sehingga banyak yang menunggu. |
| Callback | Fungsi yang diserahkan ke pihak lain untuk dipanggil nanti ketika suatu kejadian terjadi. |
| Garbage collector (GC) dan stop-the-world | GC membersihkan memori yang tidak terpakai secara otomatis. Pada GC “stop-the-world”, program berhenti sebentar selama pembersihan, sehingga latency bisa melonjak. |
| Goroutine | Thread ringan milik bahasa Go yang dikelola oleh runtime Go, bukan langsung oleh OS. |
| JNDI (Java) | Java Naming and Directory Interface: cara program Java mencari objek yang terdaftar dengan sebuah nama (misalnya connection factory) tanpa tahu lokasi aslinya. |
1.4 Sistem dan data
| Istilah | Penjelasan |
|---|---|
| Node, cluster, replica | Node adalah satu mesin atau instance dalam sistem. Cluster adalah sekumpulan node yang bekerja bersama. Replica adalah salinan dari sebuah komponen atau data. |
| Single point of failure (SPOF) | Satu komponen yang kalau gagal membuat seluruh sistem berhenti. |
| Throttling | Sengaja membatasi atau memperlambat laju request supaya sistem tidak kelebihan beban. |
| Foreign key dan normalisasi | Foreign key adalah kolom yang merujuk kunci tabel lain. Normalisasi memecah tabel supaya data tidak tersimpan berulang. Penjelasan lengkapnya di materi Basisdata/PDL (lihat 14_Relational_Data_Model). |
| Transaksi terdistribusi dan two-phase commit (2PC) | Transaksi yang mencakup beberapa database atau service. 2PC adalah protokol klasik agar semua peserta sepakat commit atau semuanya batal; mahal dan lambat, itu sebabnya Saga dibahas di 2.12. |
| IoT (Internet of Things) | Perangkat fisik kecil (sensor, alat rumah, dsb) yang terhubung ke jaringan dan mengirim data. |
2. Materi Inti (Urut Menurut Ketergantungan Konsep)
2.1 Fondasi Aplikasi Terdistribusi
Sumber: 01_Pengantar_Arsitektur_Aplikasi_Terdistribusi
Aplikasi terdistribusi terdiri dari banyak proses pada satu atau lebih node, berkomunikasi lewat infrastruktur (Socket/TCP/UDP, HTTP, WebSocket), berjalan di lingkungan heterogen (mobile, Linux, Windows, Internet, LAN), dan bisa memakai bahasa berbeda. Heterogenitas ini yang membuat dibutuhkan format data dan mekanisme komunikasi yang disepakati bersama (lihat 2.7).
Keterbatasan sumber daya per node: CPU (instruksi per waktu), memory, storage (SSD sekitar 3.000-100.000 IOPS, yaitu operasi I/O per detik), dan network. Contoh perhitungan: bila 1 request = 1 KB, bandwidth 1 Gbps secara teori hanya sanggup 1.000.000/8 = 125.000 request/detik, dan angka riil jauh lebih kecil karena overhead protokol dan software.
Beban melebihi kapasitas menyebabkan antrian (I/O jika volume request > kapasitas I/O; antrian pemrosesan jika request konkuren > jumlah worker/thread). Antrian menaikkan latency dan menurunkan throughput. Inilah alasan mendasar arsitektur terdistribusi (load balancing, scaling) penting: mengelola antrian dan keterbatasan secara sistematis, bukan sekadar menambah server.
Lima aspek desain:
| Aspek | Fokus |
|---|---|
| Komunikasi | Mekanisme pengiriman data antar node |
| Koordinasi | Siapa melakukan apa, dan bagaimana jika node gagal |
| Skalabilitas | Efisiensi menangani beban: throughput dan latency/response time |
| Resiliensi | Tetap beroperasi meski terjadi kegagalan |
| Operations | Pengelolaan dari development, testing, deployment, hingga maintain |
Komunikasi. Masalahnya: reliability (jaringan putus, paket hilang, sender/receiver crash), keamanan (data dibaca pihak lain saat transit), dan isu Internet seperti DNS stale (cache DNS lama belum ter-update) dan DNS update propagation time. Abstraksi yang membantu: TCP (reliable communication, data tidak hilang dan berurutan), HTTP/HTTPS (pola request/reply), gRPC (pemanggilan prosedur remote seolah fungsi lokal).
The Law of Leaky Abstractions (Joel Spolsky): “All non-trivial abstractions, to some degree, are leaky.” Setiap abstraksi (TCP, gRPC, NFS, Object Storage, query database) selalu punya peluang tidak menjamin semua yang seharusnya disediakan. Contoh: koneksi TCP bisa terputus atau HTTP request gagal meski sender/receiver tidak crash, atau delay berlebihan. Implikasi: developer tidak boleh hanya mengandalkan abstraksi, harus memahami stack protocol di baliknya.
Koordinasi dan FLP Impossibility. Koordinasi punya masalah reliability bila terjadi kegagalan di tengah proses. FLP Impossibility: consensus tidak bisa diimplementasikan secara pasti (deterministik) pada sistem asynchronous jika ada kemungkinan satu proses saja gagal. Ini dasar teoritis mengapa algoritma consensus (Paxos, Raft) sulit dan selalu berisi trade-off. Kegagalan harus ditangani khusus, terutama yang menyangkut state sistem (integritas data bisa rusak jika operasi gagal di tengah).
Skalabilitas. Kinerja menunjukkan seberapa efisien sistem menangani beban (load). Beban diukur dari jumlah user/request konkuren, jumlah request per satuan waktu (throughput), dan rasio update/write terhadap read. Dua pendekatan: scale up (hardware lebih kuat) dan scale out (menambah jumlah mesin/instance).
Resiliensi. Sistem resilient tetap berfungsi saat ada kegagalan, biasanya lewat redundancy. Cascading failure: kegagalan satu komponen menjalar ke komponen lain; solusinya fault isolation. Contoh pada slide: dua replica database (A dan B) masing-masing 50 tps di belakang load balancer; bila B gagal, seluruh 100 tps beralih ke A yang mungkin tidak didesain untuk dua kali beban sehingga A ikut gagal.

Kutipan Jeff Dean (Google): “Things will crash. Deal with it!” Data “The Joys of Real Hardware” untuk tahun pertama sebuah cluster baru: ~0,5 overheating, ~1 PDU failure (~500-1000 mesin hilang, ~6 jam pulih), ~1 rack-move, ~1 network rewiring, ~20 rack failure (40-80 mesin hilang), ~5 rack “wonky” (50% packet loss), ~8 network maintenance, ~12 router reload, ~3 router failure, puluhan blip DNS, ~1000 kegagalan mesin individual, dan ribuan kegagalan hard drive. Poin: pada skala besar kegagalan adalah hal rutin, jadi sistem harus didesain mengasumsikan kegagalan sejak awal.
Common failures: process crash (hardware failure atau unhandled exception), network delay (menyulitkan menentukan timeout: terlalu pendek risiko false positive, terlalu panjang memperlambat deteksi), unsynchronized clock (error pada ordering atau validasi timestamp), DNS problems, cache problems.
Operations dan maintainability. Biaya terbesar muncul setelah pengembangan awal (bug fixing, fitur baru, penyesuaian flow, operasi). Dibutuhkan testing berlapis (unit, integration, end-to-end), DevOps, serta system monitoring dan observability.
2.2 Anatomi Sistem dan Infrastruktur Komunikasi
Sumber: 01_Pengantar_Arsitektur_Aplikasi_Terdistribusi
Tiga sudut pandang sistem terdistribusi: (1) fisik: sekumpulan mesin yang terhubung jaringan; (2) run-time: proses software yang berkomunikasi lewat IPC (interprocess communication, misalnya HTTP); (3) implementasi: kumpulan loosely-coupled components yang di-deploy dan di-scale independen, disebut services.
Service mengimplementasikan sebagian kapabilitas sistem. Di dalamnya ada business logic yang menyediakan interface inbound (API yang diekspos) dan outbound (API call ke pihak lain).

Anatomi internal service: business logic di tengah, dikelilingi Service Interface (gRPC atau HTTP Controller), Messaging Interface (Kafka Producer/Consumer), dan Repository Interface (SQL Adapter), dengan adapter sebagai penghubung ke luar.
API: direct vs indirect. Direct: client mengirim request, server membalas langsung. Indirect: lewat broker. Pada direct, pesan berisi data yang diserialisasi dengan format language-agnostic. Bila client terblok menunggu response disebut synchronous communication; tidak efisien karena thread terblokir. Teknologi umum: gRPC, REST, GraphQL.
Infrastruktur komunikasi berupa libraries (socket library, Boost Asio), fitur bahasa (Java RMI), atau layanan spesifik platform (Android, Unix, Windows). Pemilihan teknologi komunikasi adalah penentu penting desain karena memberi constraint pada arsitektur, implementasi (idiom, pattern, cara koding), dan teknik pengembangan (thread, async, kompatibilitas).
Middleware adalah perantara antar komponen software di sistem berbeda, fokus pada integrasi dan interoperability. Layanan umum: transparent location services (client tidak perlu tahu lokasi server), standardized communication, network and platform independent, reliability/scalability/availability.
| Kategori | Contoh Teknologi |
|---|---|
| Stack protocol (TCP/IP) | Socket library, tersedia di banyak platform/bahasa |
| RPC & serialization | RMI, Apache Thrift, Google Protobuf, Apache Avro |
| Message-oriented middleware | JMS, AMQP, XMPP, Apache Kafka |
| Enterprise messaging | SOAP, Web Services |
| Application servers | JSP servers, EJB container |
| Database access | ORM, Hibernate, JPA |
- Stack protocol: library atau dukungan bahasa untuk mengakses jaringan di level aplikasi, mencakup layer network, transport, dan aplikasi.
- RPC/Serialization: framework RPC menyediakan definisi prosedur yang bisa dipanggil jauh, serialisasi (mengubah data menjadi format yang bisa dikirim), penyembunyian detail komunikasi, dan abstraksi seolah memanggil fungsi lokal. Contoh Java RMI: Client punya Stub (representasi lokal objek remote), Server punya Skeleton; Server melakukan registration ke Naming Service (RMI Registry) dan Client melakukan lookup untuk menemukan objek remote (wujud transparent location service).

- Messaging: infrastruktur komunikasi berbasis message dengan dua pola, point-to-point dan publish-subscribe, lewat message channel. Contoh JMS: client
send/receivelewat Queue (PTP), ataupublish/subscribelewat Topic (pub/sub). Detail di 2.11.

- Application server: lingkungan menjalankan aplikasi dengan fitur persistensi, transaksi, dan distribusi; komponennya dibatasi aturan (lifecycle, akses ke luar, threading, blocking), contoh JSP server dan EJB container.
- Database access: API database (JDBC, ODBC), konversi SQL ke object model (ORM), dan gateway ke database lain.
Jenis aplikasi terdistribusi: (1) client/server klasik, (2) web applications, (3) file and information sharing, (4) distributed databases, (5) enterprise applications, (6) cloud computing, (7) multi-agent distributed systems.
- Klasik (FTP, web browser, remote shell, remote desktop): fitur spesifik, bergantung protokol standar, punya dedicated client dan server, komponen bisa dibuat vendor berbeda, tersedia luas.
- Web application: memakai HTTP, client di browser, fungsi utama di server. Session management kompleks karena HTTP stateless (butuh mekanisme seperti cookie). Social networks umumnya web app atau native app mobile.
- File/information services: sering peer-to-peer, robust terhadap failure, minimal centralization, cocok distribusi data skala besar (distribusi Linux) dan streaming.
- Distributed database: storage di lebih dari satu node dengan replikasi dan duplikasi. Untung: reliabilitas dan availabilitas lebih tinggi, skalabilitas lebih baik, distribusi data bisa disesuaikan. Rugi: kompleksitas implementasi, high maintenance, isu security lebih kompleks.
- Enterprise application: software perusahaan skala besar; dibangun in-house, custom-made pihak ketiga, atau SaaS. Ciri: arsitektur three-tier atau n-tier, platform software khusus, high performance dan scalable, maintenance dan support kritikal.
- Cloud computing: model software tanpa keterlibatan pengguna dalam deployment, konfigurasi, dan hosting; berbasis utility computing (bayar sesuai pemakaian); layanan berupa aplikasi web, layanan web, atau API; dikendalikan penuh vendor, client membayar sesuai pemakaian (pay-as-you-go).
Monolithic vs service/microservice (pengantar). Monolithic: seluruh logic (frontend dan backend) digabung jadi satu Web Server terhubung ke Database dan Storage.
| Aspek | Monolithic |
|---|---|
| Kelebihan | Mudah dibangun, di-deploy, ditest, dikoordinasikan, dan berbagi data. Pilihan terbaik untuk aplikasi sederhana. Bahkan layanan sangat besar (misalnya Facebook) tetap monolithic. |
| Kekurangan | Bottleneck pengembangan (banyak developer pada satu codebase, banyak koordinasi/merging). Kode besar bisa berantakan dan rapuh. Seluruh aplikasi harus di-redeploy meski fitur kecil. Harus satu bahasa, build system, dan runtime. |

Service/microservice: frontend dan backend dipecah ke komponen terpisah (Service A, B, C) yang independen. Layanan dipecah menjadi service kecil dengan antarmuka jelas (API), umumnya HTTP, dan deployment umumnya berbasis container sehingga tiap service di-deploy independen. Motivasi: membatasi penggunaan resource per komponen (isolasi resource), memungkinkan pembagian tim per komponen, dan menerapkan separation of concerns. Pembahasan lengkap di 2.9.
2.3 Stateless vs Stateful
Sumber: 01_Pengantar_Arsitektur_Aplikasi_Terdistribusi
Salah satu konsep terpenting untuk skalabilitas. Aspek yang diperhatikan dalam desain service:
- Stateless service memungkinkan scale out karena bebas diduplikasi; storage, session, dan data disimpan di luar service. Pada HTTP (stateless), perlu mekanisme menjaga identitas/sesi user, misalnya cookie.
- Cache & proxy: state bisa di-push ke luar service (CDN, cache service).
- Load balancing, sharding/partition data, push notification, asynchronous processing.
Stateless vs stateful worker thread. Stateless tidak mengingat apa pun dari request sebelumnya; perilaku ditentukan input request dan kode penanganan, jadi service redundan bisa menjalankan kode yang sama tanpa state lokal untuk disinkronkan. Stateful berubah seiring waktu akibat penanganan request (variabel persisten/global yang diubah). Stateless dianalogikan “pure function”, tetapi tidak berarti selalu deterministik (bisa melibatkan random). Contoh fungsi stateless: float cosine(float x), int sum(int a, int b), List sort(List myList), List<T> listAppend(List<T> myList, T newItem), float generateRandomNumber().
Studi kasus chess.com (tracking state banyak game catur, halaman misalnya https://chess.com/game/23):
| Desain | Cara | Masalah |
|---|---|---|
| Paling sederhana | Game state di memory satu mesin (dictionary), semua user ke satu mesin | Tidak scalable |
| Pendekatan 1: horizontal scaling naif (stateful) | Kode sama di banyak server, tiap game berjalan hanya di satu server (state lokal) | User harus kembali ke server yang sama (butuh routing/affinity). Bila satu server gagal, sekitar 1/n game hilang karena state hanya di memory server itu |
| Pendekatan 2: stateless | Push semua game state ke central shared database; user terhubung ke sembarang instance lewat load balancer | Database menjadi resource terpusat yang membatasi scalability dan bisa jadi bottleneck/single point of failure baru |
2.4 Load Balancer
Sumber: 01_Pengantar_Arsitektur_Aplikasi_Terdistribusi
Konsep: load balancer membuat cluster tampak seperti satu superior server dengan interface sama seperti single server (misalnya HTTP server di satu IP).

Keuntungan tambahan:
- Upstream server bisa diganti tanpa mengganggu layanan: rolling update (server diupdate satu per satu sambil traffic diarahkan ke yang masih versi lama) atau synchronized update (siapkan VM baru lalu alihkan konfigurasi LB ke semua VM baru sekaligus).
- Health check: LB mengirim request periodik (biasanya simple GET). Bila gagal, server dianggap crash dan LB berhenti meneruskan request sampai pulih.
Dua jenis local load balancer:
| Aspek | NAT (Network Address Translation) | Reverse Proxy |
|---|---|---|
| Layer kerja | IP layer | HTTP layer |
| Cara kerja | Meneruskan paket satu per satu, mengingat server mana ditugaskan untuk tiap client | Menyimpan full request/response sebelum diteruskan |
| Kompatibilitas | Tipe layanan apa pun | Hanya HTTP |
| Fitur tambahan | - | SSL termination, caching, compression |
| Contoh | Perangkat hardware NAT (umumnya mahal) | Nginx, Squid (open-source, murah) |

NAT LB mengubah IP dan port paket di kedua arah: client ke satu IP publik LB (2.2.2.2:80), LB memetakan tiap koneksi ke server backend (Server A di 10.0.0.2:80 atau Server B di 10.0.0.3:80) sambil mengingat pemetaan IP:port tiap client. Lebih sederhana dan efisien daripada reverse proxy karena tidak perlu mengimplementasikan TCP, HTTP, atau menyimpan full request/response.

Alur Nginx reverse proxy (6 langkah): (1) client kirim request ke LB; (2) LB memilih salah satu upstream server; (3) LB meneruskan (relay) request ke upstream di jaringan privat; (4) upstream mengirim response ke LB; (5) LB mencari tahu client mana yang berhubungan dengan koneksi tersebut; (6) LB meneruskan response ke client. Ada dua segmen jaringan: client-side WAN (publik) dan upstream-side private LAN; reverse proxy menjadi jembatan keduanya.
Keuntungan reverse proxy: SSL certificate cukup di proxy (komunikasi internal boleh tidak terenkripsi karena jaringan privat dianggap aman). Proxy bisa caching response, tetapi ini dapat membatasi skalabilitasnya (proxy menyimpan lebih banyak state/data cache).
| Aspek | NAT | Reverse Proxy |
|---|---|---|
| Routing oleh | IP address/port translation | HTTP proxy |
| Skala | ~1-10 juta request/detik | ~100 ribu - 1 juta request/detik |
| Layanan | Semua jenis | Hanya HTTP |
| Fitur tambahan | Tidak ada | SSL termination, caching |
Keterbatasan load balancer: bisa jadi single point of failure; batas praktis sekitar 1 juta request/detik; berada di satu data center (mungkin jauh dari customer, dan data center itu sendiri jadi SPOF). Untuk layanan sangat besar muncul masalah distributed service discovery: bagaimana client menemukan replica tanpa melewati bottleneck pusat? Solusinya load balancing global lewat DNS atau IP Anycast.
DNS sebagai global load balancer. DNS adalah direktori terdistribusi yang memetakan hostname ke IP, dengan arsitektur distributed, hierarchical, dan caching. Local resolver menyimpan cache jawaban dan hanya bertanya ke hierarki atas bila tidak ada di cache.
- Round-robin DNS: beberapa jawaban (banyak IP) untuk satu query; client memilih salah satu secara acak, atau server memberi respons berbeda ke user berbeda (acak atau bergiliran/cyclic, asal nama round-robin). Karena DNS cached dan terdistribusi, tidak ada batas skala untuk sisi frontend.
- Geographic load balancing: DNS server memeriksa IP requester (IP address geolocation) lalu meresolve ke server paling dekat secara geografis, jawabannya disesuaikan per client.
- CDN (Content Delivery Network): kumpulan web server global yang meng-cache response untuk client lokal. Pada dasarnya distributed caching HTTP reverse proxy yang memakai DNS (dan teknik lain) untuk geographic load balancing. Contoh: Akamai, Cloudflare, Cloudfront (jaringan edge server di banyak kota).
- IP Anycast: contoh
8.8.8.8(DNS publik Google, lebih dari 400 miliar request/hari). Karena layanan ini adalah DNS itu sendiri, tidak bisa memakai DNS untuk load balancing sendiri. Solusi: banyak router Google di seluruh dunia mengiklankan lewat BGP bahwa mereka mencapai8.8.8.8dalam satu hop, sehingga traffic dikirim ke router Google yang paling dekat secara topologi. Secara teknis melanggar prinsip satu IP = satu destinasi tunggal, tetapi tidak masalah untuk DNS karena memakai UDP yang stateless.
| Aspek | DNS | IP Anycast |
|---|---|---|
| Routing oleh | Domain Name Service | BGP |
| Batas skala | Dibatasi Internet itu sendiri | Dibatasi Internet itu sendiri |
| Kecepatan perubahan | DNS TTL (menit sampai jam) | BGP convergence (sekitar satu menit) |
| Kemudahan deployment | Perlu software/konfigurasi DNS lanjut | Harus mengoperasikan Autonomous System sendiri (jadi ISP) |
DNS paling umum karena mudah; IP Anycast realistis hanya untuk perusahaan raksasa (Google, Facebook, Amazon, Microsoft) yang mengoperasikan jaringan sendiri.
| Aspek | Local | Global |
|---|---|---|
| Routing oleh | NAT atau HTTP Proxy | DNS atau BGP |
| Batas skala | Kecepatan satu mesin | Internet itu sendiri |
| Kecepatan perubahan | Milidetik | Menit sampai jam |
| Kemudahan deployment | Sederhana, software/hardware siap pakai | Perlu software/konfigurasi DNS lanjut |
Mayoritas layanan skala besar memakai dua level sekaligus: Local (operasi berkelanjutan dan skalabilitas di dalam satu data center, termasuk health check dan rolling update) dan DNS/Global (skalabilitas global dan latency rendah, mengarahkan user ke data center terdekat).
2.5 Arsitektur Proses Server dan Model I/O
Sumber: 02_Proses_Server_Architecture
C10K problem: bagaimana mendesain socket server yang menangani sangat banyak klien bersamaan (sekitar 10 ribu koneksi concurrent). Bottleneck pada skala besar: data copies (penyalinan antar buffer, misalnya user-space ke kernel-space), context switches, memory allocation, dan lock contention.
Perdebatan: “On the Duality of Operating System Structures” (Lauer & Needham: message-oriented system, proses sedikit, statis, komunikasi via pesan eksplisit, vs procedure-oriented system, proses banyak, dinamis, sinkronisasi via shared data) serta “Why Threads Are A Bad Idea (for most purposes)” (Ousterhout) vs “Why Events Are A Bad Idea (for high-concurrency servers)” (von Behren, Condit, Brewer).
Alur request di web server: (1) accept koneksi TCP; (2) read request: baca raw bytes dari socket (I/O bound) lalu parsing (CPU bound), plus baca body bila ada (misalnya POST); (3) dispatch request (baca file untuk static, atau teruskan ke backend/CGI/FastCGI/WSGI, I/O bound); (4) tulis response ke socket. Sebagian besar tahap I/O bound, hanya parsing yang CPU bound, sehingga desain penanganan I/O sangat menentukan performa.
Strategi penanganan client:
| Strategi | Cara | Catatan |
|---|---|---|
| One process per client | Listener accept() lalu fork() proses baru tiap koneksi; parent close(newsock) | Overhead fork per koneksi |
| 1p1c prefork | nchildren proses di-fork di awal, tiap child loop accept() pada listensock yang sama | Menghindari overhead fork per koneksi, latency terima koneksi lebih kecil |
| 1t1c prethread | Sejumlah thread dibuat di awal (pthread_create), tiap thread menunggu koneksi pada listensock yang sama | Thread lebih ringan daripada proses (berbagi address space), tetap bermasalah pada koneksi sangat banyak |
Masalah model 1 process/thread per client: resource agregat besar. Contoh: response 100 KB (tipikal) diambil dari disk sangat cepat, tetapi bisa 10 detik untuk dikirim ke client (tergantung kecepatan jaringannya), jadi thread banyak idle menunggu I/O. Dengan 1000 client dan 1 MB per thread/process, dibutuhkan 1 GB hanya untuk 1000 koneksi. Makin parah dengan persistent connection HTTP (koneksi tetap terbuka untuk beberapa request). Akar masalah: aplikasi jaringan itu I/O bound, sehingga model ini memboroskan resource saat resource tidak dipakai komputasi.
Dua fase operasi input: (1) menunggu data siap di kernel, (2) menyalin data dari kernel ke process. Lima model I/O: blocking, non-blocking, I/O multiplexing, signal-driven, asynchronous. Bedanya pada cara menangani dua fase ini.

| Model I/O | Fase wait for data | Saat data belum siap | Efisiensi |
|---|---|---|---|
| Blocking | Proses memanggil recvfrom dan diblok kernel sampai data siap (fase copy juga blok) | Tidak melakukan apa pun, tidak buang CPU, tapi tidak bisa mengerjakan tugas lain | Sederhana, tapi 1 proses/thread hanya 1 koneksi, tidak scalable |
| Non-blocking | Polling berulang memanggil recvfrom; langsung dapat error EWOULDBLOCK bila belum siap; fase copy tetap blok | Bisa lanjut kerja lalu polling lagi | Boros CPU (busy-wait) |
| I/O Multiplexing (select/poll/epoll/kqueue) | Satu panggilan memantau banyak descriptor, proses blok di panggilan itu; setelah ready, recvfrom (blok saat copy) | Blok sampai salah satu dari banyak socket ready, bukan busy-wait | Efisien untuk banyak koneksi dengan 1 thread; select/poll punya overhead pemeriksaan linear |
| Signal-driven | Proses mendaftar handler SIGIO via sigaction, lanjut kerja; kernel kirim SIGIO saat data siap; lalu recvfrom (blok saat copy) | Tidak ada busy-wait maupun blok | Handling signal lebih rumit, kurang umum untuk I/O volume tinggi |
| Asynchronous | aio_read langsung return; kernel mengerjakan kedua fase (wait + copy); notifikasi setelah selesai total | Tidak ada blok sama sekali | Paling efisien teori, dukungan OS/API historisnya terbatas |
Empat model pertama menangani fase pertama berbeda-beda, tetapi fase kedua (copy) selalu blok di recvfrom. Hanya async I/O yang non-blocking penuh di kedua fase. Beda signal-driven vs async: signal-driven memberi notifikasi saat I/O dapat diinisiasi (data siap, proses masih memanggil recvfrom dan menunggu copy); async memberi notifikasi saat I/O sudah complete (data sudah di user buffer).
I/O multiplexing: implementasi.
- select():
int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout), mengembalikan jumlah descriptor ready.fd_setadalah kumpulan bit descriptor, dimanipulasi lewat macroFD_ZERO,FD_SET,FD_CLR,FD_ISSET. Developer menentukan socket yang dicek untuk read, write, dan error, lalu setelah return memeriksa satu-satu denganFD_ISSET. Multiplexing: tiap koneksi baru masuk watchlist,selectmenunggu event seluruh watchlist. - Masalah select: (1) seluruh set descriptor dikirim ulang tiap pemanggilan (two memory copies user-kernel); (2) setelah return harus iterasi seluruh descriptor (linear scan); (3) set harus dibangun ulang tiap pemanggilan; (4) hanya untuk descriptor (socket/file), signal dan event lain perlu mekanisme terpisah. Alternatif: poll, epoll, kqueue.
- poll():
int poll(struct pollfd fds[], nfds_t nfds, int timeout), memakai arraypollfd {fd, events, revents}. Tidak dibatasi ukuran tetap sepertifd_set, tapi tetap scan linear. - kqueue (BSD): lebih efisien dan general purpose (socket/file, signal, timer, child process). Struktur
kevent {ident, filter, flags, fflags, data, udata}; pasangan<ident, filter>adalah identitas event (ident= file descriptor, process id, atau signal number;filtermisalnyaEVFILT_READ/EVFILT_WRITE;flagsmisalnyaEV_ADD,EV_DELETE,EV_ENABLE,EV_ONESHOT,EV_ERROR). Alur:kqueue()membuat antrian event,EV_SETmengisi event,kevent()mendaftarkan minat sekaligus memonitor. - epoll (Linux): setara kqueue.
epoll_createmembuat instance,epoll_ctlmendaftar/menghapus/mengubah minat,epoll_waitmenunggu dan langsung mengembalikan daftar descriptor ready (tanpa scan linear).
Level-triggered vs edge-triggered. Bila paket N bytes datang tapi aplikasi hanya membaca B < N, tersisa N-B. Level-triggered: notifikasi terus muncul selama masih ada data belum dibaca. Edge-triggered: notifikasi hanya saat status berubah (misalnya dari tidak ada data menjadi ada data), jadi aplikasi wajib membaca semua data yang tersedia dalam satu kesempatan.
Library event handling: libevent dan libev membungkus select/poll/epoll/kqueue. Pada libev konsep utama adalah watcher (minat terhadap event tertentu): ev_io, ev_timer, ev_periodic, ev_signal, ev_child, ev_stat.
Thread vs Event.
- Model thread: satu thread per rangkaian event terkait (misalnya per koneksi TCP); bila I/O belum ready, thread diblok; state machine implisit dalam alur sekuensial; shared state harus disinkronkan; scaling teorinya satu thread per koneksi.
- Model event: satu event loop menunggu event berikutnya; tiap event ditangani sampai selesai (“completion”); state machine dilacak eksplisit; satu thread bisa menangani event konkuren (secara teori) tanpa batas; secara teori tidak perlu sinkronisasi; scaling teorinya satu event loop per CPU core.
| Aspek | Thread | Event |
|---|---|---|
| Performance | Abstraksi lebih berat terhadap hardware (blocking I/O menerjemah ke polling); context switch mahal; operasi sistem sering O(n), meski bukan fundamental | Memetakan lebih rapi ke hardware (tanpa interrupt, CPU core pada dasarnya sistem event); lebih mudah efisien; kompleksitas dilempar ke aplikasi; O(n) terhadap jumlah tipe event, sudah diperbaiki dalam dekade terakhir |
| Control flow | Linear tersirat (I/O ini, lalu itu); pola umum dan mudah (call/return, parallel calls, pipelines); flow kompleks (dynamic fan-in/fan-out) tidak cocok | Tidak ada flow tersirat, mendukung call/return, parallel, pipelines, fan-in/fan-out; tapi flow sederhana justru lebih sulit diprogram (exception dan error handling sangat sulit) |
| Synchronization | Sulit (locks, condition variables, channels), sulit dinalar dan di-test; kadang diperlukan meski tidak fundamental (misalnya uniprocessor) | “Gratis” pada single thread; TAPI hanya untuk uniprocessor, server scalable multi-core tetap butuh sinkronisasi eksplisit |
| State management | State terenkapsulasi otomatis di stack; tapi tiap thread butuh stack sendiri (ukuran sulit: terlalu kecil overflow, terlalu besar boros) | State dilacak eksplisit (“stack ripping”) lewat variabel global/shared, sulit bila state-space besar; tidak perlu stack per thread jadi memori optimal |
| Scheduling | Preemptive oleh sistem: isolasi performa (komputasi panjang tidak membuat thread lain starvation), programmer tidak memikirkan scheduling; tapi butuh worst-case context switching dan keputusan bisa suboptimal | Cooperative: handler menyerahkan kontrol dengan return ke loop; keputusan scheduling di aplikasi; hanya bila menulis event loop sendiri; fairness sulit dicapai dan sulit di-debug/test regresinya |
Ringkasan: event unggul pada sinkronisasi murah (multitasking kooperatif), overhead state ringan, scheduling dan locality lebih baik karena informasi level aplikasi, control flow fleksibel. Thread unggul pada abstraksi lebih natural (alur sekuensial manusia) dan peluang improvement dari compiler/runtime (thread tidak secara fundamental lebih lambat, hanya implementasinya historisnya lebih berat).
Contoh server nyata.
- Apache: multiprocess-multithreads lewat MPM: prefork (preforking process, non-threaded, dipakai Apache 1.3), worker (multi-process multi-threaded), event (event-based/multiplexing).
- Nginx: event-based, sejumlah worker yang masing-masing menerima banyak koneksi (bukan 1 thread = 1 koneksi). Event-driven (multiplexing
kevent/epoll/select), asynchronous dan non-blocking, satu proses Master (load configuration, launch workers, non-stop upgrade), tiap worker punya run loop pada socket yang di-share, berkomunikasi ke backend lewat HTTP, FastCGI, atau protokol memcache, dan memakai advanced I/O (sendfile, AIO, mmap) untuk proxy cache.

2.6 Asynchronous Programming
Sumber: 03_Asynchronous_Programming (memakai konsep event loop di 2.5)
Motivasi: untuk aplikasi I/O bound (khususnya network), asynchronous/event-based lebih efisien daripada thread-per-request karena tidak perlu stack per thread, tidak ada context switching saat penanganan resource, dan menghindari race condition thread. Dua kesalahpahaman: async tidak membuat program lebih cepat, dan async tidak berarti tidak perlu thread. Async soal efisiensi resource.
Arsitektur library async: blocking request diubah menjadi event loop + handler. Event loop mengecek event lalu memanggil handler. Handler tidak boleh blocking dan harus selesai secepat mungkin (selama handler jalan, loop tidak memproses event lain); pekerjaan blocking harus dialihkan keluar (misalnya thread pool). Hal yang perlu dipahami pada tiap framework: pembuatan, run, dan terminasi loop; cara mendefinisikan event dan handler; cara mendaftarkannya ke loop; jenis handler; penanganan blocking request; library pendukung high level task.
Library C: libevent (mendukung /dev/poll, kqueue, select, poll, epoll), libev (memperbaiki bug dan limitasi libevent), libuv (dikembangkan untuk Node.js; abstraksi di atas libev pada Linux dan IOCP pada Windows sehingga portable; di baliknya epoll/kqueue/event ports di Unix, IOCP di Windows, thread pool untuk operasi yang native blocking seperti file I/O).
Anatomi watcher libev: buat loop (ev_default_loop), inisialisasi watcher dan callback (ev_init), set parameter (ev_io_set), aktifkan (ev_io_start), jalankan (ev_run). Keluarga fungsi per jenis ev_TYPE: ev_init, ev_TYPE_set, ev_TYPE_init (gabungan), ev_TYPE_start, ev_TYPE_stop. Jenis watcher: io (level trigger), timer, periodic, signal, child, stat, idle (loop sedang idle), prepare dan check (sebelum dan sesudah polling I/O), embed, fork. Watcher one-shot harus dihentikan manual di callback (ev_io_stop). ev_break(loop, EVBREAK_ALL) menghentikan semua ev_run bersarang, EVBREAK_ONE hanya yang paling dalam.

Satu iterasi loop libuv: update waktu loop, cek loop masih alive (ada watcher aktif), jalankan timer jatuh tempo, panggil pending callback, jalankan idle handle, jalankan prepare handle, poll I/O, jalankan check handle, panggil close callback, ulangi.
Python: threading ke asyncio. Contoh 10.000 thread yang masing-masing sleep(60) menghabiskan sekitar 82 GB memory karena tiap thread dapat stack sendiri; ini bukti model thread-per-task tidak scalable. Thread pool (concurrent.futures.ThreadPoolExecutor, max_workers) lebih terkontrol, tetapi tetap memakai thread OS dengan overhead context switching dan risiko race condition.

asyncio: library concurrent programming dengan syntax async/await. Menjalankan event loop; task dieksekusi sesuai event; task yield secara voluntary lewat await (bukan di-preempt). Alur: jalankan loop, panggil fungsi async/await, buat task, tunggu task selesai, tutup (close) loop. Contoh minimal asyncio.run(main()) (Python 3.7+). Pengelolaan eksplisit: loop.create_task, run_until_complete, batalkan task pending (task.cancel()), asyncio.gather(..., return_exceptions=True), loop.close().
Blocking call di asyncio: fungsi blocking (misalnya time.sleep() langsung) tidak boleh dipanggil di coroutine karena memblokir seluruh loop. Solusi: offload ke executor (thread pool) lewat loop.run_in_executor(None, blocking).
Coroutine: objek yang mengenkapsulasi kemampuan melanjutkan (resume) eksekusi fungsi yang di-suspend sebelum selesai. Tiga cara memicu: coro.send(None), loop.create_task(coro), await coro. Contoh: main() men-await f(); eksekusi main() di-suspend sampai f() selesai, semua dalam satu thread yang dikoordinasikan event loop.
2.7 API, REST, Serialisasi, dan Autentikasi
Sumber: 04_RPC_Fundamentals_API
API mendefinisikan bagaimana software dipakai software lain. API untuk library: daftar fungsi/kelas dalam proses yang sama (Java SDK API, Linux Kernel API, Socket API). Network API: disediakan software service untuk dipanggil dari proses/mesin lain lewat jaringan (RPC API). Bentuknya: Sun (ONC) RPC, Java RMI, CORBA (obsolete), REST, SOAP, Apache Thrift, Protocol Buffers, GraphQL. Karena diakses lewat jaringan, wajib memperhatikan authentication, authorization, confidentiality.
Klasifikasi: web-based vs non-web-based; Ingress (interaksi dengan pihak eksternal, lewat internet, high latency, satu call bisa memicu banyak interaksi internal) vs Internal (antar komponen dalam sistem sendiri). Ilustrasi Barista: satu request ingress diteruskan ke beberapa service internal (Hot/Cold Beverage Barista) yang memanggil service lebih granular (Espresso, Milk, Ice).

Hal yang dipertimbangkan saat mendesain API:
- Format data: teks (JSON, XML: human-readable, mudah di-debug, verbose) vs binary (Protocol Buffers, Thrift: ringkas dan efisien, tidak bisa dibaca manusia).
- Gaya arsitektur:
| Aspek | Resource-Oriented (REST) | RPC (Command-Oriented) | GraphQL |
|---|---|---|---|
| Unit dasar | Resource/objek data (mis. /accounts/12345) | Aksi/prosedur (mis. createMessage) | Query ke graph data, client menentukan field |
| Operasi | HTTP method standar | Nama fungsi bebas sesuai domain | Satu endpoint, dibedakan lewat query/mutation |
| Cocok untuk | CRUD yang natural sebagai resource | Aksi sulit dijadikan resource (mis. calculateTotal) atau perlu kontrak fungsi eksplisit | Kebutuhan fleksibilitas field, menghindari over-/under-fetching |
| Overhead | Sedang (HTTP + format teks) | Bisa sangat rendah bila biner (Thrift/gRPC) | Tergantung implementasi, umumnya di atas HTTP |
- Command-oriented vs resource-oriented: command-oriented memodelkan API sebagai pemanggilan aksi (mirip fungsi), resource-oriented memodelkan sebagai representasi state resource yang dimanipulasi lewat verb standar.
- Granularitas: terlalu fine-grained butuh banyak round-trip; terlalu coarse-grained bisa mengembalikan data berlebih. Volume: besar data per request memengaruhi pilihan format dan transport.
- High message rate, low overhead: overhead per pesan (header HTTP, parsing JSON/XML) signifikan pada frekuensi tinggi, mendorong format biner. Streaming: request-response klasik kurang natural, mendorong protokol seperti gRPC yang mendukung streaming native.
HTTP methods dan idempotence:
| Method | Fungsi | Idempotent? |
|---|---|---|
| GET | Membaca data | Ya |
| POST | Mengirim data baru | Tidak |
| PUT | Membuat atau menggantikan dokumen/entity | Ya |
| DELETE | Menghapus dokumen/entity | Ya |
| HEAD | Seperti GET tanpa body (hanya headers) | Ya |
| PATCH | Mengubah sebagian data | Tidak (default) |
Idempotence: request bisa diulang berkali-kali tanpa mengubah hasil akhir dibanding sekali. HTTP mengatur semua method selain POST idempotent. Penting karena proxy/server dapat mengulang PUT dan DELETE (retry saat timeout), jadi server harus menanganinya tanpa efek samping. Status code umum: 200 OK, 301 Moved Permanently, 403 Forbidden, 404 Not Found, 500 Internal Server Error.
Contoh REST: GET /accounts/12345 dengan Accept: application/vnd.acme.account+json mengembalikan 200 OK berisi account_number, balance {currency, value}, dan links ke aksi lanjutan (deposit, withdraw, transfer, close). Pola links ini dikenal sebagai HATEOAS (Hypermedia as the Engine of Application State): client tidak hardcode endpoint, cukup mengikuti link dari server.
Idempotence dalam praktik (Elasticsearch): PUT /my-index/_doc/2345 idempotent (ID eksplisit, diulang hanya menimpa); POST /my-index/_doc tidak (server membuat ID baru, diulang bisa membuat duplikat).
Semantik REST harus sesuai HTTP. DELETE /user/[user-id]/feed/posts/latest bermasalah: DELETE seharusnya idempotent, tetapi diulang (retry) bisa menghapus lebih dari satu post. Solusi: rujuk resource lewat ID, DELETE /user/[user-id]/feed/post/[post-id].
Input/output REST: Request: method (GET baca; POST/PUT/DELETE edit), path (jenis request sekaligus parameter, mis. GET /tweets/kistijantoro), query parameter (GET /search?startDate=...&search=...&api_key=...), headers (cookies, custom), body (form-encoded atau JSON). Response: status code (200, 403, 404, 422), headers (hati-hati dengan custom headers), body (umumnya JSON). Umumnya butuh API key atau access token untuk authentication dan authorization.
REST API design style: path merepresentasikan resource; GET baca, PUT/POST buat atau ubah, DELETE hapus. Aksi (bukan sekadar data) sulit dijadikan REST; biasanya dikonversi jadi “event resource”. Evolusi desain “membuat pesan baru di inbox”: POST /inbox/createMessage (jalan tapi tidak RESTful, ala RPC) → POST /inbox/message (lebih RESTful) → PUT /inbox/message/[uuid] (lebih baik lagi: identitas eksplisit sehingga otomatis idempotent).
| Kelebihan HTTP (REST) | Kekurangan |
|---|---|
| Enkripsi (TLS/HTTPS) built-in | Mewarisi kompleksitas HTTP yang belum tentu diperlukan |
| Kompresi didukung banyak library/server | Format human-readable (JSON/XML) menambah overhead ukuran |
| Hampir semua bahasa punya HTTP library | Perlu memikirkan ulang desain agar sesuai model REST (memetakan aksi ke resource bisa sulit) |
| Banyak server framework siap pakai (Tomcat, Node.js, Django, Flask, FastAPI) yang menangani enkripsi, kompresi, database pooling, queueing | |
| Web proxy dan cache langsung bisa dimanfaatkan | |
| Response code HTTP cukup generik untuk dipakai ulang |
Contoh REST API publik di slide: Twitter REST API, Elasticsearch REST API, Oracle Fusion Cloud Financials REST API, Discourse forum public API.
Format lebih efisien (sekilas): Apache Thrift dan Protocol Buffers tidak dibangun di atas HTTP. Message lebih space-efficient tetapi tidak human-readable; tanpa overhead HTTP; cukup spesifikasikan fungsi API lalu tools membangkitkan library bahasa yang diinginkan. Karena ukuran pesan bukan concern utama kebanyakan aplikasi, REST tetap lebih umum. Detail di 2.8.
Serialisasi. Memori adalah array besar dengan reference untuk struktur kompleks, sedangkan file adalah array of bytes dan message di jaringan adalah stream serial bytes. Serialisasi mengubah objek data (berstruktur reference) menjadi sequence of bytes untuk disimpan/dikirim, lalu direkonstruksi di penerima.
- JSON: format sebagian besar REST API; mendukung nesting, spasi diabaikan kecuali di dalam kutip.
[ ]list berurut,{ }dictionary/object tidak berurut (key harus string), tipe dasar number,true/false,null, string dalam kutip ganda. - XML: mendahului JSON, kini jarang karena lebih kompleks; HTML adalah dokumen XML untuk web page. Komponen: text, tag
<tagname>...</tagname>, atribut<Tag attr="value">. Pada level byte dengan UTF-8/ASCII, 1 karakter = 1 byte, jadi JSON/XML di kabel hanya deretan byte teks (bisa dilihat denganhexdump -C). - Reference membuat serialisasi tidak trivial: apakah objek yang direferensikan berkali-kali diulang, dan bagaimana circular reference (dua objek saling merujuk). Solusi umum: serialisasi reference berupa ID (contoh
hometown_id, ataubest_friend_idmelingkar). Kelemahan: butuh lebih dari satu pass (producer harus menemukan dan menyimpan seluruh objek yang direferensikan sebelum mengirim; consumer harus membaca dulu sebelum bisa menemukan data yang dirujuk ID).
Autentikasi.
- Berbasis HTML/form (cookie dan session): (1) login screen, (2) user kirim login dan password, (3) server verifikasi lalu mengembalikan cookie berisi session ID, (4) browser menyimpan cookie, (5) request berikutnya otomatis membawa cookie dan server mengidentifikasi user, (6) logout menghapus cookie, server bisa menghapus session ID; session ID biasanya punya expiry time. Atribut cookie autentikasi: Secure (hanya via HTTPS), HTTPOnly (tidak bisa diakses JavaScript), SameSite (hanya dikirim ke server asal yang sama). Potensi masalah: XSS dan CSRF.
- Bentuk session ID: random unique ID (server menyimpan pemetaan ke info user; tiap akses butuh query database, potensi masalah skalabilitas) vs rich token (informasi seperti user id, expiry, permission disematkan di cookie, menghindari akses database berulang, tetapi berpotensi dipalsukan; solusinya token di-sign dan bisa di-encrypt). Proses signing bisa terpisah dari aplikasi utama dan dipakai bersama banyak service, dasar SSO (Single Sign-On).
- OAuth 2.0: standar umum autentikasi API (terutama REST); sebenarnya standar authorization, memakai konsep scope untuk cakupan akses. OpenID Connect adalah implementasi populer di atas OAuth (menambah lapisan identitas). Alur: (1) akses tanpa autentikasi di-redirect ke authorizer, (2) user review dan login di authorizer lalu kembali dengan auth token, (3) akses berikutnya memakai token dan server mengembalikan response terautentikasi.

Flow authorization code (dengan login page): GET myservice.com/login → form login ke authorizer → POST authorizer.com/authorize (grant_type=authorization_code, redirect_uri, user, password) → 302 Found ke myservice.com/redirect?code=XXXXX → GET .../redirect?code=XXXXX → login ke sistem, set cookie, 302 ke myservice.com. Flow client credentials (tanpa interaksi user, server-ke-server): POST /token (grant_type, client_id, client_secret) mengembalikan JSON {access_token, token_type: "bearer", expires_in: 86400}; request berikutnya memakai header Authorization: "Bearer ZZZZ".
- JWT (JSON Web Token): token self-encoded dengan tiga elemen: Header (cara token di-encode: algoritma dan tipe), Payload (isi; field standar disebut claim, misalnya
ississuer danexpexpiry dalam Unix Epoch), Signature (memverifikasi token dari sumber sah dan tidak diubah), dihitungHMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret). Dikirim lewat headerAuthorization: Bearer <token>. Alur: Client meminta token ke Authorization Server, mendapat token, memakainya ke Resource Server. Karena self-encoded, ukuran membesar seiring claim; bermasalah bila terlalu besar (misalnya > 8 KB) karena dikirim berulang di header setiap request.

RPC dan evolusinya. RPC (Remote Procedure Call) adalah mekanisme IPC yang memungkinkan sebuah proses memanggil prosedur pada proses lain (mesin berbeda) seolah fungsi lokal.
| Tahun | Perkembangan |
|---|---|
| 1981 | Birrell dan Nelson mengimplementasikan RPC pertama di Xerox, dilanjutkan Sun RPC di Unix |
| 1990-an | Paradigma object-oriented: RMI (Java), CORBA |
| 1998 | SOAP (XML-RPC) |
| 2000 | REST |
| 2005 | JSON-RPC |
| 2007 | Apache Thrift |
| 2015 | OpenAPI/RESTful API, gRPC, GraphQL |
RPC dan REST adalah dua gaya dengan filosofi berbeda, bukan satu menggantikan yang lain: REST berbasis resource (cocok untuk API publik/ingress yang butuh keterbacaan, kompatibilitas luas, caching infrastruktur web); RPC (Thrift/gRPC) berbasis command/fungsi dengan kontrak eksplisit (cocok untuk komunikasi internal dengan high message rate, low overhead, dan streaming).
2.8 RPC Modern: GraphQL, Thrift, Protobuf dan gRPC
Sumber: 05_RPC_Serialization_GraphQL_Thrift_Protobuf
GraphQL
Motivasi (keterbatasan REST): endpoint berbasis resource butuh beberapa pemanggilan API untuk data yang saling terkait (GET user, lalu posts, lalu comments), dan tidak bisa memilih field spesifik (over-/under-fetching). Query-based API menyediakan: representasi resource lengkap berbasis id, listing koleksi dengan pagination dan filtering, mutasi data, response shaping (menentukan field), serta deep dan shallow fetch. Contoh yang dibakukan OASIS: OData (sering dikombinasi dengan REST, dipakai di Microsoft Graph API untuk Office 365). Contoh query OData: GET serviceRoot/Airports('KSFO')/Name (hanya field Name) atau GET serviceRoot/People?$filter=FirstName eq 'Scott'.

GraphQL adalah RPC-based API dengan fitur query dan mutation. Dikembangkan internal di Facebook pada 2012, dirilis publik 2015. Populer sebagai interface antara aplikasi SPA (Single-Page Application) dan mobile dengan backend datastore, karena mengambil data dengan beragam granularitas dan mendukung deep nested graph structure. Filosofi: “ask for what you want, get exactly that”; response memiliki shape persis seperti query. Query employee(id: 42) { name email birthDate hireDate } mengembalikan JSON dengan shape yang sama; deep fetch hero { name friends { name } } mengambil relasi satu-ke-banyak dalam satu request.
Komponen:
- Data schema: mendefinisikan tipe dan struktur data, dipakai untuk validasi di client dan server (query ke field yang tidak ada ditolak). Contoh tipe
Query { human(id: ID!): Human },Human { name, appearsIn: [Episode], starships: [Starship] },enum Episode {NEWHOPE EMPIRE JEDI},Starship { name }. - Resolver: implementasi di server yang menjalankan query; setiap field pada setiap type di-backup oleh sebuah resolver. Saat field dieksekusi, resolver-nya dijalankan: menjembatani schema deklaratif dengan sumber data nyata. Resolver field sederhana membaca properti object; resolver field relasi (misalnya
starships) memanggil sumber data lain untuk tiap id, dan itulah mekanisme di balik deep/nested fetch (tiap level nesting memicu resolver berjenjang).
Apache Thrift
Apache Thrift adalah RPC-based software library dari Facebook dengan fokus scalability, efficient dan reliable communication, dan multi-language (C++, Java, Python, PHP, C#, Erlang, JavaScript, Ruby, Objective-C, dll). Menangani serialisasi, service definition, dan server threading. Elemen: namespace, tipe data, exceptions, services.
IDL (Interface Definition Language) menyatakan struktur data dan services secara language-independent. Dari satu file IDL, thrift --gen <bahasa> membangkitkan kode untuk banyak bahasa target (memungkinkan cross-platform service, misalnya modul C++ diakses dari Node.js lewat client stub dan server stub dari IDL yang sama, menjadi network-based microservice). Tipe serialisasi Thrift juga bisa dipakai untuk pesan di messaging platform (NATS, RabbitMQ, AWS SQS, Apache Qpid).

Type system: dasar bool, byte, i16, i32, i64, double, string (UTF-8); khusus binary; struct (mirip struct C); container list<t>, set<t>, map<t1,t2>; exception; services (nama fungsi yang disediakan server, mirip Java interface; signature di IDL, implementasi di bahasa target). Contoh service CalculatorService { i32 add(1:i32 n1, 2:i32 n2) }.
Positional arguments dan evolvability: parameter diberi nomor eksplisit (1:i32 n1) supaya service tetap evolvable. Contoh: addUser(String firstname, string lastname, i32 ID) berubah menjadi addUser(String fullname, i32 ID, i32 phonenum) (urutan berubah, ada yang dihapus dan ditambah); informasi tipe saja tidak cukup membedakan versi, jadi dipakai nomor (1:string firstname, 2:string lastname, 3:i32 ID vs 4:string fullname, 3:i32 ID, 5:i32 phonenum) sehingga ID (nomor 3) tetap dikenali. Dasar kompatibilitas backward/forward. Berlaku juga pada struct dengan modifier required/optional dan nilai default (contoh struct Tweet dengan 16: optional string language = "english").
Arsitektur framework: lapisan dari atas: Client program/Service handler, Service stubs, User types, Protocol, Transport, Device.
- Protocol (TProtocol): serialisasi dari user types ke format serial (memetakan struktur data in-memory ke format on-the-wire, misalnya
writeI32,readI32,writeString,readString). Menangani format (text, biner, compress). - Transport (TTransport): pengiriman data di level byte (jaringan TCP/HTTP, disk, memory), bisa juga untuk logging.

| Varian Protocol | Keterangan |
|---|---|
| BinaryProtocol | Format biner sederhana, nilai numerik di-encode biner |
| TCompactProtocol | Encoding sangat efisien dan padat |
| TDenseProtocol | Mirip Compact tapi melepas meta information lalu menambahkannya kembali di penerima (eksperimental, tidak ada di Java) |
| TJSONProtocol | Memakai JSON |
| TSimpleJSONProtocol | JSON write-only, cocok diparsing scripting language |
| TDebugProtocol | Text human-readable untuk debugging |
| Varian Transport | Keterangan |
|---|---|
| TSocket | Blocking socket I/O |
| TFramedTransport | Data dalam frame dengan panjang di depan; wajib untuk non-blocking server |
| TFileTransport | Menulis ke file (tidak ada di Java) |
| TMemoryTransport | I/O di memory (Java: ByteArrayOutputStream) |
| TZlibTransport | Kompresi zlib, dipakai bersama transport lain (tidak ada di Java) |
Processor adalah “lem” hasil generate compiler yang menghubungkan pesan protokol RPC dengan kode developer. Server adalah high-level controller: membuat transport (buka TCP socket, bind, listen, accept), input/output protocol, dan processor, lalu menyerahkan koneksi ke processor. Pola server: TSimpleServer (single-threaded, blocking, untuk testing), TThreadPoolServer (multi-threaded, blocking), TNonblockingServer (multi-threaded, non-blocking, NIO di Java, harus TFramedTransport).
Model pengembangan: (1) buat file thrift (IDL), (2) implementasi handler dan server, (3) implementasi client. thrift --gen <bahasa> calculator.thrift menghasilkan interface Iface, kelas client dan Processor, serta kelas struct dan exception. Di client hasil generate, tiap method dipecah menjadi send_xxx lalu recv_xxx. Handler mengimplementasikan Iface. Server: handler, processor, TServerSocket, TSimpleServer, serve(). Client: TSocket → open() → TBinaryProtocol → Client, lalu memanggil method seperti fungsi lokal.
Performa (1 juta service request): dari paling lambat ke tercepat: SOAP (JAX-WS, Tomcat, HTTP, XML) → REST (JAX-RS/Jersey, Tomcat, HTTP, JSON) → Thrift (Tomcat, HTTP, JSON) → Thrift (TCP, JSON) → Thrift (TCP, Compact) tercepat.

Protocol Buffers dan gRPC
Protobuf adalah data serialization library (description language/IDL, compiler, runtime library) dari Google, fokus efisiensi, language interoperability, dan usability. Bahasa official: C++, Java, Python (lainnya via pihak ketiga). gRPC adalah library multi-language untuk RPC di atas Protobuf. Dibanding Thrift, Protobuf dan gRPC lebih opinionated: transport default HTTP/2, sementara Thrift membebaskan transport.

Pola kerja: definisi service di file .proto (mis. ProductInfo.proto) membangkitkan client stub (Consumer) dan server skeleton, saling berkomunikasi lewat Protocol Buffer di atas HTTP/2, bisa lintas bahasa (consumer Java, server Go).
HTTP/2 menambah binary framing layer dibanding HTTP/1.1 (teks): pesan dipecah menjadi HEADERS frame dan DATA frame biner. Keuntungan: multiplexing, banyak stream (request/response) berjalan bersamaan dalam satu koneksi TCP tanpa saling menunggu (HTTP/1.1 rawan head-of-line blocking); frame dari stream berbeda (1, 3, 5, …) berselang-seling pada satu koneksi.

Definisi pesan .proto: message dengan tiap field punya nomor unik (untuk evolvability, mirip numbering Thrift) dan modifier required/optional/repeated. Contoh Person {required string name = 1; required int32 id = 2; optional string email = 3; enum PhoneType; message PhoneNumber; repeated PhoneNumber phone = 4} dan AddressBook {repeated Person person = 1}. Kode dibangkitkan lewat protoc -I=<src> --java_out=<dst> tutorial.proto; pemakaian di Java memakai pola builder (Person.newBuilder().setId(...).build()). Method serialisasi/parsing: toByteArray(), parseFrom(byte[]), writeTo(OutputStream), parseFrom(InputStream).
gRPC service: service HelloService { rpc SayHello (HelloRequest) returns (HelloResponse); }. Empat pola komunikasi (memanfaatkan streaming HTTP/2):
| Pola | Request → Response | Contoh |
|---|---|---|
| Unary RPC | 1 request → 1 response | rpc SayHello(HelloRequest) returns (HelloResponse) |
| Server streaming | 1 request → stream response | rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse) |
| Client streaming | stream request → 1 response | rpc LotsOfGreetings(stream HelloRequest) returns (HelloResponse) |
| Bidirectional streaming | stream request → stream response | rpc BidiHello(stream HelloRequest) returns (stream HelloResponse) |
Dukungan bidirectional streaming native adalah keunggulan gRPC dibanding Thrift. gRPC membangkitkan stub client dan kode server dari .proto.

Alur remote call getProduct("ABC"): (1) client memanggil prosedur secara lokal; (2) stub client membangun encoded message biner beserta message headers (:method POST, :path /ProductInfo/getProduct); (3) dikirim lewat koneksi HTTP/2; (4) server menerima dan menyerahkan ke server stub; (5) server stub unpack menjadi request details (nama service, nama fungsi, parameter); (6) server stub melakukan local call ke fungsi getProduct sungguhan.
gRPC vs Thrift: gRPC memakai HTTP/2, Thrift punya transport layer extensible (TCP, memory, disk, AMQP, HTTP/2, websocket); gRPC native bidirectional streaming, Thrift tidak; gRPC saat ini lebih populer. Benchmark (rpc_benchmark): long connection, QPS tidak jauh beda, gRPC unggul latency lebih rendah, Thrift unggul CPU usage lebih rendah; short connection, Thrift (TCP) mengungguli gRPC (HTTP/2) pada QPS, CPU, dan latency. Catatan: pola satu goroutine per koneksi menaikkan CPU seiring jumlah koneksi (batasi koneksi), dan latency sebagian kecil koneksi sulit dikontrol karena GC Go yang stop-the-world; untuk aplikasi real-time dengan latency ketat disarankan implementasi C/C++.
| Aspek | Thrift | Protocol Buffers |
|---|---|---|
| Composite type | Struct {} | Message {} |
| Base types | bool, byte, 16/32/64-bit integer, double, string | bool, 32/64-bit integer, float, double, string, byte sequence |
| Containers | list<t1>, set<t1>, map<t1,t2> | Tidak ada container bawaan |
| Enumerations | Ya | Ya |
| Constants | Ya (mis. const i32 INT_CONST = 1234;) | Tidak |
| Exception | Ya (keyword exception) | Tidak |
Thrift punya type system lebih kaya; Protobuf lebih ramping tetapi ekosistem gRPC matang (HTTP/2, streaming) dan tooling Google luas. Kekurangan Protobuf/gRPC: setup awal lebih hassle (.proto, generate kode, toolchain protoc) dan hasil biner tidak human-readable; kelebihannya payload sangat compact dan serialisasi cepat, cocok untuk RPC performa tinggi antar microservice.
Perbandingan REST vs GraphQL vs Thrift vs Protobuf/gRPC:
| Aspek | REST | GraphQL | Apache Thrift | Protobuf & gRPC |
|---|---|---|---|---|
| Format data | JSON/XML via HTTP | Query teks, response JSON | Biner (Binary/Compact) atau JSON | Biner di atas HTTP/2 |
| Human-readable | Ya | Ya | Tergantung protocol | Tidak |
| Fleksibilitas data | Rendah (endpoint tetap, rawan over-/under-fetching) | Tinggi (client tentukan field dan kedalaman) | Rendah (signature tetap dari IDL) | Rendah (signature tetap dari .proto) |
| Performa | Relatif lambat, banyak round-trip untuk data relasional | Baik mengurangi round-trip, overhead parsing query | Tinggi (TCP + Compact) | Tinggi, payload compact |
| Polyglot | Ya | Ya | Ya, didesain polyglot | Ya (official C++/Java/Python, banyak lewat gRPC) |
| Use case | Public web API, CRUD sederhana | Backend SPA/mobile dengan data kompleks nested | RPC antar microservice banyak bahasa | RPC internal performa sangat tinggi, termasuk streaming dua arah |
| Learning curve | Rendah | Sedang | Sedang-tinggi | Sedang-tinggi |
2.9 Microservices: Konsep dan Trade-off
Sumber: 07_Microservices_Architecture (bagian konsep)
Masalah monolith: tier frontend dan backend sering tightly coupled meski dikembangkan tim berbeda; penambahan fitur butuh koordinasi antar tim sehingga deployment kompleks dan lama. Contoh Netflix sebelum migrasi: satu Monolithic App (Account, Catalog, Recommendation, Customer Service) di belakang satu Load Balancer berbagi satu Database.

- Karakteristik: large codebase, many components tanpa ownership jelas, long deployment cycles.
- Pros: single codebase (mudah develop/debug/deploy, dukungan IDE), mudah di-scale horizontal tetapi hanya secara un-differentiated, satu tim Ops terpusat efisien.
- Why not monolith: sulit frequent deployment dan continuous delivery; sulit dikelola dan umumnya harus teknologi sama; less reliability (perubahan satu tim butuh koordinasi tim lain); scalability lebih mahal (“Cant scale Product Catalog differently from Customer Service”); bug tracking sulit; komponen makin tightly coupled; availability rapuh (satu titik koma hilang pernah membuat seluruh website Netflix down berjam-jam sekitar 2008, satu request buruk/lambat bisa memblokir seluruh app container karena thread berbagi resource).
- Tipping point: kombinasi organizational growth, diverse functionality, dan bottleneck monolithic stack. Bezos Platform Mandate (Amazon): semua tim wajib mengekspos data lewat interface, tidak ada bentuk komunikasi antar-proses lain, semua interface harus externalizable.
- Skala Netflix: 2008 satu
.wardi data center; ~2010 pindah ke AWS dengan ratusan fine grained services; kini >500 microservices, ~30 tim engineering, ~2 miliar edge API request/hari.
Definisi (Martin Fowler): pendekatan mengembangkan satu aplikasi sebagai suite of small services, masing-masing berjalan di process sendiri dan berkomunikasi dengan mekanisme ringan, sering HTTP resource API. Definisi lain: small, independently deployed components that deliver one or a small number of bounded digital capabilities. Driver utama: koordinasi antar tim, prinsip 1 microservice : 1 team (Amazon two-pizza rule). Microservices bukan soal ukuran tim, jumlah baris kode, atau jumlah endpoint; soal bounded context (bahkan “MegaService” tetap microservice bila satu tanggung jawab dan independen).
Karakteristik: fine grained dengan Single Responsibility Principle; Domain Driven Development dan Bounded Context; independently managed dengan ownership jelas; umumnya model DevOps. Composability (filosofi Unix): “Write programs that do one thing and do it well. Write programs to work together.” (seperti pipeline tr | sort | uniq | comm).
Key enabler: container, container orchestration, dan platform manajemen container (deployment time lebih cepat dibanding VM atau bare metal); model komunikasi beragam dan efisien (sync dan async; JSON, XML, binary, Protobuf, Avro; tooling Thrift, gRPC).
Evolusi: Monolith (tightly coupled, monolithic scaling) → SOA (pemisahan tetapi little empowerment, service course-grained dan reusable, masih coupled lewat orkestrasi, masih berbagi server/DB/data, diperlakukan sebagai proyek) → Microservices (platform for the business, agility, tim bebas memilih server/tools/DB, dikelola sebagai produk, “Build it, Run it, Own it” dari conception sampai retirement).
Smart endpoints, dumb pipes. Public API: simple dan stateless (RESTful) (sedikit coupling ke proses, beda dari SOAP/Web services klasik, didesain outside-in), bullet proof (built-in error handling), berubah sangat lambat (mengisolasi consumer dari perubahan internal), self described (dokumentasi standar, misalnya Swagger), semua reuse dikonfigurasi bukan di-coding (security, identity, composition, policy/SLA, auditing, analytics). Private API antar service: kecerdasan di endpoint, bukan middleware (no intelligent middleware). Konsekuensi: designed for failure (service lain bisa gagal; uji dengan stress test dan simulasi kegagalan). Design security assuming it’s public: threat protection (OWASP top 10), identity management (AAA, OAuth 2.0), jangan asumsikan akses internal aman, auditability dan compliance; “the real firewall” ada di lapisan microservices, bukan hanya di edge.
| Aspek | Monolithic | Microservices |
|---|---|---|
| Codebase | Satu besar | Banyak kecil, satu per service |
| Deployment | Seluruh aplikasi sekaligus, siklus panjang | Independen per service, siklus cepat |
| Scaling | Undifferentiated | Selektif per service |
| Database | Umumnya satu bersama | Idealnya per service |
| Teknologi | Seragam | Polyglot |
| Availability | Satu bug bisa menjatuhkan semua | Fault isolation (bila diarsitekturkan benar) |
| Ownership | Banyak tim 1 codebase | 1 service = 1 tim |
| Kompleksitas | Di dalam 1 aplikasi | Pindah ke pengelolaan banyak service (distributed system) |
| Komunikasi | In-process | Antar proses via jaringan (REST/gRPC), overhead network |
| Testing | Relatif sederhana | Lebih sulit, perlu entire ecosystem untuk end-to-end |
| DevOps | Central Ops cukup | DevOps model per tim hampir mutlak |
Mengapa microservices: deployment dan rollback lebih cepat dan sederhana (independent speed of delivery); framework/tool/bahasa tepat per domain (mis. Recommendation Python, Catalog Java); greater resiliency lewat fault isolation; better availability hanya “if architected right”; cross-service coupling minimal (smart endpoints, dumb pipes). Microservices tidak otomatis availability lebih baik kecuali benar-benar fault tolerant (lihat 2.12).
Kekurangan dan tantangan: kompleksitas pengelolaan (“can lead to chaos if not designed right”); multiple database menyulitkan data dan transaksi lintas service; security vulnerabilities (attack surface lebih luas); testing lebih sulit; overhead network communication; kompleksitas DevOps (DevOps model absolutely required); reduced performance akibat serialization overhead (data di-transform berulang: JSON di client A, XML untuk service B, Avro untuk service C); butuh Service Metadata Registry untuk service discovery; service interface versioning (mismatch versi antar service); distributed systems (latency, fault tolerance, retry storms).
Trade-off: strong service boundary vs performance (overhead network); individual deployment vs eventual consistency (database masing-masing, masalah konsistensi, transaksi, performa); independent deployment vs operational complexity (testing, debugging, monitoring butuh automation); technology diversity vs cost of interface issues (polyglot, integrasi lebih kompleks).
12 Factor App (12factor.net): metodologi aplikasi modern untuk microservices agar memakai format declarative untuk setup automation (minim waktu onboarding), clean contract dengan OS (maksimum portability), cocok untuk platform cloud modern, meminimalkan divergensi dev dan production (continuous deployment), dan bisa scale up tanpa perubahan besar.
| # | Faktor | Penjelasan |
|---|---|---|
| 1 | Codebase | Satu codebase di version control, banyak deploy |
| 2 | Dependencies | Deklarasikan dan isolasi dependency eksplisit |
| 3 | Config | Simpan konfigurasi di environment, bukan hardcoded |
| 4 | Backing Service | Perlakukan DB, queue, cache, dst sebagai attached resource yang bisa ditukar |
| 5 | Build, Release, Run | Pisahkan tegas tahap build dan run |
| 6 | Processes | Jalankan sebagai satu atau lebih stateless process |
| 7 | Port binding | Ekspor service via port binding |
| 8 | Concurrency | Scale out via process model |
| 9 | Disposability | Robust: startup cepat dan graceful shutdown |
| 10 | Dev/Prod parity | Jaga dev, staging, production semirip mungkin |
| 11 | Logs | Perlakukan log sebagai event stream |
| 12 | Admin processes | Task admin sebagai one-off process |
2.10 API Gateway dan Service Mesh
Sumber: 06_API_Gateway_Service_Mesh (memakai microservices di 2.9 dan reverse proxy di 2.4)
Dua isu pengelolaan banyak API: traffic management dan security. Karena itu dibutuhkan infrastruktur terpusat, bukan implementasi berulang di tiap service.
API Gateway adalah façade/proxy untuk API publik, secara konsep reverse proxy: client memanggil gateway, yang meneruskan ke internal API yang sesuai. Manfaat: mengurangi coupling eksternal-internal; menyederhanakan akses (menggabungkan beberapa API internal menjadi 1 call, termasuk orkestrasi concurrent call); proteksi dari overuse dan abuse serta threat detection; observability penggunaan API; API lifecycle management (versioning, pemisahan dev/staging vs prod); monetisasi (account management, billing, payment).
| Fungsi | Penjelasan |
|---|---|
| Routing | Meneruskan request ke internal API yang sesuai, internal bisa berubah tanpa mengubah public API |
| Composition | Menggabungkan beberapa internal API low-level menjadi satu higher-level API |
| Translation | Mengubah protokol/format (REST publik → gRPC internal, atau satu query GraphQL → beberapa REST call internal) |
Cross-cutting concern (dibutuhkan hampir semua API, lebih efisien sekali di gateway): Authentication, Authorization, Rate-limiter (batasi request dalam periode tertentu), Timeout/retries, Logging, Tracing (jejak request lintas backend).
Sejarah: 1990-an hardware load balancer (F5) → 2000-an software load balancer (NGINX, HAProxy) → pertengahan 2000-an ADC (F5, Cisco, Citrix: compression, caching, connection multiplexing, traffic shaping, SSL offload) → awal 2010-an API gateway (Kong, NGINX, WSO2) → kini AWS API Gateway, GCP Apigee, Zuul (Netflix), Traefik, Tyk, Ambassador, Mulesoft.
Contoh AWS API Gateway: endpoint publik terintegrasi monitoring (CloudWatch) dan caching, me-route ke backend beragam (Lambda, Kinesis, EC2, DynamoDB, layanan eksternal).

Konfigurasi penting: Resource/Method mapping (berdasarkan path, query, method; integration type Lambda, HTTP, Mock, AWS Service, VPC Link); Stage (dev/staging/prod atau versioning); Authorizer (fungsi Lambda atau AWS Cognito); Gateway Response transformation (ubah status code/header/body, tangani Access Denied, Quota Exceeded, Invalid API Key); Usage Plans (rate limiting) dengan limit tetap atau algoritma leaky bucket yang mengizinkan burst volume tertentu sebelum throttling; Monitoring (API Calls, latency total, Integration Latency ke backend, error 4xx/5xx, alerting); Tracing dengan AWS X-Ray (peta node service dan rata-rata waktu respons).
Contoh Traefik: komponen Entrypoints (titik masuk HTTP/TLS/TCP, port yang di-expose), Providers (sumber konfigurasi routing: Docker labels, Kubernetes, file), Routers (menerima inbound request; Rules mencocokkan host/path/header, Middlewares mentransformasi request: header, redirect, auth, rate limiting), Services (meneruskan ke backend).

Service Mesh: “an infrastructure layer that enables you to control the network communication of your workloads from a single control plane.” Mengatur komunikasi internal antar service (routing, authorization, logging, traffic shaping) dari satu titik kendali terpusat. Fungsinya mirip API Gateway, tetapi API Gateway untuk trafik eksternal-ke-internal, service mesh untuk trafik internal; service mesh juga bisa mengatur akses eksternal (berfungsi seperti API Gateway). Contoh: Istio (data plane Envoy), Linkerd, Consul, App Mesh (AWS), Azure Service Fabric Mesh.
| Fitur service mesh | Penjelasan |
|---|---|
| Observability | Visibilitas perilaku dan kesehatan service (metrics, trace) |
| Routing | Cara request diarahkan (load balancing, canary/blue-green) |
| Automatic scaling | Autoscaling berdasarkan trafik/beban |
| Separation of duties | Konfigurasi mesh independen dari tim development |
| Trust | Secure communication (mis. mTLS) dan manajemen sertifikat |
| Automatic service registration and discovery | Registrasi otomatis saat deployment |
| Resilient | Retry, circuit breaking, timeout di level komunikasi |
Control plane vs data plane (dipisahkan karena requirement berbeda):
| Aspek | Control Plane | Data Plane |
|---|---|---|
| Fungsi | Mengatur konfigurasi dan kebijakan (policy, routing rule, load balancing, sertifikat) | Mengeksekusi kebijakan pada trafik request/data nyata |
| Volume trafik | Low volume | High volume |
| Prioritas | Konsistensi dikutamakan dibanding availability | Speed dan availability |
| Letak | Terpusat | Tersebar, melekat pada tiap service (sidecar) |
Sidecar proxy: tiap service berdampingan dengan proxy yang menangani seluruh komunikasi masuk/keluar; semua sidecar menerima konfigurasi dari satu control plane, jadi kebijakan konsisten meski service di lingkungan berbeda (Kubernetes maupun non-Kubernetes) tanpa mengubah kode service.

2.11 Messaging: Queue dan Publish-Subscribe
Sumber: 08_Message_Queue_Publish_Subscribe
Messaging system: fasilitas peer-to-peer (proses ke proses) untuk saling kirim pesan lewat broker, memberi loosely coupled communication (sender dan receiver tidak perlu tahu detail satu sama lain). Bentuk: direct message passing, message queue, pub/sub. Perbandingan decoupling:
| Abstraction | Space/time decoupling | Synchronization decoupling |
|---|---|---|
| Message passing | No | Varies |
| RPC/RMI | No | Invoker is blocked |
| Async RPC/RMI | No | Yes |
| Tuple spaces | Yes | Reader is blocked |
| Message queuing | Yes | Varies |
| Pub/sub | Yes | Yes |
Message queuing dan pub/sub memberi decoupling paling lengkap.

Komponen: Message (Header, Properties, Body), Message Queue (penyimpanan sementara), Producers, Consumers (mode pull atau push), Message Broker (mengelola queue; menerima send dari producer dan meneruskan recv ke consumer).
Jenis message dari sisi desain: Command (perintah/aksi), Event (notifikasi bahwa event terjadi), Document (notifikasi event lengkap dengan atribut entity, bukan hanya perubahan), Query (permintaan data). Contoh alur event-driven: UI query ke Inventory Service (Query) → UI publish CreateOrderCommand ke Message Queue → Order Service mengonsumsi, lalu publish OrderCreatedEvent ke Inventory Service dan OrderDocument ke Notification Service.
Point to Point (PTP): tujuan eksplisit lewat message queue; sender kirim ke queue tertentu, receiver memonitor queue itu. Sebuah pesan hanya dikonsumsi 1 receiver (bila banyak receiver di queue sama, pesan dibagi/load-balanced, bukan diduplikasi); sender tidak menunggu receiver; receiver bisa acknowledge; konsumsi bisa synchronous atau asynchronous.

Publish-Subscribe: pesan dikirim ke resource bersama, banyak subscriber mengonsumsi pesan yang sama (broadcast/multicast), subscriber menyatakan minat lewat filter.

Komponen sistem pub/sub: Publisher (membuat notifikasi/event instance), Subscriber (mengajukan subscription lalu menerima notifikasi), Subscription Manager (mengelola subscription di subscription storage), Notification Engine (mencocokkan event dengan subscription, mengirim ke Notification Consumer; event bisa disimpan di event storage), Notification Consumer (meneruskan ke subscriber).
Variasi sistem pub/sub: persistency (event dan subscription disimpan atau tidak; memengaruhi subscriber offline), filtering (berdasarkan source, header, atau content), broker hierarchy (single, clustered, hierarchical/partitioned), event delivery guarantee, dan acknowledgment (auto vs manual).
| Delivery guarantee | Penjelasan |
|---|---|
| Exactly once | Tepat satu kali, tidak hilang dan tidak duplikat; paling mahal |
| At least once | Pasti sampai tapi bisa duplikat (retry setelah ack hilang/timeout); consumer harus idempotent |
| At most once | Maksimal sekali, bisa hilang tapi tidak duplikat |
| No guarantee / best effort | Tanpa jaminan, bisa hilang atau duplikat |
Reliabilitas: trade-off data safety vs performance pada tiga titik (pengiriman dari producer, pengambilan oleh consumer, kegagalan broker). Mekanisme: publisher confirms (broker ack ke producer), persistent messages dan queues (disimpan ke disk), consumer manual ack (ack setelah selesai diproses, bila crash pesan di-redeliver). Trade-off lain: availability vs performance (jumlah node cluster dan replikasi).
Platform: RabbitMQ (AMQP broker), ActiveMQ (JMS broker), ZeroMQ (library, bukan broker penuh), RocketMQ (OpenMessaging, JMS), Kafka (high throughput), NATS, Mosquitto (MQTT), serta layanan cloud (Google Cloud Pub/Sub, Amazon SQS/SNS, Azure Service Bus, Alicloud SMQ).
JMS (Java Messaging Service)
JMS adalah spesifikasi (bukan implementasi) untuk message service di Java secara portable antar vendor; implementasinya disebut JMS Provider (contoh ActiveMQ).

Dua domain: Message Queues (PTP) dan Topics (pub/sub). Administered objects (Connection Factories dan Destinations) dikelola secara administratif (mis. j2eeadmin), diakses lewat interface portable via lookup JNDI. Dua Connection Factory: QueueConnectionFactory dan TopicConnectionFactory.

Programming model: Connection Factory → Connection (ke JMS Provider; QueueConnection/TopicConnection) → Session (single-thread context, mendukung transaksi, menserialisasi eksekusi message listener; QueueSession/TopicSession) → Message Producer (QueueSender.send, TopicPublisher.publish) dan Message Consumer (QueueReceiver, TopicSubscriber). TopicSubscriber bisa durable (menerima pesan yang dipublish saat subscriber tidak aktif, di-buffer broker). Message tidak di-deliver sebelum connection di-start(). Synchronous: receive() blocking (bisa dengan timeout). Asynchronous: implement MessageListener (onMessage(Message)) lalu setMessageListener.
Message selector: filter pesan (subset SQL92 conditional expression) lewat createReceiver/createSubscriber/createDurableSubscriber; filtering dilakukan JMS provider (di broker), lebih efisien karena pesan tak relevan tidak dikirim.
Tipe message JMS (header, properties, body): TextMessage (teks, mis. XML), MapMessage (pasangan name/value), BytesMessage (stream of bytes), StreamMessage (stream primitive Java, sekuensial), ObjectMessage (objek Java Serializable).
AMQP dan RabbitMQ
AMQP adalah open standard application layer untuk messaging dan pub/sub (OASIS, amqp.org); fitur: message orientation, queuing, routing, reliability, security. AMQP mendefinisikan perilaku provider, client, broker, dan wire-level protocol, sehingga client dan broker vendor berbeda tetap bisa berkomunikasi (beda dari JMS yang hanya spesifikasi API). Port standar 5672/tcp. Pola dasar: request-response dan pub/sub.
Model AMQP: Message Broker (server tempat client terhubung), Node (entity yang menyimpan/mengirim message: Producer, Consumer, Queue, Exchange), Container (meng-host node: Broker app atau Client app), Connection (koneksi fisik berasosiasi dengan User), Channel (koneksi logik di dalam Connection), Session (dua channel unidirectional antara 2 node). Message ditransfer antar node lewat Link (source dan target), dapat melewati filter. Container (Broker/Client) meng-host 0..n Node (Producer, Consumer, Queue).

Alur end-to-end: Publisher → Exchange di broker → Queue yang sesuai → Consumer. Exchange menerima pesan dari producer dan meneruskan ke queue yang sesuai; Queue menampung pesan untuk consumer secara FIFO, bisa di disk atau memory, tiap queue independen. Properti queue: private atau shared; durable atau temporary; client named atau server named (contoh: shared store-and-forward queue, private reply queue, private subscription queue).
Exchange menentukan routing dengan memeriksa header dan body pesan; routing key menentukan queue tujuan; exchange bisa durable, temporary, atau autodelete. Jenis: direct, fanout, topic (dan header).
| Exchange | Cara kerja |
|---|---|
| Direct | Routing key persis; cocok untuk point-to-point sederhana/load-balanced. Contoh: publish dengan key "France", hanya queue yang di-queueBind dengan key "France" menerima |
| Fanout | Pub/sub murni: pesan yang sama ke semua queue yang ter-bind, apa pun routing key |
| Topic | Content-based routing: pola binding (mis. a.b.c, a.b.*, a.#) dicocokkan dengan routing key; satu pesan bisa masuk beberapa queue |

Implementasi AMQP: OpenAMQ (C, opensource), RabbitMQ, Apache Qpid.
Contoh kode RabbitMQ. Point-to-point: producer queueDeclare("hello") lalu basicPublish("", "hello", ...) (langsung ke queue bernama tetap); consumer basicConsume; satu queue bernama tetap dibagi habis (PTP). Pub/sub (fanout): producer exchangeDeclare("logs", "fanout") lalu basicPublish("logs", "", ...) (kirim ke exchange, bukan queue); tiap consumer membuat queue anonim/sementara sendiri (queueDeclare().getQueue()) dan queueBind(queueName, "logs", ""), sehingga tiap subscriber menerima salinan pesan (ciri pub/sub). Direct: exchangeDeclare(..., "direct"), basicPublish(EXCHANGE, "France", ...) dan consumer queueBind(queueName, EXCHANGE, "France").
Apache Kafka
Kafka dikembangkan di LinkedIn sejak 2011 (Scala dan Java); tujuan: high throughput, realtime processing, fault tolerant, fast, large data. Komponen: Producer, Consumer, Broker (dalam Kafka cluster); Zookeeper mengelola state dan koordinasi broker dan consumer (versi baru bisa digantikan KRaft, materi ini memakai Zookeeper).
Topic, partition, offset: data disimpan di topics; topic dibagi ke beberapa partition yang masing-masing direplikasi; tiap message di partition punya offset (id unik). Producer menulis ke salah satu partisi. Urutan terjamin dalam satu partisi (berdasarkan offset), tidak antar partisi: parallelism tinggi mengorbankan urutan global. Jumlah partisi menentukan tingkat paralelisasi maksimum per consumer group.

Consumer Group (CG): pembacaan dijamin unik per consumer group: satu pesan diproses satu consumer dalam satu CG (semantik PTP di dalam grup), tetapi CG berbeda menerima salinan pesan yang sama. Maka dua pola:
- Publish-subscribe: tiap consumer di CG sendiri-sendiri, semua menerima semua pesan.
- Load balancing queue: semua consumer di CG yang sama, pesan dibagi.

Consumer memakai offset pointer per partisi, posisi baca disimpan per CG; pesan tidak dihapus setelah dibaca (tetap sampai masa retensi), jadi bisa replay dari offset awal. Contoh: 4 partisi (P0-P3) di 2 server, CG A (2 consumer) dan CG B (4 consumer) membaca keempat partisi secara independen.
Replikasi: tiap partisi punya replika sesuai replication factor; satu leader, sisanya follower/backup; semua read dan write hanya ke leader; bila leader gagal, satu follower dipromosikan (basis fault tolerant).
Konfigurasi dasar: buat topic via CLI (kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic test); auto-create topic via auto.create.topics.enable=true di config/server.properties. API Producer: send(KeyedMessage<K,V>) (satu topic, dipartisi berdasarkan key) atau send(List<...>) (banyak topic), close().
| Konfigurasi Producer | Keterangan |
|---|---|
client.id | Identifikasi producer app, mis. di system logs |
producer.type | async atau sync |
request.required.acks | Semantik acking |
serializer.class | Encoder |
metadata.broker.list | Daftar broker bootstrap |
| Konfigurasi Consumer | Keterangan |
|---|---|
group.id | Menetapkan consumer ke “group” |
zookeeper.connect | Menemukan broker/topic dan menyimpan consumer state (high-level consumer API) |
fetch.message.max.bytes | Bytes pesan per partisi; harus >= message.max.bytes broker |
Mengapa cocok untuk high-throughput, real-time, large-scale, fault-tolerant: write append-only ke log per partisi (sequential disk write cepat) dan partisi memungkinkan paralelisme (high throughput); consumer membaca segera setelah ditulis (near real-time); topic dipartisi lintas banyak broker (skala horizontal); replikasi leader-follower mencegah kehilangan data saat satu broker mati.
MQTT
MQTT (MQ Telemetry Transport): dikembangkan IBM sejak 1999, open standard OASIS 2014 (MQTT 3.1.1). Client/server publish/subscribe messaging transport protocol; bukan protokol message queue, murni pub/sub. Target: embedded device dan IoT. Fitur: lightweight dan binary (untuk low bandwidth, high latency, low powered device; payload UTF-8 string), berjalan over TCP, pola pub/sub berbasis topics, Keep-Alive timer, dukungan QoS.
Alur: client subscribe ke topik; client lain publish ke topik; client terhubung ke broker lewat CONNECT; broker mengautentikasi; saat publish, broker meneruskan ke semua subscriber topik itu; broker bisa menyimpan message dengan flag RETAIN dan WILL message. Jenis control packet: CONNECT, CONNACK, PUBLISH, PUBACK, PUBREC, PUBREL, PUBCOMP, SUBSCRIBE, SUBACK, UNSUBSCRIBE, UNSUBACK, PINGREQ, PINGRESP, DISCONNECT. Fixed header 2 byte: byte pertama Message Type, DUP flag, QoS level, RETAIN flag; byte kedua Remaining Length.

| QoS | Nama | Mekanisme |
|---|---|---|
| 0 | Best Effort | Hanya PUBLISH (setara at most once) |
| 1 | At Least Once | PUBLISH + PUBACK (retry bila ack tak diterima, bisa duplikat) |
| 2 | Exactly Once | PUBLISH + PUBREC + PUBREL + PUBCOMP (4-way handshake) |
Tiga level QoS memetakan ke tiga dari empat kategori delivery guarantee di atas.
RETAIN: bila diset, broker menyimpan pesan dan meneruskannya ke client baru yang subscribe ke topik tersebut walau bergabung setelah pesan dipublish (subscriber baru langsung mendapat state terakhir). Last Will and Testament (LWT): pesan “wasiat” yang didaftarkan saat CONNECT, otomatis dikirim broker ke client lain bila client itu terputus tiba-tiba/tidak normal (tanpa DISCONNECT), sehingga sistem lain bisa mendeteksi device IoT “mati” mendadak.
RabbitMQ vs Kafka (dan MQTT)
- RabbitMQ: general purpose messaging broker, AMQP compliant, beragam pola producer-consumer; exchange dan queue; mendukung PTP dan pub/sub; broker menyediakan routing (smart broker, dumb client); default pesan tidak persistent (producer bisa set persistent per pesan); transactional support.

- Kafka: high volume, durable data; pesan di-keep hingga durasi tertentu (durable message store); smart client, dumb broker (client mencatat sendiri offset, bisa replay dari awal).
| Aspek | RabbitMQ | Kafka | MQTT |
|---|---|---|---|
| Standar/protokol | AMQP compliant | Protokol proprietary Kafka | Standar OASIS, bukan message queue |
| Filosofi | Smart broker, dumb client | Smart client, dumb broker | Client/server pub-sub sederhana dan ringan |
| Model utama | PTP dan pub/sub (exchange direct/fanout/topic/header) | Pub/sub berbasis topic-partition dan consumer group | Pub/sub murni berbasis topic |
| Penyimpanan | Default tidak persistent (bisa persistent), dihapus setelah di-ack | Durable sampai masa retensi, bisa replay | Umumnya tidak persistent, kecuali RETAIN |
| Skala/use case | Messaging umum, decouple web request dari proses backend panjang, request-reply, load balancing | High volume, stream processing skala besar (log processing, big data analytics, event sourcing) | Embedded device dan IoT, low-bandwidth/low-power |
| Replikasi/HA | Clustering: queue di-mirror antar node (ha-mode), exchange dan binding ada di semua node | Replikasi per partisi (leader-follower) | Tidak spesifik |
| Contoh | Ticketing: pencarian harga tiket dari frontend ke backend via RabbitMQ | Log processing, call data record telecom, input Hadoop/Spark, event sourcing | Sensor IoT, telemetry, embedded |
RabbitMQ clustering: semua node mereplikasi data/state yang diperlukan broker; client bisa terhubung ke node mana pun (equal peer); exchange dan binding ada di setiap node, tetapi queue hanya di node tempat di-declare; queue bisa di-mirror lewat policy ha-mode; tiap queue punya master replika di satu node (operasi dikirim ke master dulu; lokasinya: node dengan bound master terkecil, node tempat client men-declare, atau acak). Beda dengan Kafka: RabbitMQ mereplikasi di level queue (mirroring), Kafka di level partisi topic.
2.12 Pattern Microservices dan Praktik Netflix
Sumber: 07_Microservices_Architecture (bagian pattern dan studi kasus; memakai 2.9, 2.10, 2.11)
Klasifikasi pattern: decomposition, composition, database, observability, cross-cutting concern, serta additional database architecture dan deployment patterns.
Decomposition patterns:
- By functional capability: saat mendesain atomic service untuk aplikasi baru; tiap service dipetakan ke satu kapabilitas fungsional bisnis.
- By sub-domain / DDD: untuk common functional services lintas sub-domain; memakai bounded context dari DDD.
- Strangler pattern: merefactor aplikasi legacy besar; fitur baru dibangun sebagai microservice yang berangsur “mencekik” fungsi lama pada monolith sampai bisa dipensiunkan, tanpa big-bang rewrite.

Composition patterns: (i) Aggregator (komponen memanggil beberapa service dan basis datanya lalu menggabungkan hasil); (ii) Proxy (controlled access ke microservice tertentu); (iii) Chained (service dipanggil berurutan, output jadi input berikutnya; contoh Travel plan → Flight → Hotel → Cab booking); (iv) Branch (kombinasi aggregator dan chained, beberapa cabang rantai paralel); (v) Shared resource (beberapa service berbagi resource, mis. shared library/DB); (vi) API Gateway pattern (single entry point dengan: single entry point, routing, load balancing, service discovery, protocol conversion, data format conversion, security implementation, orchestration, data aggregation, proxy; lihat 2.10); (vii) Client-side UI composition (tiap tim punya UI sendiri/fragmen UI dikomposisikan di client; komunikasi antar service asynchronous, mayoritas resource-based REST API, database tidak dibagi, memakai Event Driven Architecture, teknologi bebas, UI harus resilient terhadap service gagal).

Database patterns: Database per service (ideal, hindari tight coupling lewat shared schema) dan Shared database per service (kompromi, mengorbankan sebagian independensi).
CQRS (Command Query Responsibility Segregation): memisahkan jalur command (write) dan query (read) ke dua model/database. Client kirim Command → tulis ke Write DB → perubahan disebarkan lewat event architecture → update Read DB → Client baca lewat Query dari Read DB. Sisi baca dan tulis bisa di-scale dan dioptimasi independen (read DB didenormalisasi untuk kecepatan, write DB dinormalisasi untuk konsistensi).

Saga pattern: pada database per service, transaksi lintas service sulit (tidak ada distributed transaction/2PC yang murah). Saga menjalankan transaksi per service dan menyediakan compensating transaction bila satu langkah gagal. Contoh order processing:
| Service | Deskripsi | Local Transaction | Compensating Transaction |
|---|---|---|---|
| Order | Customer membuat order | T1: buat entry di order table | C1: hapus entry order |
| Payment | Menerima pembayaran | T2: terima pembayaran dan buat entry payment | C2: kembalikan pembayaran dan hapus entry payment |
| Check availability | Cek stok | T3: cek status (available / out of stock / not in production) | C3: bila tidak diproduksi, hapus item dari catalog table |
| Shipment | Mengirim barang | T4: kirim dan buat entry shipment | C4: hapus record shipment |
Bila T1 sampai T4 berhasil, Saga sukses; bila salah satu gagal (mis. T3 stok habis), compensating transaction dijalankan mundur (C2 lalu C1, dan memberi tahu customer).

| Aspek | Events / Choreography | Command / Orchestration |
|---|---|---|
| Koordinasi | Tanpa koordinator pusat | Satu coordinator service terpusat |
| Cara kerja | Tiap service memproduksi dan mendengarkan event service lain, memutuskan sendiri aksi | Coordinator memusatkan keputusan Saga dan mengurutkan business logic |
| Trade-off | Lebih loosely coupled (via event) | Alur lebih mudah dipahami karena terpusat, tapi coordinator jadi titik ketergantungan |
Observability patterns: (i) Centralized logging (stack: Logstash collect/transform → Elasticsearch search/analyze → Kibana visualize); (ii) Application performance metrics (latency, throughput, error rate); (iii) Distributed tracing (jejak satu request lintas service, trace ID dipropagasi); (iv) Health check (endpoint status up/down/degraded).
Cross-cutting concern patterns: (i) External configuration store (konfigurasi di luar kode, ubah tanpa redeploy); (ii) Service registry (direktori host/port instance aktif); (iii) Circuit breaker (cegah cascading failure: pantau tingkat kegagalan pemanggilan, bila melewati ambang “circuit” dibuka sehingga pemanggilan berikutnya langsung gagal cepat atau ke fallback tanpa membebani service bermasalah); (iv) Blue-green deployment (dua environment identik, blue lama live dan green baru; traffic dialihkan penuh setelah green sehat; minim downtime dan rollback mudah).

Arsitektur Netflix setelah microservices: Account, Catalog, Recommendation, Customer Service, masing-masing dengan database sendiri (Catalog DB, Customer DB), diakses lewat API Gateway di belakang Load Balancer.

Service dependency graph: App memanggil Service X, Y, Z yang memanggil service lain lagi (L, M), membentuk graf dependency kompleks; karenanya service dependency visualization penting.
Service discovery: dengan ratusan service dibutuhkan Service Metadata Registry (Discovery Service); service mendaftar dan mencari lokasi service lain lewat registry, bukan alamat hardcoded. Contoh: Netflix Eureka.
Chattiness dan fan-out: pada monolith 1 request = 1 pemrosesan internal; pada microservices 1 request di edge fan out ke banyak request downstream. Skala Netflix: ~2 miliar request/hari di Edge Service menghasilkan ~20 miliar fan-out request ke ~100 microservices. Risiko: latency menumpuk; satu dependency lambat memblokir banyak thread (“Service Hosed”: semua thread request terblokir menunggu satu dependency lambat pada beban 50+ request/detik).

Isolasi dan load balancing: isolasi akses antar microservices (mis. Security Groups di AWS), jangan asumsikan saling percaya. Pilihan load balancer: central (proxy) (satu LB terpusat, biasanya per jenis service, diakses via API Gateway), client-side (logic LB di sisi caller, tanpa hop tambahan), client-based smart (memperhitungkan kondisi real-time: outstanding request, instance “tripped”/circuit-open, zona bermasalah; contoh Ribbon menghitung average active requests dan menghindari instance tripped atau zona dropped). Tip: gunakan client-side smart load balancer karena lebih adaptif terhadap kegagalan instance dibanding LB terpusat yang statis.
Dependency resiliency:
- Guard your dependency calls: isolasi tiap pemanggilan (pola Hystrix: tiap dependency lewat Command dengan thread pool sendiri dan timeout; bila pool/queue penuh, request gagal cepat atau memakai fallback).
- Cache dependency call results: server caching (hasil Service X/Y/Z di cache cluster; atur TTL sesuai toleransi data staleness) dan composite (materialized view) caching (hasil gabungan Fn{A,B,C} disimpan sebagai satu entri).
- Batching beberapa panggilan kecil jadi satu batch (kurangi round-trip).
- Async/ReactiveX (RxJava/RxNetty) agar thread tidak diblokir menunggu I/O.
- Bottleneck/hotspot: service “hub” (mis. User Account Service) dipanggil berulang (misalnya 4 kali per request). Solusi: teruskan data lewat HTTP header (mis.
Usr=XX; AbCell=103) sepanjang rantai pemanggilan agar downstream tidak memanggil ulang hub. - Test resiliency: latency/error tests, dependency service unavailability, network errors. Contoh tool: Simian Army (Netflix OSS, chaos engineering).
Tools deployment: Auto scaling (AWS Auto Scaling Groups berdasarkan RPS atau CPU/Load Average via CloudWatch); Canary release dan Red/Black (Blue-Green) push (versi baru tidak menerima trafik live dulu, divalidasi, baru trafik dialihkan penuh; contoh NetflixOSS Asgard); service dependency visualization (menjawab: berapa banyak dependency, call volume, dependency “running hot”, top N slowest business transactions, sample request/response yang menghasilkan error 5xx dalam 30 menit terakhir).
Polyglot dan Sidecar pattern: karena tiap tim bebas memilih bahasa (Java, Python/Django, Node.js, Ruby on Rails, Go, R), muncul tantangan homogenitas pada Platform Services (registry, config, metrics). Sidecar pattern: komponen infrastruktur berdampingan dengan aplikasi utama (biasanya non-JVM), memberi akses homogen ke platform services lewat HTTP tanpa implementasi ulang per bahasa. Contoh Prana (Netflix OSS) menjembatani ke Archaius (persisted properties), Suro, dan Eureka lewat plugin (Archaius, Proxy, Suro, Eureka Plugin).

IPC stack Netflix: 1.0 arsitektur blocking (Apache HTTP Client, Ribbon untuk LB dan integrasi Eureka, Hystrix, EVCache, server Apache Tomcat/Karyon). 2.0 fully reactive (Ribbon 2.0 dan Karyon di atas RxNetty: Reactive Extensions + Netty, UDP/TCP/WebSockets/SSE, non-blocking di semua layer); benchmark: RxNetty throughput (req/sec) lebih tinggi dibanding Tomcat NIO pada skenario “Hello Netflix” dengan dependency call, trade-off CPU/request dan max latency perlu dievaluasi.
NetflixOSS: Eureka (service registry/discovery), Karyon (server reactive atau threaded/servlet), Ribbon (IPC client + fault tolerant smart LB), Hystrix (fault tolerance, circuit breaker, thread pool isolation, fallback), Archaius (dynamic properties), Servo (metrics), EVCache (distributed cache), Curator/Exhibitor (operasi Zookeeper).
Ringkasan microservices: kumpulan tren, pattern, dan praktik (bukan satu teknologi); menambah kompleksitas demi kesederhanaan di level lain; bukan silver bullet (cocok untuk aplikasi bisnis modern yang butuh skala dan kecepatan delivery tinggi, monolith masih cocok untuk organisasi kecil); sebuah perjalanan (journey), adopsi saat organisasi cukup besar/kompleks, manfaatkan best practice dan platform cloud elastis.
3. Sengaja Tidak Dicakup (Rinci di Note Sumber)
Bagian ini hanya berisi contoh kode panjang dan detail sangat teknis yang tidak diulang di sini. Konsepnya sudah dijelaskan di bagian 2, dan kodenya bisa dibaca di note sumber:
| Yang dilewati | Ada di |
|---|---|
Kode C fork/pthread_create lengkap (1p1c, prefork, prethread) | 02_Proses_Server_Architecture |
Kode contoh select, kqueue (timer 5 detik, client interaktif), dan pola epoll | 02_Proses_Server_Architecture |
Kode libev lengkap (ev_io stdin + ev_timer) dan kode asyncio lengkap (run_until_complete, run_in_executor) | 03_Asynchronous_Programming |
| Contoh request-response REST lengkap, JSON/XML lengkap, flow OAuth berurutan, contoh JWT ter-encode | 04_RPC_Fundamentals_API |
| Kode GraphQL resolver (JavaScript) dan contoh query/response Star Wars | 05_RPC_Serialization_GraphQL_Thrift_Protobuf |
Kode Thrift (IDL, handler, server, client Java), contoh .proto lengkap, kode builder Protobuf | 05_RPC_Serialization_GraphQL_Thrift_Protobuf |
Kode JMS (lookup JNDI, session, sender, receiver, listener) dan kode RabbitMQ (Send, Recv, EmitLog, ReceiveLogs) | 08_Message_Queue_Publish_Subscribe |
| Kode Producer Kafka (API lama) lengkap | 08_Message_Queue_Publish_Subscribe |
| Slide Figure 2.1 dan 2.2 (diagram AMQP berbentuk teks di note sumber) | 08_Message_Queue_Publish_Subscribe |
4. Peta Pembahasan
| Note sumber | Topik | Bagian di file ini |
|---|---|---|
| 01 | Pengertian, sumber daya, lima aspek, leaky abstraction, FLP, scalability, resiliency, operations | 2.1 |
| 01 | Anatomi, API direct/indirect, infrastruktur komunikasi, middleware, jenis aplikasi, monolith vs microservice (pengantar) | 2.2 |
| 01 | Stateless vs stateful, chess.com | 2.3 |
| 01 | Load balancer, NAT vs reverse proxy, DNS, CDN, Anycast, local vs global | 2.4 |
| 02 | C10K, strategi client, 5 model I/O, select/poll/kqueue/epoll, thread vs event, Apache, Nginx | 2.5 |
| 03 | Event loop, libev/libuv, asyncio, coroutine | 2.6 |
| 04 | API, REST, HTTP methods, idempotence, serialisasi, autentikasi, JWT, RPC | 2.7 |
| 05 | GraphQL, Thrift, Protobuf, gRPC, perbandingan | 2.8 |
| 06 | API Gateway, AWS, Traefik, Service Mesh, control/data plane, sidecar | 2.10 |
| 07 | Monolith, definisi, trade-off, 12 factor | 2.9 |
| 07 | Pattern, Saga, CQRS, Netflix, resiliency, sidecar | 2.12 |
| 08 | Messaging, PTP, pub/sub, JMS, AMQP/RabbitMQ, Kafka, MQTT, perbandingan | 2.11 |