İçeriğe geç
academia.sh

Ders 14 / 16

Ön Yüz İçin Backend

Kenarın istemci türüne göre bölünmesi: üç istemcinin alan kümelerinin ayrılması, tek birleşik gövdenin taşıdığı kullanılmayan alanların ve istek sayısının ölçülmesi, ayrı kenar birimlerinin ödettiği toplu uç şartı ve istemci karışımının K01 çıkış hesabına etkisi.

İçindekiler

Önceki üç ders kenarı tek bir yüzey olarak ele aldı: bütün istemciler aynı adrese gelir, aynı denetimlerden geçer, toplama yapıldığında aynı birleşik gövdeyi alır. Oysa takip bilgisini isteyen istemciler aynı şeyi istemez. Bir mobil takip kartı yalnız durumu ve güncellenme zamanını gösterir; bir web takip sayfası bölgeyi ve rota adımlarını da açar; bir satıcı paneli gönderi listesini ücret kalemleriyle birlikte ister.

Ön yüz için backend (backend for frontend), kenarı istemci türü başına ayrı bir birime bölmektir: her istemcinin kendi kenar birimi olur ve o birim yalnız o istemcinin istediği alanları, o istemcinin istediği biçimde döndürür. Bu ders iki yerleşimi karşılaştırır ve sorunun ölçüsünü kullanılmayan alan sayısı ile istek sayısında arar. Aşırı veri çekme Web API Tasarımı kursunda kurulmuş ve orada arayüz biçemleri üzerinde ölçülmüştü; burada aynı olgu bir kenar yerleşimi kararı olarak ele alınır.

Üç İstemci, Üç Alan Kümesi

Model süreç içidir: gerçek bir istemci, tarayıcı ya da ayrı süreç yoktur. Birleşik gövde önceki dersin ölçtüğü gövdedir; alan kümeleri istemci türü başına listelenir. gonderi alanı bir görüntülemede kaç kaydın istendiğini, pay alanı takip sorgularının ne kadarının o istemciden geldiğini söyler.

// kenar/istemci.mjs — uc istemci turu, istedikleri alanlar ve alanlarin hangi serviste oldugu
export const KAYIT = {
  takipNo: "TR-4821", durum: "dagitimda", bolge: "35",
  guncellenme: "2026-03-11T08:24:00Z", rota: ["34", "41", "35"],
  ucret: { tarife: 9600, indirim: 1440, net: 8160, sozlesmeNo: "S7" },
};

export const SERVIS_ALANI = {
  "teslimat-op": ["takipNo", "durum", "bolge", "guncellenme", "rota"],
  "ucretlendirme": ["ucret"],
};

// gonderi: bir goruntulemede kac kayit isteniyor; pay: takip sorgularinin ne kadari (T2)
export const ISTEMCI = {
  "mobil kart": { alan: ["takipNo", "durum", "guncellenme"], gonderi: 1, pay: 0.6 },
  "web sayfasi": { alan: ["takipNo", "durum", "bolge", "guncellenme", "rota"], gonderi: 1, pay: 0.3 },
  "satici paneli": { alan: ["takipNo", "durum", "ucret"], gonderi: 5, pay: 0.1 },
};

export const yaprak = (d) => (typeof d !== "object" || d === null ? 1
  : Object.values(d).reduce((t, v) => t + yaprak(v), 0));
export const sec = (kayit, alanlar) => Object.fromEntries(alanlar.map((a) => [a, kayit[a]]));
export const bayt = (d) => Buffer.byteLength(JSON.stringify(d));
export const servisSayisi = (alanlar) => Object.values(SERVIS_ALANI)
  .filter((liste) => alanlar.some((a) => liste.includes(a))).length;

pay değerleri bu kursun varsayımıdır (T2): takip sorgularının yüzde altmışı mobil karttan, yüzde otuzu web sayfasından, yüzde onu satıcı panelinden gelir. K01’in tablosuna eklenmez, çünkü K01 istemci türü ayırmıyordu. Gerekçesi takip sorgusunun çoğunun alıcı tarafından tek gönderi için yapılmasıdır; duyarlılığı aşağıda hesaplanır.

// kenar/olc.mjs — tek kenar ile on yuz icin backend yerlesimini olcer ve K01 cikisina baglar
import { KAYIT, ISTEMCI, yaprak, sec, bayt, servisSayisi } from "./istemci.mjs";

