PHP Academy · Ders

Dayanıklılık: Devre Kesiciler ve Yeniden Denemeler

Kısmi arızalar sırasında sistemleri sağlıklı tutun.

4. ders / 413 adım

Dayanıklılık: Devre Kesiciler ve Yeniden Denemeler, CoddyKit'te ücretsiz bir PHP Academy dersidir. Bu, 4 dersinin 4. dersidir. Aşağıdan dersin tamamını ücretsiz okuyabilir, sonra tarayıcıda yerleşik kod editörü ve 7/24 yapay zeka koçu ile uygulamalı olarak pratik yapabilirsin. Bu, PHP Academy öğrenme yolunun bir parçasıdır ve ilerlemeniz web ve CoddyKit uygulaması arasında senkronize olur. PHP Academy kursu toplamda 4 dersten oluşur.

Dayanıklılık Kalıpları

Dağıtık bir sistemde kısmi arıza olağan durumdur; bazı bağımlılıklar her zaman yavaşlar, yeniden başlar veya aşırı yüklenir. Dayanıklılık, sorunlu tek bir bağımlılığın hizmetinizi ve ardından tüm sistemi beraberinde çökertmemesi için her hizmeti tasarlamaktır.

Bu derste temel araç setini PHP ile ele alacağız: zaman aşımları, beklemeli yeniden denemeler, devre kesiciler, kaynak yalıtımı ve kontrollü işlev azaltma.

Önce Zaman Aşımları

Dayanıklılık açısından en önemli tek ayar zaman aşımıdır. Zaman aşımı olmazsa yavaş bir alt hizmet PHP-FPM çalışanlarınızı beklemeye kilitler; istekler birikir, çalışanlarınız tükenir ve hizmetiniz, başka birinin yavaş olması yüzünden çöker. Bu, ders kitaplarına girecek türden bir zincirleme arızadır.

Her dış çağrıda hem bağlantı zaman aşımı hem de toplam istek zaman aşımı ayarlayın. Her zaman.

<?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.

Yeniden Denemeler — Dikkatle

Geçici arızalar (kısa bir kesinti, kısa süreli bir ağ kopması veya 503) çoğu zaman ikinci denemede başarılı olur. Ancak yeniden denemeler tehlikelidir: çok istekli biçimde yeniden denerseniz, zaten zorlanan bir hizmet üzerindeki yükü artırırsınız. Kurallar:

  • Yalnızca aynı sonucu veren işlemleri ve yeniden denenebilir hataları (zaman aşımları, 5xx, 429) yeniden deneyin.
  • Deneme sayısını sınırlandırın.
  • 4xx istemci hatalarını asla yeniden denemeyin; yine başarısız olurlar.

Üstel Bekleme ve Rastgele Sapma

Birçok istemcinin sabit aralıklarla yaptığı yeniden denemeler, iyileşmekte olan hizmete dalgalar hâlinde yüklenen bir toplu hücuma dönüşür. Çözüm, yükü yaymak için üstel beklemeyi (her denemede gecikmeyi iki katına çıkarmayı) ve rastgele sapmayı bir arada kullanmaktır.

<?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));
}

Yeniden Deneme Döngüsü

Parçaları bir araya getirelim: sınırlandırılmış denemeler, yalnızca yeniden denenebilir hatalarda yeniden deneme, denemeler arasında rastgele sapmalı bekleme ve tüm denemeler başarısız olursa son hatayı üst katmana iletme.

<?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); }

Devre Kesici

Yeniden denemeler kısa süreli kesintilere yardımcı olur; ancak bir bağımlılık gerçekten devre dışıysa, her isteği yeniden denemek yalnızca zaman ve kaynak israf eder. Bir devre kesici hataları izler ve hatalar bir eşiği aştığında açılır; çağrıları kısa devre yaparak çalışmayan bir hizmeti beklemek yerine anında başarısız olur.

Üç durumu vardır: Kapalı (çağrılar geçer, hatalar sayılır), Açık (çağrılar hemen reddedilir) ve Yarı Açık (iyileşmeyi sınamak için birkaç deneme çağrısı yapılır).

Devre Kesici Durum Makinesi

Geçişler şöyledir: Hatalar eşiği aştığında Kapalı → Açık. Soğuma süresinden sonra Açık → Yarı Açık. Başarılı bir sınama sonucunda Yarı Açık → Kapalı; başarısızlıkta yeniden Açık. Durum PHP süreçleri arasında paylaşılmalıdır (Redis/APCu); çünkü her istek yeni bir süreçtir.

<?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;
        }
    }
}

Kaynak Yalıtımı

Adını gemi bölmelerinden alan bölme yalıtımı kalıbı, bir alandaki arızanın tüm gemiyi batırmaması için kaynakları birbirinden ayırır. Tüm çalışanlarınız yavaş Reports hizmetini çağırabiliyorsa, Reports hizmetindeki bir arıza her çalışanı tüketip Checkout'un kaynaksız kalmasına neden olabilir.

Kaynakları bölümlere ayırın: her bağımlılık için ayrı bağlantı havuzları, ayrı çalışan havuzları veya kuyrukları ya da her alt hizmet için eşzamanlılık sınırları kullanın. Böylece başarısız olan tek bir bağımlılık yalnızca kendisine ayrılan bölümü tüketir.

Kontrollü İşlev Azaltma ve Yedek Yollar

