Bloga Dön

Oyun Varlıkları için CDN Ölçekleme: Lansman Günü Trafik Dalgalanmalarını Atlatma Rehberi

Yayınlanma tarihi 4 Ağustos 2026
Oyun Varlıkları için CDN Ölçekleme: Lansman Günü Trafik Dalgalanmalarını Atlatma Rehberi Yapay zekâ yardımıyla oluşturuldu

Özet olarak

Oyun varlıkları için CDN ölçekleme rehberi: lansman günü trafik dalgalanmalarını tespit edin, origin koruması ve stale-while-revalidate ile çözün, çok katmanlı önbellek mimarisiyle önleyin.

CDN'iniz Çökecek — İşte Ne Zaman Olduğunu Nasıl Anlarsınız

Her oyun geliştiricisi aynı lansman günü senaryosundan korkar: Steam sayfanız yayına girer, oyuncu sayısı 10.000 eşzamanlıyı geçer ve aniden doku indirmeleri normal 12ms yerine 200ms p99 gecikmede takılmaya başlar. Oyuncular eksik modeller bildirir. Yama indirmeleri %43'te asılı kalır. İzleme paneliniz kırmızıya döner ve hangi katmanın başarısız olduğu hakkında hiçbir fikriniz yoktur.

Bu varsayımsal bir senaryo değil. cdnjs — gezegendeki en yaygın kullanılan açık kaynak CDN ağlarından biri — günde 9 milyar isteği yönetmek için yakın zamanda Cloudflare'in Developer Platform'una tam bir altyapı geçişi tamamladı. Bu geçiş hikayesi, tek bir 4K doku paketi güncellemesinin dakikalar içinde terabaytlarca trafik üretebildiği oyun varlık dağıtımına doğrudan uygulanabilir mimari desenleri ortaya koyuyor.

Ana ders: oyun varlıkları için CDN ölçekleme daha fazla bant genişliği satın almakla ilgili değildir. Önbellek hiyerarşileri, geri dönüş mantığı ve origin koruması tasarlamakla ilgilidir; böylece trafik dalgalanmaları kesinti yerine sıradan olaylara dönüşür.

Bu rehber, CDN'iniz doygunluğa ulaştığında neyin bozulduğunu, Discord'unuz öfke mesajlarıyla dolmadan doygunluğu nasıl tespit edeceğinizi, üretimde nasıl iyileştirme yapacağınızı ve tekrar oluşmasını önlemek için mimariyi nasıl tasarlayacağınızı kapsar.


CDN Doygunluğa Ulaştığında Ne Bozulur

Oyun varlık dağıtımı, standart web içeriğine kıyasla benzersiz bir trafik profiline sahiptir. Arıza modlarını anlamak, bu profili anlamayı gerektirir.

Trafik Şekli Sorunu

Tipik bir indie multiplayer oyunu şu trafik desenlerini görür:

  • Temel seviye: Lobi varlıkları, UI sprite'ları, konfigürasyon JSON'ları için 50-200 istek/saniye
  • Yama günü dalgalanması: Steam otomatik güncellemeleri tetiklediğinde 3 dakikalık bir pencerede 15.000-80.000 istek/saniye
  • Bölgesel kademeli dalgalar: Asya-Pasifik oyuncuları CDN'e NA'dan 8-12 saat sonra ulaşır ve ikinci bir dalga oluşturur
  • Varlık sürüm patlaması: Her yama önbelleğe alınmış nesneleri geçersiz kılar ve yeni hash'ler için origin çekmelerini zorunlu kılar

cdnjs Cloudflare altyapısına geçtiğinde benzer bir sürüm patlaması sorunuyla karşılaştı. npm tarzı sürümleme, her kütüphane güncellemesinin yeni önbellek anahtarları oluşturduğu anlamına geliyordu ve 4.200+ kütüphane günlük güncellendiğinden, origin koruma tasarımı yalnızca statik içerik değil, sürekli önbellek değişimini de yönetmek zorundaydı.

Üç Arıza Modu

1. Origin Çekme Doygunluğu