const TAM = yaprak(KAYIT);                    // birlesik govdenin tasidigi yaprak alan sayisi

function tekKenar(i) {                        // her istemci ayni birlesik govdeyi alir
  const kullanilan = yaprak(sec(KAYIT, i.alan));
  return { istek: i.gonderi, bayt: i.gonderi * bayt(KAYIT), tasinan: i.gonderi * TAM,
    kullanilmayan: i.gonderi * (TAM - kullanilan), icIstek: 2 * i.gonderi };
}

function onYuz(i) {                           // her istemci turu icin ayri kenar birimi
  const govde = i.gonderi === 1 ? sec(KAYIT, i.alan)
    : Array.from({ length: i.gonderi }, () => sec(KAYIT, i.alan));
  return { istek: 1, bayt: bayt(govde), tasinan: yaprak(govde), kullanilmayan: 0,
    icIstek: servisSayisi(i.alan) };
}

const ALAN = ["istek", "bayt", "tasinan", "kullanilmayan", "icIstek"];
for (const [ad, olc] of [["tek kenar", tekKenar], ["on yuz icin backend", onYuz]]) {
  console.log(`\n-- ${ad} --`);
  console.log(`${"istemci".padEnd(15)}${ALAN.map((a) => a.padStart(14)).join("")}`);
  let t = Object.fromEntries(ALAN.map((a) => [a, 0]));
  for (const [i, tanim] of Object.entries(ISTEMCI)) {
    const r = olc(tanim);
    ALAN.forEach((a) => { t[a] += r[a]; });
    console.log(`${i.padEnd(15)}${ALAN.map((a) => String(r[a]).padStart(14)).join("")}`);
  }
  console.log(`${"toplam".padEnd(15)}${ALAN.map((a) => String(t[a]).padStart(14)).join("")}`);
  console.log(`kenar birimi = ${ad === "tek kenar" ? 1 : Object.keys(ISTEMCI).length}, ` +
    `bir alan eklendiginde etkilenen istemci = ${ad === "tek kenar" ? Object.keys(ISTEMCI).length : 1}, ` +
    `servisin sunmasi gereken toplu uc = ${ad === "tek kenar" ? 0 : 2}`);
}

// K01 Kabaca Buyukluk Hesabi: V5 = 480 bayt (varsayim), tepe okuma 416.67 istek/s (hesap).
// Olcek: modelin durum govdesi 115 bayt, K01'in takip yaniti 480 bayt.
const V5 = 480, OKUMA_TEPE = 416.67, DURUM_BAYT = bayt(sec(KAYIT, ["takipNo", "durum", "bolge",
  "guncellenme", "rota"]));
const OLCEK = V5 / DURUM_BAYT;
const mbit = (istek, bayt) => (istek * bayt * 8) / 1e6;
console.log(`\ndurum govdesi = ${DURUM_BAYT} bayt, K01 olcegi = ${OLCEK.toFixed(4)} (480 / ${DURUM_BAYT})`);

console.log(`${"yerlesim".padEnd(21)}${"istek/s".padStart(10)}${"bayt/istek".padStart(12)}${"Mbit/s".padStart(9)}`);
for (const [ad, olc] of [["tek kenar", tekKenar], ["on yuz icin backend", onYuz]]) {
  let istek = 0, toplamBayt = 0;
  for (const tanim of Object.values(ISTEMCI)) {
    const r = olc(tanim);
    istek += OKUMA_TEPE * tanim.pay * r.istek;
    toplamBayt += OKUMA_TEPE * tanim.pay * r.bayt * OLCEK;
  }
  console.log(`${ad.padEnd(21)}${istek.toFixed(2).padStart(10)}` +
    `${(toplamBayt / istek).toFixed(0).padStart(12)}${((toplamBayt * 8) / 1e6).toFixed(2).padStart(9)}`);
}
console.log(`K01 (tek istemci turu)${OKUMA_TEPE.toFixed(2).padStart(9)}${String(V5).padStart(12)}` +
  `${mbit(OKUMA_TEPE, V5).toFixed(2).padStart(9)}`);

