Loading...

Vaka çalışması

Ölçekte canlı anket: cache-ve-purge deseni

Canlı yayındaki bir anket, olabilecek en kötü okuma desenidir: bütün izleyiciler aynı saniyede aynı cevabı ister, sunucu yeni soruyu açtığı anda hepsi yeniden sorar. Backend'i yoklamak (polling) bunu kaldırmaz. yayında.tv'deki anketleri ve Videoonly'deki oynatıcı içi etkileşimleri, her değişiklik başına yaklaşık tek bir origin isteğiyle böyle çalıştırıyoruz — cache'lenen bir URL ve bir purge çağrısından fazlası yok.

9 Orta seviye Güncellendi

Ölçekte canlı anket: cache-ve-purge deseni

Canlı anket, akla ilk gelen çözümü neden kırar?

Akla ilk gelen çözüm, sayfanın birkaç saniyede bir çağırdığı bir uçtur. Beş kişiyle testte çalışır, canlıda dağılır; çünkü canlı bir kitle, normal web trafiğinin asla olmadığı biçimde eşzamanlıdır.

Herkes aynı anı izliyor. Sunucu soruyu açıyor ve otuz bin tarayıcı aynı saniye içinde onu istiyor. Hepsi birebir aynı cevabı istiyor; yani aynı sorguyu otuz bin kez çalıştırıp aynı baytları döndürüyorsunuz. Sonra yayın boyunca, bir şey değişsin değişmesin, birkaç saniyede bir sormaya devam ediyorlar.

Alışıldık kaçış yolu WebSocket: izleyici başına bir bağlantı tutup veriyi itmek. Çalışır, ama bağlantı durumunu, soket katmanını ölçeklemeyi, mobil şebeke tökezlediğinde yeniden bağlanma fırtınalarını ve bağlantı tutamayan istemciler için bir yedek yolu da üstlenmiş olursunuz.

Daha basit bir seçenek var ve canlıda çalıştırdığımız bu.

Desen: tek cache'li URL, değişince purge

Anket durumu küçüktür, herkes için aynıdır ve nadiren değişir — yayın başına birkaç kez. Bu, tam olarak CDN'in var olma sebebi olan şekildir.

O yüzden onu düz, cache'lenebilir bir JSON URL'i olarak yayınlayın. İzleyiciler o URL'i çeker ve en yakın edge cevap verir. Origin'iniz her lokasyondaki ilk isteği görür, sonrasında kaç kişi izlerse izlesin neredeyse hiçbir şey görmez.

Sunucu bir soruyu açtığında, kapattığında veya düzenlediğinde backend o tek URL'i purge eder. Sonraki izleyici isteği edge'de ıskalar, yeni durumu bir kez çeker, ondan sonraki herkes yine cache'ten sunulur.

İlginç olan, kitle büyüdüğünde ne olduğu: hiçbir şey. On bin izleyici de olsa yüz bin de olsa origin yine lokasyon başına değişiklik başına tek istek görür. Maliyet, kaç kişinin izlediğini değil, anketin ne sıklıkta değiştiğini takip eder.

yayında.tv'de nasıl görünüyor

yayında.tv bizim canlı yayın platformumuz ve mekanizmanın tamamı bu.

Okuma tarafı, aktif anketi soruları ve cevaplarıyla birlikte JSON olarak döndüren tek bir uç; CDN üzerinden sunuluyor. İzin verici CORS başlıkları gönderiyor, böylece oynatıcı yayının gömülü olduğu hangi alan adı olursa olsun onu çekebiliyor. URL, kanal adı ve sunucu tarafındaki bir gizli anahtardan türetilen bir hash taşıyor; bu, adresin kolayca tahmin edilmesini engellerken cache'lenebilirliği bozmuyor — URL belirli bir kanal için sabit, yani kullanıcıya özel değil, gerçek bir cache anahtarı.

Yazma tarafı ise anketi başlatan ya da durduran controller'daki birkaç satır: aynı URL'i kur, purge API'sini çağır, bitti. Kuyruk yok, dağıtım katmanı yok, soket katmanı yok — dağıtımı CDN yapıyor.

İki yarı
// OKUMA — her izleyicinin çağırdığı, edge'de cache'li
GET https://cdn.example.tv/{kanal}/survey?s={hash}

{
  "status": "success",
  "survey": {
    "id": 42,
    "questions": [
      { "text": "Penaltıyı kim kullanır?",
        "answers": [{"id": 1, "text": "..."}, {"id": 2, "text": "..."}] }
    ]
  }
}

// YAZMA — sunucu anketi açar; backend o tek URL'i purge eder
cdnctl purge --account <account_uuid> \
             --path "/{kanal}/survey?s={hash}" --type exact

// ya da doğrudan uygulamadan, anketi canlıya alan olayın içinde

Ve oynatıcının içinde: Videoonly

Videoonly aynı fikri video oynatıcının içine uyguluyor. Oynatıcı içi etkileşimler — soru katmanı, sponsor kartı, yayının belirli bir anına zamanlanmış bir eylem çağrısı — hepsi aynı biçimde bir problem: her izleyicinin ihtiyaç duyduğu, bir operatör değiştirmeye karar verdiğinde değişen küçük bir durum parçası.

