Ketahanan: Pemutus Sirkuit dan Percobaan Ulang
Jaga sistem tetap sehat saat terjadi kegagalan sebagian.
Ketahanan: Pemutus Sirkuit dan Percobaan Ulang adalah pelajaran PHP Academy gratis di CoddyKit. Ini adalah pelajaran 4 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.
Pola Ketahanan
Dalam sistem terdistribusi, kegagalan sebagian adalah keadaan normal—beberapa dependensi selalu lambat, sedang dimulai ulang, atau kelebihan beban. Ketahanan berarti merancang setiap layanan agar satu dependensi yang bermasalah tidak ikut menjatuhkan layanan Anda, lalu seluruh sistem.
Pelajaran ini membahas perangkat inti: batas waktu, percobaan ulang dengan penundaan, pemutus sirkuit, sekat, dan degradasi anggun—semuanya dari PHP.
Dahulukan Batas Waktu
Pengaturan ketahanan yang paling penting adalah batas waktu. Tanpanya, layanan di belakang yang lambat akan menahan pekerja PHP-FPM Anda dalam keadaan menunggu; permintaan menumpuk; Anda kehabisan pekerja; layanan Anda mati karena pihak lain lambat. Inilah contoh klasik kegagalan berantai.
Tetapkan batas waktu koneksi dan batas waktu total permintaan pada setiap panggilan keluar. Selalu.
<?php
require 'vendor/autoload.php';
use GuzzleHttp\Client;
$http = new Client([
'connect_timeout' => 0.5, // fail fast if we can't even connect
'timeout' => 2.0, // hard cap on the whole call
]);
// A hung dependency now fails in 2s instead of holding a worker forever.Percobaan Ulang dengan Hati-hati
Kegagalan sementara (gangguan singkat, koneksi jaringan terputus sebentar, atau 503) sering kali berhasil pada percobaan kedua. Namun, percobaan ulang berbahaya: jika Anda mengulang terlalu cepat, Anda memperparah beban pada layanan yang sudah kesulitan. Aturannya:
- Hanya ulangi operasi idempoten dan kesalahan yang dapat dicoba ulang (batas waktu, 5xx, 429).
- Batasi jumlah percobaan.
- Jangan pernah mengulangi kesalahan klien 4xx—kesalahan itu hanya akan gagal lagi.
Penundaan Eksponensial + Pengacakan
Percobaan ulang dengan interval tetap dari banyak klien akan tersinkronisasi menjadi kawanan yang menggelegar dan membombardir layanan yang sedang pulih secara bergelombang. Solusinya adalah penundaan eksponensial (menggandakan jeda pada setiap percobaan) ditambah pengacakan untuk menyebarkan beban.
<?php
function backoffDelay(int $attempt, float $base = 0.1, float $cap = 5.0): float {
$exp = min($cap, $base * (2 ** $attempt)); // 0.1, 0.2, 0.4, ...
return mt_rand(0, (int)($exp * 1000)) / 1000; // full jitter: 0..exp
}
for ($i = 0; $i < 5; $i++) {
printf("attempt %d -> wait %.3fs\n", $i, backoffDelay($i));
}Perulangan Percobaan Ulang
Menggabungkan semua bagian: jumlah percobaan yang dibatasi, hanya mengulangi kesalahan yang dapat dicoba ulang, tidur dengan penundaan yang diacak di antara percobaan, dan meneruskan kegagalan terakhir jika semua percobaan gagal.
<?php
function withRetry(callable $op, int $maxAttempts = 4): mixed {
$attempt = 0;
while (true) {
try {
return $op();
} catch (\Throwable $e) {
$attempt++;
if ($attempt >= $maxAttempts || !isRetryable($e)) {
throw $e; // give up
}
usleep((int)(backoffDelay($attempt) * 1_000_000));
}
}
}
function isRetryable(\Throwable $e): bool { return $e->getCode() === 0 || $e->getCode() >= 500; }
function backoffDelay(int $a): float { return min(5.0, 0.1 * (2 ** $a)) * (mt_rand(0, 100) / 100); }Pemutus Sirkuit
Percobaan ulang membantu mengatasi gangguan singkat, tetapi jika dependensi benar-benar mati, mengulangi setiap permintaan hanya membuang waktu dan sumber daya. Pemutus sirkuit melacak kegagalan dan, setelah jumlahnya melampaui ambang, menjadi terbuka—memintas panggilan dan langsung gagal alih-alih menunggu layanan yang mati.
Pemutus ini memiliki tiga status: Tertutup (panggilan berjalan dan kegagalan dihitung), Terbuka (panggilan langsung ditolak), dan Setengah Terbuka (beberapa panggilan percobaan menguji pemulihan).
Mesin Status Pemutus
Transisinya: Tertutup → Terbuka saat kegagalan melewati ambang. Terbuka → Setengah Terbuka setelah masa pendinginan. Setengah Terbuka → Tertutup setelah pemeriksaan berhasil, atau kembali ke Terbuka jika gagal. Status harus dibagikan ke seluruh proses PHP (Redis/APCu), karena setiap permintaan menggunakan proses baru.
<?php
final class CircuitBreaker {
public function __construct(
private int $threshold = 5,
private int $coolDown = 30, // seconds
) {}
public function call(callable $op, array &$state): mixed {
if ($state['status'] === 'open') {
if (time() - $state['openedAt'] < $this->coolDown) {
throw new \RuntimeException('Circuit open - failing fast');
}
$state['status'] = 'half-open'; // time to probe
}
try {
$result = $op();
$state = ['status' => 'closed', 'failures' => 0]; // recovered
return $result;
} catch (\Throwable $e) {
$state['failures'] = ($state['failures'] ?? 0) + 1;
if ($state['failures'] >= $this->threshold || $state['status'] === 'half-open') {
$state['status'] = 'open';
$state['openedAt'] = time();
}
throw $e;
}
}
}Sekat
Dinamai berdasarkan kompartemen kapal, pola sekat mengisolasi sumber daya agar kegagalan di satu area tidak menenggelamkan seluruh kapal. Jika semua pekerja Anda dapat memanggil layanan Reports yang lambat, gangguan pada Reports dapat menghabiskan semua pekerja dan membuat Checkout kekurangan sumber daya.
Partisikan sumber daya—pisahkan kumpulan koneksi, kumpulan pekerja atau antrean untuk setiap dependensi, atau batasi konkurensi untuk setiap layanan hilir—agar satu dependensi yang gagal hanya menghabiskan bagian yang diperuntukkan baginya.
Degradasi Anggun & Jalur Cadangan
Saat dependensi yang tidak kritis tidak tersedia, kurangi fungsionalitas alih-alih menghasilkan kesalahan. Sajikan nilai dari tembolok, nilai bawaan, atau pengalaman yang lebih sederhana. Status terbuka pemutus sirkuit adalah pemicu alami untuk jalur cadangan.
<?php
function getRecommendations(callable $remoteCall, Redis $cache, string $userId): array {
try {
$recs = $remoteCall($userId);
$cache->setex("recs:$userId", 3600, json_encode($recs));
return $recs;
} catch (\Throwable $e) {
// Fallback 1: last-known-good from cache
if ($cached = $cache->get("recs:$userId")) {
return json_decode($cached, true);
}
// Fallback 2: generic popular items - never block the page
return ['popular-1', 'popular-2'];
}
}Kunci Idempotensi untuk Percobaan Ulang yang Aman
Percobaan ulang hanya aman untuk operasi idempoten. Untuk tindakan yang tidak idempoten seperti "menagih kartu", sertakan kunci idempotensi yang digunakan server untuk menghapus duplikasi: jika percobaan ulang tiba setelah percobaan pertama sudah berhasil (tetapi responsnya hilang), server mengembalikan hasil asli alih-alih menagih dua kali.
<?php
function chargeWithRetry(callable $http, string $orderId, int $cents): array {
// Same key across all retries of THIS logical charge
$key = 'charge-' . $orderId;
return withRetry(fn() => $http('POST', '/charges', [
'headers' => ['Idempotency-Key' => $key],
'json' => ['order' => $orderId, 'amount' => $cents],
]));
}
function withRetry(callable $op) { return $op(); } // see earlier sceneMenggabungkan Semuanya
Pola-pola ini dapat disusun, dan urutannya penting. Panggilan keluar yang tangguh biasanya bersarang seperti ini:
- Batas waktu pada setiap percobaan individual (lapisan terdalam).
- Percobaan ulang dengan penundaan yang membungkus panggilan berbatas waktu untuk mengatasi gangguan sementara.
- Pemutus sirkuit yang membungkus percobaan ulang agar gangguan berkelanjutan segera memicunya.
- Sekat yang membatasi kapasitas yang dapat digunakan dependensi ini.
- Jalur cadangan di lapisan terluar, yang menangkap apa pun yang diteruskan ke atas.
Pustaka seperti pembungkus bergaya Resilience4PHP tersedia, tetapi memahami pelapisan ini lebih penting daripada paket tertentu mana pun.
Pemeriksaan Singkat
Memilih pola yang tepat.
Ringkasan
Bertahan dari kegagalan sebagian:
- Batas waktu pada setiap panggilan mencegah kehabisan pekerja dan kegagalan berantai.
- Percobaan ulang hanya untuk operasi idempoten dan kesalahan yang dapat dicoba ulang, dengan penundaan eksponensial + pengacakan.
- Pemutus sirkuit gagal dengan cepat (Tertutup → Terbuka → Setengah Terbuka) saat dependensi mati.
- Sekat mengisolasi sumber daya agar satu kegagalan tidak membuat semuanya kekurangan sumber daya.
- Degradasi anggun / jalur cadangan menjaga alur inti tetap berjalan.
Jika dilapiskan, semua pola ini mengubah kegagalan yang tak terhindarkan menjadi kejadian yang terkendali dan dapat dipulihkan.
Belajar PHP dengan tutor AI — gratis
Tulis dan jalankan kode asli di browser kamu, dapatkan bantuan instan dari tutor AI 24/7, dan lanjutkan di mana kamu tinggalkan di web atau aplikasi.
- Kursus
- 49
- Pelajaran
- 195
Pertanyaan yang Sering Diajukan
Apakah pelajaran “Ketahanan: Pemutus Sirkuit dan Percobaan Ulang” gratis?
Ya — teks lengkap “Ketahanan: Pemutus Sirkuit dan Percobaan Ulang” 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 “Ketahanan: Pemutus Sirkuit dan Percobaan Ulang”?
Jaga sistem tetap sehat saat terjadi kegagalan sebagian. 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 4 dari 4.
Berapa lama pelajaran “Ketahanan: Pemutus Sirkuit dan Percobaan Ulang” 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
- Dari Monolit ke Layanan Mikro
- Komunikasi Layanan: REST dan gRPC
- Gerbang API dan Penemuan Layanan
- Ketahanan: Pemutus Sirkuit dan Percobaan Ulang