0Pricing
PHP Academy · Pelajaran

Dari Monolit ke Layanan Mikro

Tentukan apa yang perlu dipisahkan dan cara menetapkan batas layanan.

Dari Monolit ke Layanan Mikro adalah pelajaran PHP Academy gratis di CoddyKit. Ini adalah pelajaran 1 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar PHP Academy, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus PHP Academy mencakup 4 pelajaran total.

Dari Monolit ke Layanan Mikro

Layanan mikro merupakan pilihan organisasi dan operasional, bukan pilihan bawaan. Memisahkan monolit PHP berarti menukar kesederhanaan dalam proses dengan panggilan jaringan, data terdistribusi, dan kompleksitas penerapan. Jika dilakukan karena alasan yang keliru, semuanya justru menjadi lebih lambat.

Pelajaran ini membahas bagian tersulitnya: menentukan batas layanan. Jika batasnya tepat, sisanya hanyalah pekerjaan teknis; jika keliru, Anda akan membangun monolit terdistribusi — menanggung semua biayanya tanpa memperoleh manfaatnya.

Mengapa (dan Mengapa Tidak) Memisahkan

Alasan yang baik untuk memisahkan:

  • Kemampuan penerapan secara mandiri dan kepemilikan oleh tim.
  • Penskalaan subsistem yang sibuk secara mandiri.
  • Isolasi teknologi dan lingkungan eksekusi serta pembatasan dampak kegagalan.

Alasan yang buruk: "kodenya berantakan" (refaktor monolit terlebih dahulu), atau sekadar mengikuti tren. Jika dua layanan harus selalu diterapkan bersama atau berbagi tabel basis data, keduanya sebenarnya satu layanan yang menjalankan dua peran.

Konteks Berbatas

Domain-Driven Design menyediakan alat paling tepat untuk menentukan batas: konteks berbatas. Di dalam satu konteks, istilah memiliki satu makna yang tepat. "Pelanggan" dalam Penagihan (pihak yang ditagih) berbeda dari "Pelanggan" dalam Dukungan (penulis tiket).

Setiap konteks berbatas merupakan kandidat kuat untuk dijadikan layanan. Batas mengikuti bahasa bisnis dan cara organisasi berkomunikasi secara nyata — inilah Conway's Law dalam praktik.

Kohesi Tinggi, Keterikatan Rendah

Batas layanan yang baik mempertahankan hal-hal yang berubah bersama di dalamnya, dan mengeluarkan hal-hal yang berubah secara mandiri. Ukur pemisahan yang diusulkan berdasarkan:

  • Berapa banyak fitur yang mengharuskan Anda menyentuh dua layanan sekaligus? (Sebaiknya sedikit.)
  • Seberapa banyak percakapan dalam pola pemanggilan di antara keduanya? (Sebaiknya berbutir kasar.)

Jika penerapan satu fitur terus-menerus melintasi suatu batas, berarti batas tersebut berada di tempat yang keliru.

<?php
// Chatty boundary smell: N network calls to render one view
foreach ($order->lineItems as $item) {
    $product = $catalogApi->get($item->productId); // one call PER item!
    $names[] = $product['name'];
}

// Coarse-grained: one batch call across the boundary
$ids   = array_map(fn($i) => $i->productId, $order->lineItems);
$names = $catalogApi->getMany($ids); // single round-trip
echo count($names) . " products in one call\n";

Satu Basis Data per Layanan

Aturan yang tidak dapat ditawar: setiap layanan memiliki datanya dan tidak ada layanan lain yang menyentuh tabelnya. Basis data bersama menciptakan kembali keterikatan yang ingin Anda hindari dengan pemisahan — perubahan skema dapat merusak layanan yang tidak terkait.

Artinya, kueri lintas layanan yang sebelumnya berupa SQL JOIN dalam monolit berubah menjadi panggilan API atau model baca yang direplikasi. Itulah biayanya, dan memang itulah tujuannya.