Bu yüzden oynatıcı, katman yapılandırmasını API'yi zamanlayıcıyla yoklayarak değil, cache'li bir URL'den çekiyor. Biri bir katmanı planladığında ya da kaldırdığında o URL purge ediliyor. Oynatıcı bir sonraki çekimde yeni halini alıyor ve API sıcak yolda hiç yer almıyor.

Aynı mantık şu özelliklere sahip her şey için geçerli: skor tabelası, "şimdi çalıyor" şeridi, canlı bir etkinlik için özellik bayrakları, kısa kesilebilen bir geri sayım.

Ayrıntıları doğru yapmak

Bunun pratikte akıcı mı yoksa sinir bozucu mu olacağını birkaç şey belirliyor.

**URL'i sabit tutun.** Yolda ya da sorgu dizesinde kullanıcıya özel her şey — oturum kimliği, cache kırıcı zaman damgası — her izleyiciye kendi cache anahtarını verir ve herkes için yeniden origin'e gidersiniz. Kişiselleştirme, paylaşılan isteğe değil, ikinci ve ayrı bir isteğe aittir.

**Zaten yaşayabileceğiniz bir TTL koyun.** Değişikliği hızlı yapan şey purge'dür, ama sonlu bir TTL, purge çağrısının başarısız olduğu gün için güvenlik ağınızdır. Kaçan bir purge'ün sadece bir tökezleme olacağı kadar kısa, origin'in sessiz kalacağı kadar uzun olsun.

**Sunduğunuz URL'in tam olarak kendisini purge edin.** Cache'lenen nesne `?s=abc` ise ve siz sorgu dizesi olmadan yolu purge ederseniz hiçbir şey geçersizleşmez, eski anket ekranda kalır. Bu desenin sessizce bozulmasının en yaygın yolu budur.

**Okumayı yazmadan ayırın.** İzleyiciler cache'li URL'i okur; oylar normal, cache'lenmeyen bir uca gider. Yazma, okumanın çok küçük bir kesridir — izleyici bir kez oy verir, sürekli okur — yani yazma yolu sıradan kalabilir.

**URL hash'ine sır koymayın.** Bu yetkilendirme değil, gizlemedir: rastgele denemeleri durduracak kadar; ve cache ile uyumlu kalmak zorunda. Gerçekten korunması gereken hiçbir şey, paylaşılan ve cache'lenen bir nesnenin içinde olmamalı.

Ne zaman WebSocket'e gitmeli

Bu desen evrensel bir ikame değil ve nerede bittiğini açıkça söylemekte fayda var.

Durum herkes için ortaksa, küçükse ve insan zaman ölçeğinde değişiyorsa uyar — anketler, katmanlar, skor tabelaları, bayraklar. Her izleyicinin farklı veriye ihtiyaç duyduğu, güncellemelerin ara sıra değil sürekli olduğu ya da sıralama garantisiyle saniye altı teslim gerektiğinde uymaz. Canlı sohbet bunun apaçık karşı örneğidir: kullanıcıya özel, sürekli ve gecikmeye duyarlı. Orada soket katmanı kullanın.

Dürüst çerçeve şu: bir yayın sayfasındaki "gerçek zamanlı" özelliklerin çoğu aslında gerçek zamanlı değildir. Ortak duruma ara sıra yapılan değişikliklerdir ve cache'li bir URL ile bir purge, bunları çok daha az hareketli parçayla halleder.

Sık sorulanlar

İzleyiciler değişikliği ne kadar hızlı görüyor?

Purge'ün yayılma süresi artı istemcinin bir sonraki çekimi kadar. Pratikte bir iki saniye — bir yayın için fazlasıyla yeterli, çünkü sunucu zaten geçişin üzerine konuşuyor.

Purge çağrısı başarısız olursa ne olur?

TTL tam da bunun için var. Kaçan bir purge, değişikliğin anında değil nesne süresi dolunca inmesi demektir. TTL'i bunun bir kesinti değil gecikme olacağı kadar kısa tutun ve purge hatalarını loglayın ki bir örüntü oluşursa fark edin.

URL'de sorgu dizesi varken çalışır mı?

Evet — CDN sorgu dizesini cache anahtarına dahil ettiği ve siz sunduğunuz URL'in tam olarak kendisini purge ettiğiniz sürece. Nesne sorgu dizesiyle cache'lenmişken yalnızca yolu purge etmek klasik hatadır.

Oylar nereye gidiyor?

Normal, cache'lenmeyen bir uca. Yalnızca ortak okuma cache'leniyor. Oylar trafiğin çok küçük bir kesri, çünkü her izleyici bir kez oy verip sürekli okuyor.

Bu WebSocket'ten ucuz mu?

Genellikle evet, ama asıl tasarruf operasyonel. Ölçeklenecek soket katmanı, tutulacak bağlantı durumu, mobil şebeke düştüğünde yeniden bağlanma fırtınası yok. Origin maliyeti kaç kişinin izlediğini değil, anketin ne sıklıkta değiştiğini takip ediyor.