Kritik olmayan bir bağımlılık kullanılamadığında hata vermek yerine işlevi azaltın. Önbelleğe alınmış bir değer, varsayılan bir değer veya azaltılmış bir deneyim sunun. Devre kesicinin açık durumu, yedek yol için doğal tetikleyicidir.

<?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'];
    }
}

Güvenli Yeniden Denemeler için İdempotensi Anahtarları

Yeniden denemeler yalnızca aynı sonucu veren işlemler için güvenlidir. "Karttan ücret çekme" gibi aynı sonucu vermeyen bir işlem için sunucunun yinelenenleri ayıklamak üzere kullandığı bir idempotensi anahtarı ekleyin: İlk deneme zaten başarılı olmuş ancak yanıt kaybolmuşsa ve yeniden deneme ulaşırsa sunucu karttan iki kez ücret çekmek yerine özgün sonucu döndürür.

<?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 scene

Hepsini Bir Araya Getirme

Kalıplar birleştirilebilir ve sıralama önemlidir. Sağlam bir dış çağrı genellikle şu şekilde iç içe yerleştirilir:

  • Her bir denemede zaman aşımı (en içte).
  • Geçici kesintiler için zaman aşımı uygulanan çağrıyı saran beklemeli yeniden deneme.
  • Süregelen bir arızada hızlıca devreye girmesi için yeniden denemeyi saran devre kesici.
  • Bu bağımlılığın tüketebileceği kapasiteyi sınırlayan kaynak yalıtımı.
  • Yukarı doğru iletilen her şeyi yakalayan en dıştaki yedek yol.

Resilience4PHP tarzı sarmalayıcılar gibi kütüphaneler vardır; ancak katmanlamayı anlamak, belirli bir paketi bilmekten daha önemlidir.

Hızlı Denetim

Doğru kalıbı seçme.

Özet

Kısmi arızalardan sağ çıkma:

  • Her çağrıdaki zaman aşımları, çalışanların tükenmesini ve zincirleme arızaları önler.
  • Yeniden denemeler yalnızca aynı sonucu veren işlemler ve yeniden denenebilir hatalar için, üstel bekleme ve rastgele sapma ile kullanılmalıdır.
  • Bir bağımlılık çalışmadığında devre kesiciler hızlıca başarısız olur (Kapalı → Açık → Yarı Açık).
  • Kaynak yalıtımı, tek bir arızanın tüm kaynakları tüketmesini önlemek için kaynakları birbirinden ayırır.
  • Kontrollü işlev azaltma ve yedek yollar, temel akışların çalışmaya devam etmesini sağlar.

Birlikte katmanlandıklarında bu yaklaşımlar, kaçınılmaz arızaları sınırlandırılmış ve kurtarılabilir olaylara dönüştürür.

Başlamak ücretsiz

Yapay zeka eğitmeniyle PHP öğren — ücretsiz

Tarayıcında gerçek kod yaz ve çalıştır, 7/24 yapay zeka eğitmeninden anında yardım al; web'de ya da uygulamada kaldığın yerden devam et.

Kurslar
49
Dersler
195

Sıkça Sorulan Sorular

“Dayanıklılık: Devre Kesiciler ve Yeniden Denemeler” dersi ücretsiz mi?

Evet — “Dayanıklılık: Devre Kesiciler ve Yeniden Denemeler” dersin tüm metni burada web'de ücretsiz olarak okunabilir. Etkileşimli olarak pratik yapmak (yerleşik kod editörü ve 7/24 yapay zeka koçu) ve PHP Academy kursunun geri kalanını açmak için CoddyKit PRO'ya yükselt. PHP Academy kursu toplamda 4 dersten oluşur.

“Dayanıklılık: Devre Kesiciler ve Yeniden Denemeler” dersinde ne öğreneceğim?

Kısmi arızalar sırasında sistemleri sağlıklı tutun. PHP Academy ile uygulamalı kodu tarayıcıda doğrudan çalıştırarak pratik yaparsın ve 7/24 yapay zeka koçu dersi çalışırken sorularını yanıtlar.

PHP Academy öğrenmeye başlamak için deneyim gerekli mi?

Önceden deneyim gerekmez. CoddyKit'te PHP Academy, başlangıçtan ileri seviyeye kadar yapılandırıldığı için buradan başlayabilir veya başından başlayıp kendi hızında ilerleme yapabilirsin. Bu, 4 dersinin 4. dersidir.

“Dayanıklılık: Devre Kesiciler ve Yeniden Denemeler” dersi ne kadar sürer?

Çoğu CoddyKit dersi yaklaşık 5–10 dakika sürer. Her biri kısa ve etkileşimli olduğu için sabit ilerleme yaparsın ve web ile uygulama arasında tam olarak bıraktığın yerden devam edebilirsin.

Bu PHP Academy dersinde kod yazıp çalıştırabilir miyim?

Evet. Her PHP Academy dersi yerleşik bir kod editörü içerir, bu sayede tarayıcıda gerçek kod yazıp çalıştırabilir ve anlık yapay zeka geri bildirimi alırsın — yerel kurulum gerekli değildir.

Bu kursun tüm dersleri

  1. Monolitten Mikro Hizmetlere
  2. Hizmet İletişimi: REST ve gRPC
  3. API Ağ Geçitleri ve Hizmet Keşfi
  4. Dayanıklılık: Devre Kesiciler ve Yeniden Denemeler
← PHP Academy Sayfasına Dön