// T2 duyarliligi: mobil payi 0.60 yerine 0.30, aradaki fark web sayfasina gecerse
const T2 = { "mobil kart": 0.3, "web sayfasi": 0.6, "satici paneli": 0.1 };
for (const [ad, olc] of [["tek kenar", tekKenar], ["on yuz icin backend", onYuz]]) {
  let istek = 0, toplamBayt = 0;
  for (const [i, tanim] of Object.entries(ISTEMCI)) {
    const r = olc(tanim);
    istek += OKUMA_TEPE * T2[i] * r.istek;
    toplamBayt += OKUMA_TEPE * T2[i] * r.bayt * OLCEK;
  }
  console.log(`T2 mobil 0.30 -> ${ad.padEnd(21)}${istek.toFixed(2).padStart(9)} istek/s` +
    `${((toplamBayt * 8) / 1e6).toFixed(2).padStart(7)} Mbit/s`);
}
-- tek kenar --
istemci                 istek          bayt       tasinan kullanilmayan       icIstek
mobil kart                  1           183            11             8             2
web sayfasi                 1           183            11             4             2
satici paneli               5           915            55            25            10
toplam                      7          1281            77            37            14
kenar birimi = 1, bir alan eklendiginde etkilenen istemci = 3, servisin sunmasi gereken toplu uc = 0

-- on yuz icin backend --
istemci                 istek          bayt       tasinan kullanilmayan       icIstek
mobil kart                  1            78             3             0             1
web sayfasi                 1           115             7             0             1
satici paneli               1           551            30             0             2
toplam                      3           744            40             0             4
kenar birimi = 3, bir alan eklendiginde etkilenen istemci = 1, servisin sunmasi gereken toplu uc = 2

durum govdesi = 115 bayt, K01 olcegi = 4.1739 (480 / 115)
yerlesim                istek/s  bayt/istek   Mbit/s
tek kenar                583.34         764     3.56
on yuz icin backend      416.67         569     1.90
K01 (tek istemci turu)   416.67         480     1.60
T2 mobil 0.30 -> tek kenar               583.34 istek/s   3.56 Mbit/s
T2 mobil 0.30 -> on yuz icin backend     416.67 istek/s   2.05 Mbit/s

Kullanılmayan Alan ve İstek Sayısı

Tek kenarda üç istemcinin toplam 7 isteği 77 alan taşıyor ve bunun 37’si kullanılmıyor — taşınan alanın yüzde kırk sekizi. Dağılım eşit değil: mobil kart 11 alanın 8’ini, web sayfası 4’ünü, satıcı paneli beş kayıt boyunca 25’ini kullanmıyor. En küçük istemci en çok fazlalığı taşıyor, çünkü birleşik gövde en geniş istemcinin ihtiyacına göre biçimlenmiştir.

Ön yüz için backend yerleşiminde bu sayı sıfırlanıyor; ilginç olan yanı istek sayısıdır. Toplam istek 7’den 3’e iniyor ve düşüşün tamamı satıcı panelinden geliyor: panel beş gönderi için beş istek yaparken tek istekte liste alıyor. Bu, Web API Tasarımı kursunda ölçülen N+1 örüntüsünün kenardaki hâlidir — liste getirip her satır için ayrı istek yapan yerleşim. Ön yüz için backend onu ortadan kaldırmıyor, kenarın arkasına taşıyor: icIstek sütunu paneli 10’dan 2’ye indiriyor ama sıfıra indirmiyor.

Gövde baytı da 1281’den 744’e, 0,58 katına iniyor. Bu sayı taşınan alanın 77’den 40’a inmesiyle aynı yönde ama aynı oranda değil; alan sayısı 0,52 katına inerken bayt 0,58 katına iniyor, çünkü kısa alan adları ve zarf karakterleri her gövdede sabit bir pay tutar.

Ödenen Sayılar

Üç sayı büyüyor. Birincisi kenar birimi sayısı: 1’den 3’e. Her birim toplama kodunu kendi içinde tekrarlar, yani ilk dersin ölçtüğü “tekrarlanan satır” sorunu kenarın kendi içinde yeniden doğar. İkincisi istemci başına düzenleme: tek kenarda bir alan eklendiğinde etkilenen istemci 3, ön yüz için backend’de 1. Bu ikisi aynı ödünleşimin iki yarısıdır — birim sayısını artırmak, bir değişikliğin etki alanını daraltmanın bedelidir.

Üçüncüsü daha az görünür ve en bağlayıcısıdır: servisin sunmasi gereken toplu uc 0’dan 2’ye çıkıyor. Panelin listesini tek istekte karşılamak için ağ geçidinin iki servisten de toplu sorgu yapabilmesi gerekir; bu, kenarda alınan bir kararın servis sözleşmelerine yazdığı bir şarttır. Ön yüz için backend, yalnız kenarı değiştiren bir karar değildir.