Edge önbelleğiniz isteği kaçırdığında (yeni yama, soğuk önbellek, önbellek süresi dolumu), her istek origin sunucunuza ulaşır. 1 Gbps çıktıya sahip tek bir origin, yaklaşık 1.250 eşzamanlı 1 MB varlık indirmesini sunabilir. Her biri 2 GB yama indiren 80.000 eşzamanlı oyuncuda, çoğu indie kurulumunun sahip olmadığı origin kapasitesine ihtiyacınız vardır.

2. Önbellek İzdihamı (Cache Stampede)

En çok istek alan varlığınız edge önbelleğinden süresi dolduğunda (TTL yanlış yapılandırması, deploy tarafından tetiklenen temizleme), binlerce edge düğümü aynı nesneyi aynı anda origin'den ister. Bu "thundering herd" problemidir ve origin'leri saniyeler içinde çökertir.

3. Bölgesel Edge Açlığı

NA edge düğümleriniz sıcak. Singapur edge düğümünüz %60 önbellek isabet oranına sahip çünkü yalnızca 12.000 APAC oyuncunuz var — ta ki Japonya'daki bir YouTuber oyununuzu tanıtana ve bu sayı bir gecede 300.000'e fırlayana kadar. Edge düğümü devasa ölçekte origin'den çeker ve APAC oyuncuları 2-4 saniyelik yükleme süreleri yaşarken NA oyuncuları 40ms görür.

Tespit Sinyalleri

# Cloudflare API: bölgelere göre önbellek isabet oranını kontrol et (her 60 saniyede bir çalıştır)
curl -s -X POST "https://api.cloudflare.com/client/v4/graphql" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "{
      viewer {
        zones(filter: {zoneTag: \"YOUR_ZONE\"}) {
          httpRequests1hGroups(limit: 24, filter: {date_gt: \"2025-01-01\"}) {
            dimensions { datetime, cacheStatus, clientCountryName }
            sum { requests, bytes }
          }
        }
      }
    }"
  }' | jq '.data.viewer.zones[0].httpRequests1hGroups[] |
    select(.dimensions.cacheStatus == "miss") |
    {region: .dimensions.clientCountryName, misses: .sum.requests}'

Kararlı durum döneminde herhangi bir bölgede önbellek isabetsizlik oranınız %8'i aşarsa, bir origin selinden yalnızca bir yama uzaktasınız demektir.


Acil İyileştirme: Hemen Şimdi Ne Yapmalısınız

CDN yanarken, oyuncular review-bombing yapmaya başlamadan önce 15 dakikalık bir pencereniz var. İşte triyaj sırası.

Adım 1: Origin Korumasını Etkinleştirin

Çoğu CDN sağlayıcısı bir "origin shield" veya "shielding" özelliği sunar — edge düğümleriniz ile origin'iniz arasında bir ara önbellek katmanı. Önbellek isabetsizliğinde 200 edge düğümünün her biri bağımsız olarak origin'e ulaşmak yerine, yalnızca koruma düğümü origin ile iletişim kurar ve yanıtı dağıtır.