<?php
// In the monolith: one JOIN across domains
$sql = 'SELECT o.id, c.email
        FROM orders o JOIN customers c ON c.id = o.customer_id';

// After split: Orders service holds only the foreign id;
// it asks the Customers service for the rest (or keeps a local read model).
$order = $orderRepo->find($id);          // local
$customer = $customersApi->get($order->customerId); // network call
echo $order->id . ' / ' . $customer->email . "\n";

Pola Ara Pencekik

Jangan pernah menulis ulang monolit sekaligus. Pola ara pencekik mengekstraknya secara bertahap: arahkan sebagian lalu lintas ke layanan baru melalui fasad/proksi, kembangkan layanan tersebut, dan hentikan jalur kode lama hanya setelah jalur baru sepenuhnya mencakup fungsinya.

Proksi terbalik (atau gerbang API) berada di depan dan menentukan, untuk setiap rute, apakah akan mengakses monolit lama atau layanan baru. Migrasi berjalan satu kemampuan pada satu waktu dan selalu siap dirilis.

<?php
// Facade routing: peel off one capability at a time
function route(string $path): string {
    $migrated = ['/invoices', '/invoices/pdf']; // moved to billing-svc
    foreach ($migrated as $prefix) {
        if (str_starts_with($path, $prefix)) {
            return 'http://billing-svc' . $path;
        }
    }
    return 'http://legacy-monolith' . $path; // everything else, for now
}
echo route('/invoices/pdf'), "\n";
echo route('/users/42'), "\n";

Memisahkan Modul

Urutan pemisahan yang pragmatis:

  1. Temukan modul dengan sedikit dependensi masuk dan kepemilikan data yang jelas.
  2. Bungkus panggilan dalam prosesnya di balik sebuah antarmuka terlebih dahulu di dalam monolit.
  3. Pindahkan data yang dimilikinya ke skema/basis datanya sendiri.
  4. Ganti penerapan antarmuka tersebut dengan klien jaringan.
  5. Alihkan lalu lintas melalui fasad; hapus kode lama.

Membungkus antarmuka di dalam monolit terlebih dahulu mengurangi risiko pada tahap jaringan.

<?php
// Step 2: hide the implementation behind a port the monolith calls
interface InvoiceService {
    public function generate(string $orderId): string; // returns invoice id
}

// Today: local class. Tomorrow: HTTP client to billing-svc.
// The monolith's calling code never changes.
final class LocalInvoiceService implements InvoiceService {
    public function generate(string $orderId): string { return 'inv-1'; }
}

Konsistensi Data Terdistribusi

Setelah data dipisahkan, Anda kehilangan transaksi ACID lintas layanan. Terimalah konsistensi eventual: layanan menerbitkan peristiwa tentang datanya sendiri dan layanan lain membangun model baca lokal dari peristiwa tersebut.

Layanan Orders tidak menanyakan Customers pada setiap permintaan — layanan itu menyimpan proyeksi kecil (hanya kolom yang dibutuhkannya), yang diperbarui oleh peristiwa CustomerUpdated. Hal ini menghapus dependensi saat berjalan dan satu lompatan latensi.

<?php
// Orders service keeps a tiny local projection of customer data
function onCustomerUpdated(PDO $db, array $evt): void {
    $db->prepare(
        'INSERT INTO customer_read_model (id, email)
         VALUES (:id, :email)
         ON CONFLICT (id) DO UPDATE SET email = EXCLUDED.email'
    )->execute(['id' => $evt['id'], 'email' => $evt['email']]);
}

Realitas Operasional

Layanan mikro memindahkan kompleksitas dari kode ke operasi. Sebelum memisahkan layanan, Anda memerlukan:

  • Pencatatan terpusat dan pelacakan terdistribusi (ID korelasi di sepanjang setiap lompatan).
  • CI/CD per layanan dan penerapan berversi secara mandiri.
  • Pemeriksaan kesehatan, batas waktu, percobaan ulang, dan pemutus sirkuit pada setiap panggilan.
  • Pengujian kontrak agar penyedia tidak dapat diam-diam merusak konsumen.

