Ders 11 / 14
Video Yayın Servisi
Aynı içeriğin birden çok temsilinin tutulduğu vaka: kodlama boru hattının işlemci-saniye ile bütçelenmesi, kalite basamaklarının izleyici bant genişliği dağılımı üzerinde ölçülmesi, basamak başına kazanılan bant kullanımının azalması ve üç ayrı kısıtın üç ayrı merdiveni elemesi.
İçindekiler
Önceki vakada nesne, servis için anlamsız bir bayt dizisiydi: yazıldığı gibi saklandı, okunduğu gibi verildi. Bu vaka o varsayımı kaldırır. Yüklenen dosya bir kez saklanmaz; içeriğinden birden çok temsil üretilir ve hangi temsilin verileceği isteği yapanın o andaki bandına göre belirlenir. Yeni kalem kodlama boru hattıdır (transcoding pipeline) ve yeni ödünleşim uyarlanabilir akışın (adaptive streaming) kaç kalite basamağı (bitrate ladder) taşıyacağıdır.
Ölçülecek karar şu: her basamak hem saklanan bayta hem de işlemci-saniyeye mal olur, ama karşılığı izleyicinin bandına daha iyi uyan bir akıştır. Basamak sayısı bu iki eğrinin kesiştiği yerde seçilir ve kesişme noktası izleyici bandının dağılımına bağlıdır.
Kısıtlar
İşlevsel gereksinim: yüklenen kaynak kopyadan birden çok kalite basamağı üretme, her basamağı sabit süreli parçalara bölme, parça listesini istemciye verme ve istemcinin basamaklar arasında geçmesine izin verme.
İşlevsel olmayan gereksinim, sayıyla: bandı en düşük basamağı taşımadığı için oynatamayan izleyici oranı yüzde 10’un altında kalır; saklanan bayt kaynak kopyanın 2,5 katını geçmez; kodlamaya sürekli ayrılan işlemci 1500’ü geçmez; bir saatlik videonun yüklemeden izlenebilir olmaya geçmesi 10 dakikayı aşmaz.
Kapsam daraltması: içerik koruma, canlı yayın, öneri, altyazı üretimi ve reklam yerleştirme tasarlanmaz.
Varsayımlar
| Kod | Varsayım | Değer | Gerekçe |
|---|---|---|---|
| VY1 | günlük yüklenen video saati | 4.000 | yükleyenlerin günlük toplamı |
| VY2 | kaynak kopyanın bit hızı | 20.000 kbit/s | kodlanmamış yükleme |
| VY3 | günlük izlenen saat | 900.000 | izleme yüklemeden çok daha yoğun |
| VY4 | tepe çarpanı | 3 | tepe saatin gün ortalamasına oranı |
| VY5 | saklama süresi | 365 gün | katalog bir yıl tutulur |
| VY6 | kodlama maliyeti | 0,4 + 0,25 × Mbit/s | video-saniye başına işlemci-saniye |
| VY7 | izleyici bandı dağılımı | 0,25/1,5 + 0,50/6 + 0,25/20 | üç sınıflı karışım, üstel, Mbit/s |
| VY8 | bandın kullanılabilir payı | 0,8 | protokol yükü ve dalgalanma payı |
| VY9 | parça süresi | 4 s | basamak değişimi bu tanecikte olur |
| VY10 | kenar önbelleği isabet oranı | 0,95 | parçalar değişmez, uzun tutulur |
VY6 ve VY7 bu tasarımın iki taşıyıcı varsayımıdır: biri üretim maliyetini, öteki isabeti belirliyor. İkisi de gerekçelidir, ölçüm değildir.
Ölçek
// video-olcek.mjs — VY tablosundan cikan olcek hesabi; hepsi aritmetiktir const VY = { yuklenenSaat: 4000, kaynakKbit: 20_000, izlenenSaat: 900_000, saklamaGun: 365, sabitCpu: 0.4, kbitBasinaCpu: 0.25, parcaSn: 4 }; const BASAMAK = [400, 1200, 3000, 6000, 12_000]; // secilen kalite basamaklari, kbit/s const toplam = BASAMAK.reduce((a, b) => a + b, 0); const cpu = BASAMAK.reduce((a, k) => a + VY.sabitCpu + VY.kbitBasinaCpu * (k / 1000), 0); const videoSn = VY.yuklenenSaat * 3600; for (const [ad, d] of [ ["izlenen / yuklenen saat", VY.izlenenSaat / VY.yuklenenSaat], ["basamak toplami kbit/s", toplam], ["kodlama islemci-sn / video-sn", cpu], ["gunluk saklanan TB", (videoSn * (VY.kaynakKbit + toplam) * 1000) / 8 / 1e12], ["yil sonu saklanan PB", (videoSn * (VY.kaynakKbit + toplam) * 1000 * VY.saklamaGun) / 8 / 1e15], ["gunluk uretilen parca", (videoSn / VY.parcaSn) * BASAMAK.length], ]) console.log(ad.padEnd(30) + d.toFixed(2).padStart(14)); console.log(`\nbir saatlik video ${(3600 * cpu).toFixed(0)} islemci-sn ister:`); for (const n of [30, 60, 120]) console.log(` ${n} isci -> yukleme-izlenebilirlik ${((3600 * cpu) / n / 60).toFixed(2)} dk`);
izlenen / yuklenen saat 225.00 basamak toplami kbit/s 22600.00 kodlama islemci-sn / video-sn 7.65 gunluk saklanan TB 76.68 yil sonu saklanan PB 27.99 gunluk uretilen parca 18000000.00 bir saatlik video 27540 islemci-sn ister: 30 isci -> yukleme-izlenebilirlik 15.30 dk 60 isci -> yukleme-izlenebilirlik 7.65 dk 120 isci -> yukleme-izlenebilirlik 3.83 dk
Bu sayılar hesap sınıfındadır. Üçü tasarımı belirliyor. Her yüklenen saat 225 saat izleniyor: bir kez ödenen kodlama maliyeti iki yüz yirmi beş kez okunuyor, bu yüzden içeriği izleme anında değil yükleme anında hazırlamak baştan makul görünüyor. Günde 18.000.000 parça üretiliyor — dağıtım katmanının gördüğü nesne sayısı budur, video sayısı değil. Ve son satır bir kısıtı doğrudan karşılıyor: 10 dakikalık gecikme kısıtı en az 46 işçi ister; 30 işçiyle 15,30 dakikaya çıkıp kısıt çiğneniyor, 60 işçiyle 7,65 dakika kalıyor.
Basamak Seçimi
Basamak sayısı ancak izleyici bandının dağılımı verildiğinde savunulabilir. Aşağıdaki model bir ağ kurmaz, kodlayıcı çalıştırmaz: VY7’nin üç sınıflı karışımından bant çeker, her izleyicinin kullanılabilir bandına sığan en yüksek basamağı seçer ve dört merdiveni aynı izleyici kümesi üzerinde karşılaştırır.
// basamak.mjs — surec ici model: izleyici bant genisligi dagilimindan basamak seciminin // isabeti. Ag yok, kodlayici yok; dagilim uc sinifli bir karisimdir ve model oldugu yazilir. const IZLEYICI = 200_000, TOHUM = 20260731, PAY = 0.8; // VY8: bandin kullanilabilir payi const SINIF = [[0.25, 1500], [0.50, 6000], [0.25, 20_000]]; // VY7: pay, ortalama kbit/s const KAYNAK = 20_000, SABIT = 0.4, KBIT_CPU = 0.25; // VY2, VY6 const IZLENEN_SAAT = 900_000, TEPE = 3, ISABET = 0.95; // VY3, VY4, VY10 const YUKLENEN_SN = 4000 * 3600; // VY1: gunluk kodlanan video-saniye let durum = TOHUM; const rast = () => { durum = (durum * 1103515245 + 12345) % 2147483648; return durum / 2147483648; }; function bant() { // sinif sec, ustel dagilimdan cek let u = rast(), i = 0; while (i < SINIF.length - 1 && u > SINIF[i][0]) { u -= SINIF[i][0]; i += 1; } return -Math.log(1 - rast()) * SINIF[i][1]; } const bantlar = Array.from({ length: IZLEYICI }, bant); const MERDIVEN = { "1 basamak": [3000], "3 basamak": [800, 3000, 9000], "5 basamak": [400, 1200, 3000, 6000, 12_000], "8 basamak": [300, 600, 1000, 1800, 3000, 5000, 8000, 12_000] }; function olc(m) { let oynamayan = 0, secilenToplam = 0, kullanimToplam = 0; for (const b of bantlar) { const kullanilabilir = b * PAY; const s = m.filter((k) => k <= kullanilabilir).pop(); if (s === undefined) { oynamayan += 1; continue; } secilenToplam += s; kullanimToplam += s / kullanilabilir; } const oynayan = IZLEYICI - oynamayan; const toplamKbit = m.reduce((a, b) => a + b, 0); return { oynamayan: oynamayan / IZLEYICI, ortSecilen: secilenToplam / oynayan, kullanim: kullanimToplam / oynayan, saklama: (KAYNAK + toplamKbit) / KAYNAK, cpu: m.reduce((a, k) => a + SABIT + KBIT_CPU * (k / 1000), 0) }; } console.log(`model: ${IZLEYICI} izleyici, tohum ${TOHUM}, sinif paylari ` + `${SINIF.map(([p, o]) => `${p}/${o}`).join(" ")} kbit/s (ustel)\n`); console.log("merdiven".padEnd(11) + "oynamayan".padStart(11) + "ort secilen".padStart(13) + "bant kullanimi".padStart(16) + "saklama kati".padStart(14) + "surekli islemci".padStart(17) + "tepe uc Gbit/s".padStart(16) + "koken Gbit/s".padStart(14)); const R = {}; for (const [ad, m] of Object.entries(MERDIVEN)) { const r = olc(m); R[ad] = r; const uc = (IZLENEN_SAAT * 3600 * r.ortSecilen * 1000 / 86_400) * TEPE / 1e9; console.log(ad.padEnd(11) + `%${(r.oynamayan * 100).toFixed(2)}`.padStart(11) + r.ortSecilen.toFixed(0).padStart(13) + `%${(r.kullanim * 100).toFixed(1)}`.padStart(16) + r.saklama.toFixed(2).padStart(14) + ((YUKLENEN_SN * r.cpu) / 86_400).toFixed(0).padStart(17) + uc.toFixed(2).padStart(16) + (uc * (1 - ISABET)).toFixed(2).padStart(14)); } const k = Object.keys(MERDIVEN); console.log("\nbasamak basina kazanilan bant kullanimi:"); for (let i = 1; i < k.length; i += 1) { const d = MERDIVEN[k[i]].length - MERDIVEN[k[i - 1]].length; console.log(` ${k[i - 1]} -> ${k[i]}: ${(((R[k[i]].kullanim - R[k[i - 1]].kullanim) * 100) / d).toFixed(2)} puan/basamak`); } const kapali = olc([400, 1200, 3000, 6000]); // tepe basamak kapatilirsa console.log(`tepe basamak kapali: ort secilen ${kapali.ortSecilen.toFixed(0)} kbit/s, uc cikisi ` + `x${(kapali.ortSecilen / R["5 basamak"].ortSecilen).toFixed(2)}, oynamayan ayni %${(kapali.oynamayan * 100).toFixed(2)}`); const ozelCpu = IZLENEN_SAAT * 3600 * (SABIT + KBIT_CPU * 6); // izleyici basina tek akis const merdivenCpu = YUKLENEN_SN * R["5 basamak"].cpu; console.log(`izleyiciye ozel kodlama: ${ozelCpu.toExponential(2)} islemci-sn/gun, 5 basamagin ` + `${(ozelCpu / merdivenCpu).toFixed(1)} kati (${(merdivenCpu).toExponential(2)})`);
model: 200000 izleyici, tohum 20260731, sinif paylari 0.25/1500 0.5/6000 0.25/20000 kbit/s (ustel) merdiven oynamayan ort secilen bant kullanimi saklama kati surekli islemci tepe uc Gbit/s koken Gbit/s 1 basamak %45.75 3000 %43.2 1.15 192 337.50 16.88 3 basamak %13.77 3846 %56.5 1.64 733 432.71 21.64 5 basamak %8.91 4442 %64.9 2.13 1275 499.72 24.99 8 basamak %6.08 4607 %73.8 2.58 1854 518.24 25.91 basamak basina kazanilan bant kullanimi: 1 basamak -> 3 basamak: 6.66 puan/basamak 3 basamak -> 5 basamak: 4.22 puan/basamak 5 basamak -> 8 basamak: 2.96 puan/basamak tepe basamak kapali: ort secilen 3242 kbit/s, uc cikisi x0.73, oynamayan ayni %8.91 izleyiciye ozel kodlama: 6.16e+9 islemci-sn/gun, 5 basamagin 55.9 kati (1.10e+8)
Tablodaki oranlar ölçüm, maliyet sütunları hesap sınıfındadır; ölçülen oranlar bu koşumun tohumuna bağlıdır, kısıtları ayıran farklar ise tohumdan bağımsız büyüklüktedir. Basamak başına kazanılan bant kullanımı 6,66’dan 4,22’ye, oradan 2,96 puana düşüyor: her yeni basamak bir öncekinden daha az kazandırıyor, ama maliyeti daha az düşmüyor.
Tasarım
Ölçüm beş basamaklı merdiveni işaret ediyor; tasarım onun üstüne kurulur. Kodlama boru hattı bir mesaj kuyruğu ve rekabet eden tüketiciler üzerine oturur (Uygulama Katmanı ve Servis Etkileşimi kursunun Kuyruklar ve İş Akışları konusu). Parametre işçi sayısıdır: 60 işçi bir saatlik videoyu 7,65 dakikada izlenebilir yapar. Aynı konudaki öncelikli kuyruk yeni yüklemeyi geri dolduran yeniden kodlama işlerinin önüne alır; bu, gecikme kısıtının yalnız yeni yüklemeler için geçerli olmasını sağlar. İş iletisi baytları taşımaz, kaynak nesnenin anahtarını taşır — talep fişi kalıbı (Dayanıklılık ve Güvenilirlik kursunun Dağıtık Doğruluk konusu). Kodlama işi etkisizdir (aynı konu); tekillik anahtarı video kimliği ile basamağın ikilisidir, böylece yarıda kalan iş yeniden sürüldüğünde ikinci bir çıktı üretmez.
Dağıtım tarafı içerik dağıtım ağı ve kenar önbelleği üzerine kurulur (Trafik Katmanı kursunun Giriş Noktaları konusu). Parametre isabet oranıdır: VY10’un yüzde 95’i tepe uçtaki 499,72 Gbit/s’yi kökende 24,99 Gbit/s’ye indiriyor. Parçalar üretildikten sonra hiç değişmediği için bayatlık penceresi diye bir soru yok; aynı konudaki itme tabanlı dağıtım yeni yüklenen içeriğin ilk parçalarını izlenmeden önce kenara taşır, gerisi çekmeyle gelir. Parça listesi ve parçalar statik dosyalardır (aynı konu, Statik İçerik Barındırma), bu yüzden okuma yolunda uygulama kodu yok.
Bilerek kullanılmayan kalıp: devre kesici. Dayanıklılık ve Güvenilirlik kursunun Arıza Yalıtımı konusundaki devre kesici kodlama katmanına konmaz, çünkü işçiler senkron çağrı yapmaz; kuyruktan çeker ve başarısız işi yeniden görünür kılar — kesilecek bir çağrı yolu yoktur. İkincisi komut ve sorgu sorumluluğu ayrımıdır (Veri Katmanı Ölçekleme kursunun Okuma–Yazma Ayrımı konusu): okuma yolu bir sorgu değil, adı önceden bilinen bir dosyanın getirilmesidir ve ayrı bir okuma modeli türetmenin karşılığı yoktur.
Elenen Alternatifler
Üç alternatif üç ayrı sayıyla eleniyor ve her biri farklı bir kısıta takılıyor.
Tek basamak en ucuzudur: saklama katı 1,15, sürekli 192 işlemci. Ama izleyicilerin yüzde 45,75’i o tek basamağı taşıyamıyor ve hiç oynatamıyor — yüzde 10 kısıtının dört buçuk katı. Üç basamak da yüzde 13,77 ile kısıtın üstünde kalıyor.
Sekiz basamak isabet tarafında en iyisidir: bant kullanımı yüzde 73,8, oynatamayan yüzde 6,08. İki kısıtı birden çiğniyor: saklama katı 2,58 (sınır 2,5) ve sürekli 1854 işlemci (sınır 1500). Kazandığı 8,9 puanlık kullanım, saklamada yüzde 21, işlemcide yüzde 45 fazla ödemeye mal oluyor.
İzleyiciye özel kodlama — her akışı izleyicinin bandına tam uyduracak biçimde anlık üretmek — isabet sorununu tamamen çözer, çünkü kullanım yüzde 100 olur ve fazladan basamak saklanmaz. Günde 6,16 milyar işlemci-saniye ister; beş basamaklı merdivenin 110 milyon işlemci-saniyesinin 55,9 katı. Sebep ölçek hesabındaki ilk satırdır: kodlama yükleme başına bir kez değil, izleme başına bir kez ödenir ve izleme yüklemenin 225 katıdır.
Geriye beş basamak kalıyor: oynatamayan yüzde 8,91, saklama katı 2,13, sürekli 1275 işlemci — üç kısıt da karşılanıyor. Hangi kısıt değişirse alternatif kazanır: saklama sınırı 2,6’ya çıkarılırsa sekiz basamak girer ve bant kullanımını 8,9 puan artırır; izleyici bandı dağılımı daralırsa (üç sınıf birbirine yaklaşırsa) az basamak yeter ve üç basamak kısıtı karşılamaya başlar.
Arıza Davranışı ve Feda Edilen
Kodlama katmanı tümüyle düştüğünde katalog izlenmeye devam eder; yalnız yeni yüklemeler izlenebilir olmaz ve kuyrukta birikir. Bu zarif bozulmadır (Arıza Yalıtımı konusu) ve maliyeti gecikme kısıtının askıya alınmasıdır. Köken düştüğünde kenar önbelleği isteklerin yüzde 95’ini karşılamayı sürdürür, çünkü parçalar değişmezdir ve bayat sunum diye bir risk yoktur. Çıkış tarafında tepe yük sınırı zorladığında en üst basamak kapatılır: ortalama seçilen bit hızı 4442’den 3242 kbit/s’ye, uçtaki çıkış 0,73 katına iner ve oynatamayan izleyici oranı yüzde 8,91’de değişmeden kalır — yani bozulma kaliteyi düşürür, kimseyi dışarıda bırakmaz.
Feda edilen: bant kullanımı yüzde 64,9’da bırakıldı. İzleyicinin kullanılabilir bandının üçte biri boşta duruyor ve bu, saklamayı 2,5 katın, kodlamayı 1500 işlemcinin altında tutmanın bedelidir.
Özet
- Yüklenen her saat 225 saat izleniyor; kodlama maliyetinin izleme anında değil yükleme anında ödenmesinin gerekçesi bu orandır ve izleyiciye özel kodlamayı 55,9 kat pahalı yapan da odur.
- Kalite basamaklarının isabeti ancak izleyici bandı dağılımıyla birlikte ölçülebilir: beş basamakta bant kullanımı yüzde 64,9, oynatamayan izleyici yüzde 8,91.
- Basamak başına kazanılan kullanım 6,66’dan 4,22’ye, oradan 2,96 puana düşerken maliyet basamak başına düşmüyor; merdivenin sonu bu yüzden vardır.
- Üç alternatif üç ayrı kısıtla elenir: tek basamak oynatamayan oranıyla (yüzde 45,75), sekiz basamak saklama (2,58) ve işlemci (1854) sınırlarıyla, izleyiciye özel kodlama işlemci-saniyeyle.
- Kenar önbelleği çıkışı 499,72 Gbit/s’den 24,99 Gbit/s’ye indiriyor ve parçalar değişmez olduğu için bayatlık penceresi tartışması hiç açılmıyor.
Sonraki Adım
Bu vakada da veri yazıldığı gibi saklandı: bir parça üretildi, bir yere kondu ve sonra aynen okundu. Üretilen her bayt saklanmaya değerdi. Sonraki vaka bu varsayımı kaldırır. Orada kayıtlar saniyede yüz binlerce üretilir, tek tek hiçbiri anlamlı değildir ve hepsini saklamak imkânsızdır. Soru şuna dönüşür: hangi kayıt ne kadar süreyle ham tutulur, ne zaman toplulaştırılır ve toplulaştırılmış veriden okunan yanıt ham veriden okunandan ne kadar sapar.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.