Yapılandırma örneği (genel CDN API'si):

{
  "shielding": {
    "enabled": true,
    "shield_region": "us-east-1",
    "fallback_shield_region": "eu-west-1",
    "shield_ttl_override": 86400,
    "pass_on_shield_error": false
  }
}

Bu tek değişiklik, önbellek izdihamı sırasında origin yükünü %95 azaltabilir. cdnjs geçişi de benzer koruma mantığına dayanıyordu — origin sunucuları milyonlarca doğrudan çekme yerine saatte birkaç bin koruma kaynaklı istek gördü.

Adım 2: Statik İçerik için Varlık TTL'lerini Uzatın

4K dokularınız, ses bankalarınız ve mesh dosyalarınız yamalar arasında değişmez. 1 saatlik TTL için hiçbir neden yok.

# nginx origin sunucusu: değişmez oyun varlıkları için agresif önbellekleme
location /assets/v*/ {
    # Sürüm önekli yollar, yeni sürümlerin yeni URL'ler alması anlamına gelir
    # Temizlemeye gerek yok — eski URL'ler sonsuza kadar önbellekte kalır
    add_header Cache-Control "public, max-age=31536000, immutable";
    add_header CDN-Cache-Control "max-age=31536000";
}

# Yalnızca her yamada değişen manifest dosyaları için kısa TTL
location /manifest.json {
    add_header Cache-Control "public, max-age=60, stale-while-revalidate=300";
}

cdnjs mimarisinden ana içgörü: varlıklarınızı URL yolunda sürümleyin, sorgu dizeleriyle değil. Birçok CDN düğümü ?v=2 ve ?v=3'ü aynı önbellek anahtarı olarak ele alır. Bunun yerine /assets/v2/texture_pack.bin kullanın.

Adım 3: Stale-While-Revalidate'ı Etkinleştirin

Bu, lansman günü trafiği için en etkili tek yapılandırmadır. Önbelleğe alınmış bir varlığın süresi dolduğunda, CDN arka planda yeni sürümü getirirken istekte bulunan oyuncuya eski sürümü sunar. Oyuncu 1.200ms yanıt yerine 12ms yanıt alır.

Cache-Control: public, max-age=3600, stale-while-revalidate=86400

Bu CDN'e şunu söyler: "Bu varlık 1 saat taze. Bundan sonra, arka planda yeniden doğrularken 24 saate kadar eski sürümü sun."

Güvenlik açısından kritik olmayan oyun varlıkları için (lobi arka planları, kozmetik önizlemeler, ses parçaları) bu güvenlidir ve algılanan gecikmeyi önemli ölçüde azaltır.

Adım 4: Circuit-Breaker Geri Dönüşleri Uygulayın

CDN origin'i gerçekten aşırı yüklenmişse, oyun istemcinizin zarif bir bozulma yoluna ihtiyacı vardır — donmuş bir yükleme ekranına değil.

// C# Unity: yerel geri dönüşlü CDN circuit breaker
public class AssetLoader
{
    private const int MAX_RETRIES = 3;
    private const int TIMEOUT_MS = 5000;
    private static int _failureCount = 0;
    private static DateTime _circuitOpened = DateTime.MinValue;
    private static readonly TimeSpan CIRCUIT_RESET = TimeSpan.FromMinutes(2);

    public async Task<byte[]> LoadAsset(string assetPath)
    {
        // Circuit breaker: son hatalar eşiği aştıysa CDN'i atla
        if (_failureCount >= MAX_RETRIES &&
            DateTime.UtcNow - _circuitOpened < CIRCUIT_RESET)
        {
            Debug.LogWarning($"CDN circuit open — loading {assetPath} from local cache");
            return LoadFromLocalStorage(assetPath);
        }

        try
        {
            using var client = new HttpClient { Timeout = TimeSpan.FromMilliseconds(TIMEOUT_MS) };
            var response = await client.GetAsync($"https://cdn.yourgame.com/{assetPath}");
            response.EnsureSuccessStatusCode();
            _failureCount = 0; // Başarıda sıfırla
            return await response.Content.ReadAsByteArrayAsync();
        }
        catch (Exception ex)
        {
            _failureCount++;
            if (_failureCount >= MAX_RETRIES)
                _circuitOpened = DateTime.UtcNow;

            Debug.LogWarning($"CDN fetch failed ({_failureCount}/{MAX_RETRIES}): {ex.Message}");
            return LoadFromLocalStorage(assetPath);
        }
    }

    private byte[] LoadFromLocalStorage(string assetPath)
    {
        // Oyun ikili dosyanızla minimal bir "acil durum varlık paketi" gönderin
        // Bu, en kritik 20 varlığı kapsar: UI, varsayılan dokular, lobi müziği
        var localPath = Path.Combine(Application.streamingAssetsPath, "fallback", assetPath);
        return File.Exists(localPath) ? File.ReadAllBytes(localPath) : Array.Empty<byte>();
    }
}

Bu desen, CDN tamamen çökmüş olsa bile oyununuzun çalışır durumda kalmasını sağlar. Oyuncular birkaç dakika düşük çözünürlüklü dokular görebilir, ancak yine de oynayabilirler.


Önleme: Çok Katmanlı Önbellek Mimarisi

İyileştirme sizi lansman gününde kurtarır. Mimari, buna ihtiyaç duymanızı önler.

Üç Katman Deseni

cdnjs'in Cloudflare Workers'a geçişi, milyarlarca isteğe ölçeklenen bir önbellek mimarisi gösterdi. Oyun varlıkları için uyarlandı:

Katman 1 — Edge Önbelleği (CDN PoP'ları)

  • İsteklerin %95-99'unu karşılar
  • TTL: Sürümlü varlıklar için 365 gün, manifestler için 60 saniye
  • Dokular, mesh'ler, ses, shader'lar

Katman 2 — Koruma/Orta Katman Önbelleği

  • Edge düğümlerinden gelen önbellek isabetsizliklerini yakalar
  • TTL: Edge ile aynı, ancak origin proxy'si olarak çalışır
  • Origin yükünü %95+ azaltır

Katman 3 — Origin Sunucusu

  • Varlıkları üretir, URL'leri imzalar, manifestleri sunar
  • Rate limiting ve koruma ile korunur
  • Toplam trafik hacminin <%0,1'ini görmelidir

Sürümlü Varlık Pipeline'ı

Önbellek geçersiz kılma fırtınalarını önleyen varlık sürümleme iş akışı:

# Python: önbellek-güvenli sürümlü URL'ler üreten varlık pipeline'ı
import hashlib
import json
import os

def build_asset_manifest(asset_dir: str, cdn_base: str) -> dict:
    """
    Varlık dizinini gez, her dosyayı hash'le ve CDN edge düğümlerinin
    sonsuza kadar önbelleğe alabileceği sürümlü URL'ler içeren bir manifest üret.
    """
    manifest = {"version": "", "assets": {}}

    for root, _, files in os.walk(asset_dir):
        for filename in sorted(files):
            filepath = os.path.join(root, filename)
            relative_path = os.path.relpath(filepath, asset_dir)

            # İçerik hash'i — aynı dosyalar aynı URL'leri alır
            with open(filepath, "rb") as f:
                file_hash = hashlib.sha256(f.read()).hexdigest()[:12]

            # Sürüm PATH'te, sorgu dizesinde değil
            # CDN /assets/a3f9b2c1e8d4/texture.bin'i benzersiz bir nesne olarak ele alır
            versioned_url = f"{cdn_base}/assets/{file_hash}/{relative_path}"

            manifest["assets"][relative_path] = {
                "url": versioned_url,
                "hash": file_hash,
                "size": os.path.getsize(filepath),
            }

    # Manifest sürümü = tüm varlık setinin hash'i
    all_hashes = "".join(
        a["hash"] for a in sorted(manifest["assets"].values(), key=lambda x: x["url"])
    )
    manifest["version"] = hashlib.sha256(all_hashes.encode()).hexdigest()[:16]

    return manifest


# Kullanım
manifest = build_asset_manifest("./build/assets", "https://cdn.yourgame.com")
with open("./build/manifest.json", "w") as f:
    json.dump(manifest, f, indent=2)

print(f"Manifest version: {manifest['version']}")
print(f"Total assets: {len(manifest['assets'])}")
# Çıktı:
# Manifest version: a8f3e1c92b4d7061
# Total assets: 2,847

Bu yaklaşımla:

  • Eski varlıklar asla temizlenmez. Benzersiz URL'lere sahip oldukları için edge'de süresiz olarak önbellekte kalırlar.
  • Yeni varlıklar yeni URL'ler alır. CDN ilk istekte otomatik olarak önbelleğe alır.
  • Değişen tek dosya manifesttir. 60 saniyelik TTL'ye sahip küçük bir JSON dosyası.

cdnjs kütüphane sürümlemesini ölçekte tam olarak böyle yönetir. Her kütüphane sürümü benzersiz bir URL yolu alır, böylece CDN'in asla temizleme işlemlerine ihtiyacı olmaz — var olan en pahalı ve hataya açık CDN işlemi.

Bu mimari desen, oyun mantığının yanında konfigürasyon verisi sunması gereken dedicated server'lar çalıştırıyorsanız özellikle önemlidir. Unreal Engine dedicated server varlık ayıklamada nasıl ustalaşılır rehberimizde ele aldığımız gibi, statik varlıkları sunucu-kritik verilerden ayırmak, ölçekte birleşen temel bir optimizasyondur.


Coğrafi Dağıtım: Bölgesel Kademeli Dalgayı Çözmek

cdnjs geçişi, ham edge düğüm sayısının akıllı yönlendirmeden daha az önemli olduğunu ortaya koydu. Yönlendirme mantığı önbellek isabetsizliğinde APAC isteklerini ABD origin'ine gönderiyorsa, 300 PoP'a sahip olmak hiçbir şey ifade etmez.

Akıllı Origin Seçimi

{
  "origin_rules": [
    {
      "name": "us-primary",
      "origin_server": "origin-us.yourgame.com",
      "regions": ["NA", "SA"],
      "health_check": "/health",
      "failover_origin": "origin-eu.yourgame.com"
    },
    {
      "name": "eu-primary",
      "origin_server": "origin-eu.yourgame.com",
      "regions": ["EU", "AF"],
      "health_check": "/health",
      "failover_origin": "origin-us.yourgame.com"
    },
    {
      "name": "apac-primary",
      "origin_server": "origin-apac.yourgame.com",
      "regions": ["AS", "OC"],
      "health_check": "/health",
      "failover_origin": "origin-us.yourgame.com"
    }
  ]
}

Bölgesel origin sunucuları büyük bulut sağlayıcılarında ayda 20-40 dolar tutar. Üç bölgesel origin, NA origin'inizin APAC trafiğine 4 saat boyunca düşük performansla hizmet verdiği tek bir olaydan — ve beraberinde gelen kayıp oyunculardan — daha ucuzdur.

Bu tür çok bölgeli failover mimarisi, hibernasyon stratejileriyle sıfır atık sunucular mimarisi analizimizde tartıştığımız prensibi yansıtır — ölçeğe hazır olurken boşta altyapı için ödeme yapmama ilkesi.


Oyun Varlıkları için CDN Ölçekleme En İyi Uygulamaları

1. Varlıkları sorgu dizelerinde değil, URL yollarında sürümleyin. /assets/{hash}/texture.bin önbellek benzersizliğini garanti eder. ?v=2 garanti etmez — birçok CDN düğümü sorgu parametrelerini önbellek anahtarlarından çıkarır, bu da eski içerik veya bozuk önbellekler anlamına gelir.

2. Manifest TTL'nizi varlık TTL'nizden ayırın. Manifest dosyaları stale-while-revalidate ile 30-60 saniyelik TTL'ye sahip olmalıdır. Varlık dosyaları immutable ile 1 yıllık TTL'ye sahip olmalıdır. Bu ayrım, sorunsuz bir yama dağıtımı ile önbellek izdihamı arasındaki farktır.

3. Oyun ikili dosyanızla bir geri dönüş varlık paketi gönderin. En kritik 50-100 varlık (UI, varsayılan skin, lobi ortamı) oyun kurulumunuzun içinde 200-500 MB'lık bir acil durum paketi olarak bulunmalıdır. Circuit-breaker mantığınız, CDN erişilemez olduğunda bunlara geri döner.

4. Önbellek isabet oranını küresel değil, bölgeye göre izleyin. Küresel %97 isabet oranı, Güneydoğu Asya'daki %72'lik bir isabet oranını maskeleyebilir. Bölge bazlı izleme, bölgesel edge açlığını oyuncu kaynaklı bir olay haline gelmeden önce fark etmenizi sağlar.

5. Lansmandan önce CDN'inizi yük testine tabi tutun, lansman sırasında değil. Beklenen lansman günü trafik deseninizi CDN endpoint'inize karşı simüle etmek için k6, Locust veya Vegeta gibi araçlar kullanın. Manifest + ilk 20 varlığa 50.000 sanal kullanıcıyla 10 dakikalık bir test, gerçek oyuncular yanlış yapılandırılmış TTL'leri, eksik korumayı ve origin darboğazlarını ortaya çıkarmadan önce gösterecektir.

# k6: varlık manifestine 50.000 eşzamanlı oyuncu simüle et
cat <<'EOF' > cdn_load_test.js
import http from 'k6/http';
import { check, sleep } from 'k6';

export const options = {
  stages: [
    { duration: '2m', target: 10000 },  // 10K VU'ya yükselt
    { duration: '3m', target: 50000 },  // 50K VU'ya ani artış
    { duration: '5m', target: 50000 },  // Sürdür
    { duration: '2m', target: 0 },      // Düşür
  ],
  thresholds: {
    http_req_duration: ['p(95)<200'],   // 95. yüzdelik 200ms altında
    http_req_failed: ['rate<0.01'],     // %1'den az hata
  },
};

export default function () {
  const manifestRes = http.get('https://cdn.yourgame.com/manifest.json');
  check(manifestRes, {
    'manifest status 200': (r) => r.status === 200,
    'manifest under 100ms': (r) => r.timings.duration < 100,
    'cache HIT': (r) => r.headers['Cf-Cache-Status'] === 'HIT',
  });

  // Bir oyuncunun 5 rastgele varlık indirmesini simüle et
  for (let i = 0; i < 5; i++) {
    const assetPath = `assets/placeholder_${Math.floor(Math.random() * 100)}/mesh.bin`;
    const assetRes = http.get(`https://cdn.yourgame.com/${assetPath}`);
    check(assetRes, {
      'asset under 500ms': (r) => r.timings.duration < 500,
    });
  }

  sleep(1);
}
EOF

k6 run cdn_load_test.js

Kendiniz mi İnşa Etmeli, Yoksa Platform mu Kullanmalı?

Yukarıda açıklanan tam çok katmanlı önbellek mimarisini inşa etmek, adanmış altyapı mühendisleri olan bir ekip için tamamen uygulanabilir. Bileşenler iyi belgelenmiştir ve CDN sağlayıcıları ham ilkelleri sunar.

Ancak ekibiniz bir oyun çıkaran üç geliştiriciyse, origin koruması, bölgesel failover, varlık sürümleme pipeline'ları ve istemcinizde circuit-breaker mantığı inşa etmek için 4-6 hafta harcamak, oynanışa harcanmayan 4-6 hafta demektir. horizOn, varlık dağıtım altyapısını backend stack'inin bir parçası olarak ele alır ve operasyonel yük olmadan aynı çok bölgeli önbellekleme ve otomatik failover'ı sunar. Varlıkları yüklersiniz; platform sürümleme, edge dağıtımı ve sağlık izlemeyi kutudan çıktığı gibi halleder.

Bu makaledeki mimari prensipler, altyapı seçiminizden bağımsız olarak kritik önemini korur. Sürümlü URL yollarının neden önemli olduğunu, stale-while-revalidate'ın neden izdihamları önlediğini ve bölgesel origin'lerin neden gecikmeyi azalttığını anlamak, bilinçli kararlar vermenizi sağlar — ister Cloudflare Workers'ı elle yapılandırıyor olun, ister yönetilen bir backend hizmeti değerlendiriyor olun.


Sonraki Adım: Bir Sonraki Yamanızdan Önce Yük Testini Çalıştırın

Bir sonraki yama tarihinizi seçin. İki hafta önce, yukarıdaki k6 scriptini CDN endpoint'inize karşı çalıştırın. Simüle edilen lansman ölçeğinde p95 gecikmeniz 200ms'yi aşarsa, düzeltmek için zamanınız var. Sürdürme aşamasında önbellek isabet oranınızın %90'ın altına düştüğünü fark ederseniz, origin korumasını etkinleştirin ve varlık TTL'lerinizi uzatın.

Sorunsuz bir lansman ile lansman günü felaketi arasındaki fark nadiren oyun kodudur. Her oyuncunun ilk beş dakikada indirdiği 2 GB varlığa hizmet eden altyapıdır. Bunu doğru yapın, gerisi oynanıştır.