Jika tim Anda tidak dapat menjalankan satu layanan dengan baik, menjalankan sepuluh layanan akan sepuluh kali lebih buruk.

Menentukan Ukuran Layanan dengan Tepat

Istilah "mikro" dapat menyesatkan — tentukan ukuran layanan berdasarkan kemampuan bisnis dan kepemilikan tim, bukan berdasarkan jumlah baris kode. Jika terlalu terperinci (layanan nano), satu fitur akan menyebar menjadi banyak panggilan jaringan; jika terlalu besar, Anda kembali memiliki monolit.

Pedoman praktis yang baik: satu layanan seharusnya dapat dimiliki oleh satu tim, diterapkan secara mandiri, dan memenuhi kasus penggunaan intinya tanpa rantai sinkron melalui banyak layanan lain.

Alternatif Monolit Modular

Sebelum beralih ke sistem terdistribusi, pertimbangkan monolit modular: satu unit yang dapat diterapkan, tetapi secara internal terbagi menjadi modul-modul dengan batas yang jelas dan skemanya sendiri, yang berkomunikasi hanya melalui antarmuka yang diterbitkan — tanpa akses tabel lintas modul.

Anda memperoleh batas yang bersih dan refaktor yang mudah tanpa biaya sistem terdistribusi. Ketika sebuah modul benar-benar memerlukan penskalaan atau kepemilikan mandiri, bentuknya sudah siap dipisahkan melalui pola ara pencekik. Bagi sebagian besar tim, inilah langkah awal yang tepat.

<?php
// Modules talk only through interfaces, never each other's tables.
namespace App\Billing;          // owns billing_* tables
interface BillingFacade {
    public function invoiceForOrder(string $orderId): string;
}

namespace App\Sales;            // owns sales_* tables
final class Checkout {
    public function __construct(private \App\Billing\BillingFacade $billing) {}
    // Sales never SELECTs from billing_* directly - only via the facade.
}

Pemeriksaan Singkat

Mengenali pemisahan yang buruk.

Ringkasan

Menentukan batas layanan dengan baik:

  • Memisahkan layanan untuk kemampuan penerapan, penskalaan, dan kepemilikan — bukan karena kodenya berantakan.
  • Selaraskan batas dengan konteks berbatas; usahakan kohesi tinggi dan keterikatan rendah.
  • Satu basis data per layanan — tanpa tabel bersama; ganti JOIN dengan API atau model baca.
  • Lakukan migrasi secara bertahap dengan pola ara pencekik.
  • Terima konsistensi eventual dan berinvestasilah dalam operasi sebelum memperluas sistem.

Berikutnya: bagaimana layanan-layanan tersebut benar-benar berkomunikasi — REST dan gRPC.

Pertanyaan yang Sering Diajukan

Apakah pelajaran “Dari Monolit ke Layanan Mikro” gratis?

Ya — teks lengkap “Dari Monolit ke Layanan Mikro” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus PHP Academy, upgrade ke CoddyKit PRO. Kursus PHP Academy mencakup 4 pelajaran total.

Apa yang akan aku pelajari di “Dari Monolit ke Layanan Mikro”?

Tentukan apa yang perlu dipisahkan dan cara menetapkan batas layanan. Kamu berlatih PHP Academy dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.

Apakah aku perlu pengalaman untuk memulai PHP Academy?

Tidak diperlukan pengalaman sebelumnya. PHP Academy di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 1 dari 4.

Berapa lama pelajaran “Dari Monolit ke Layanan Mikro” memakan waktu?

Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.

Bisakah aku menulis dan menjalankan kode dalam pelajaran PHP Academy ini?

Ya. Setiap pelajaran PHP Academy menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.

Semua pelajaran dalam kursus ini

  1. Dari Monolit ke Layanan Mikro
  2. Komunikasi Layanan: REST dan gRPC
  3. Gerbang API dan Penemuan Layanan
  4. Ketahanan: Pemutus Sirkuit dan Percobaan Ulang
← Kembali ke PHP Academy