Hesaba Dönüş

K01’in okuma cikis Mbit/s hesabı tek bir istemci türü varsayıyordu: 416,67 istek/s ve 480 baytlık yanıt, 1,60 Mbit/s. Modelin gövdeleri K01 ölçeğine çevrilir — modelin durum gövdesi 115 bayt, K01’in takip yanıtı 480 bayt, ölçek 4,1739 — ve T2 payları uygulanır.

Tek kenarda uçtaki hız 583,34 istek/s, istek başına gövde 764 bayt, çıkış 3,56 Mbit/s: K01’in sayısının 2,23 katı. Hızın 416,67’yi aşması satıcı panelinin beş isteğindendir; gövdenin büyümesi ise birleşik gövdenin herkese gitmesindendir. Ön yüz için backend yerleşiminde hız 416,67’ye, gövde 569 bayta ve çıkış 1,90 Mbit/s’ye iniyor — K01’in 1,60’ının 1,19 katı. Fark kalıcıdır ve gereksinimden gelir: ücret bilgisi K01’in 480 baytında yoktu.

Duyarlılık iki yerleşimi ayırıyor. Mobil payı 0,60’tan 0,30’a inip fark web sayfasına geçtiğinde tek kenarın sayıları hiç oynamıyor: 583,34 istek/s ve 3,56 Mbit/s. Ön yüz için backend’de ise çıkış 1,90’dan 2,05 Mbit/s’ye çıkıyor. Bu, tek kenarın istemci karışımına duyarsız olduğunu söylüyor — herkes aynı gövdeyi aldığı için karışım değişse de bant genişliği değişmez. Duyarsızlık burada bir üstünlük değil: sayı, en geniş istemcinin ihtiyacına kilitlenmiştir ve mobil istemci payı ne kadar artarsa artsın küçülmez.

Özet

  • Ön yüz için backend, kenarı istemci türü başına ayrı bir birime böler; her birim yalnız o istemcinin alanlarını döndürür.
  • Tek kenarda üç istemcinin 7 isteği 77 alan taşıyor ve 37’si kullanılmıyor (yüzde kırk sekiz); en küçük istemci en çok fazlalığı taşıyor.
  • Ön yüz için backend kullanılmayan alanı 0’a, isteği 7’den 3’e, gövdeyi 1281’den 744 bayta indiriyor; istek düşüşünün tamamı satıcı panelinin liste isteğinden gelir.
  • Ödenen sayılar: kenar birimi 1’den 3’e, servisin sunması gereken toplu uç 0’dan 2’ye çıkıyor; karşılığında bir alan eklendiğinde etkilenen istemci 3’ten 1’e iniyor.
  • K01’e dönüş: 416,67 istek/s ve 480 bayt ile 1,60 Mbit/s olan çıkış, tek kenarda 583,34 istek/s ve 3,56 Mbit/s, ön yüz için backend’de 416,67 istek/s ve 1,90 Mbit/s oluyor.
  • T2 duyarlılığı iki yerleşimi ayırıyor: mobil payı yarıya indiğinde tek kenar 3,56 Mbit/s’de sabit kalıyor, ön yüz için backend 1,90’dan 2,05’e çıkıyor — tek kenarın sayısı en geniş istemciye kilitlidir.

Sonraki Adım

Buraya kadarki dört ders kenarı bir bileşen olarak ele aldı ve her kararı o bileşenin içine yazdı: yönlendirme, toplama, boşaltılan denetimler, istemciye özel gövde. Bu dersin ödediği sayılardan biri bu yaklaşımın sınırını gösteriyor — kenar birimi sayısı arttıkça aynı ortak kod her birimde tekrarlanıyor. Ortak kodu paylaşmanın bir yolu onu kitaplık olarak gömmektir, ama o zaman sürümü değiştiğinde bütün birimler yeniden yayınlanır. Sonraki ders başka bir yolu ele alır: ortak işi aynı dağıtım biriminde koşan ayrı bir sürece vermek. Elçi ve yan araba kalıpları bu yerleşimi tanımlar ve ölçülen şey yeniden yayınlanan birim sayısı ile dağıtım birimi başına süreç sayısı olur.

İlerlemeni kaydetmek ve not almak için Giriş yap

Notlarım

Not almak için giriş yapmalısın.

Aramak için yazmaya başlayın.

↑↓ Esc gezin · aç · kapat