İçeriğe geç
academia.sh

Ders 01 / 16

Yük Dengeleyiciler

Aktarım katmanında çalışan dengeleyici bağlantı dağıtır, uygulama katmanında çalışan istek dağıtır; aynı kırk öznede biri 17 özneyi 438 birimle aşırır, öteki 16 özneyi 310 birimle, ve aktarım katmanının kendi göstergesi kırk öznenin kırkında da aynı sayıyı gösterir.

İçindekiler

Önceki kurs sınırın nasıl yazıldığını ölçtü: hangi güç, hangi eşik, hangi kural dizisi, hangi ölçüt. Hiçbir ders sınırın yazıldıktan sonra ne olduğunu sormadı. Yazılan bir sınır yaşayan bir sistemde durur; yükü değişir, sapması kimseye görünmez. Sınırı yazmak ile yazılanı işletmek ayrı işlerdir.

Buraya kadarki her karar tek bir nesne içindi: bir paket, bir akış, bir istemci, bir kural satırı. İşletmede böyle çalışılmaz. Operatör tek tek nesneye dokunmaz; bir kaldıraca dokunur — bir dağıtım kuralı, bir örnekleme oranı, bir şablon — ve o kaldıraç kırk özneye birden uygulanır. Bu kursun sorusu budur, ve ilk kaldıraç yük dengeleyicidir.

Kaldıraç ve Özne

Kurs boyunca aynı topluluk ölçülür: kırk özne. Özneler birbirinin aynı değildir. Kapasiteleri 22 ile 99 birim arasında dağılır, gecikmeleri ayrıdır, üç hizmet sınıfından birine aittir ve dokuzu ilerideki bir kaldıracın dışında kalması gereken özel aygıtlardır. Toplulukta ne olduğunu biz yazdığımız için biliriz; ölçümün kâhini (oracle) kurgunun kendisidir.

Ölçülen şey kaldıracın niteliği değildir. Bir işletme kararının sayısı, kaç özneye yanlış hizmet ettiğidir. Kaldıraç tektir, özne kırktır ve aradaki farkı taşıyan azınlığa bu kursta kaldıracın kuyruğu (tail) denir. Kuyruk bu kursta yalnız bu duyudadır: kaldıracın yanlış hizmet ettiği özneler kümesi.

Kuyruğun iki ayrı sayısı vardır ve her ölçümde ikisi de yazılır. Birincisi kaç özne kuyrukta kaldığıdır. İkincisi, kuyruktakilerin kaçının kaldıracın kendi göstergesinde görünmediğidir. Bu ders ikincinin en temiz örneğiyle başlar.

Ortalamanın neden yeterli olmadığı burada görülür. Kırk özneye bölünen bir yük, ortalamada her zaman kapasitenin altında kalabilir ve aynı anda birkaç özne kapasitesinin çok üstünde olabilir. Ortalama, dağılımın iki ucunu birden aynı sayıya katar: aşan öznenin fazlası ile boşta duran öznenin eksiği toplamda birbirini götürür. Kuyruk ölçüsü tam olarak bu götürmeyi reddeder. Bu yüzden aşağıdaki her tabloda aşan özne ile boşta kalan birim ayrı sütunlardır ve hiçbir ölçümde tek bir sayıya indirgenmez.

Dengeleyici Neyi Okur

Yük dengeleyici (load balancer), gelen işi bir özne kümesine bölen aracıdır. Rolü ve katmanlara göre ayrımı Sistem Tasarımı müfredatının Trafik Katmanı kursunda kuruldu; o anlatı burada tekrarlanmaz. Fark tek cümledir: orada dengeleyicinin tasarımı ölçüldü, burada tek bir kaldıracın kapasitesi eşit olmayan kırk öznede bıraktığı kuyruk ölçülür.

Ayrımın bu ders için önemli olan yanı, dengeleyicinin neyi okuyabildiğidir.

Aktarım katmanında çalışan dengeleyici bağlantı dörtlüsünü görür: kaynak ve hedef adres, kaynak ve hedef bağlantı noktası. Bağlantının içindekini açmaz. Dağıtım birimi bu yüzden bağlantıdır: gelen her yeni bağlantıyı bir özneye bağlar ve o bağlantı kapanana kadar oraya bağlı kalır.

Uygulama katmanında çalışan dengeleyici bağlantıyı kendinde sonlandırır, isteği okur ve öznelere kendi açtığı bağlantılar üzerinden iletir. Dağıtım birimi istektir. İsteğin yolunu ve başlık alanlarını okuyabildiği için özneleri sınıflara ayırıp her sınıfı ayrı bir havuza yollayabilir.

İkisi arasındaki seçim bir yapılandırma satırıdır:

# öğretilen yapılandırma dökümü, çalıştırılmamıştır

dengeleyici aktarim {
  dinle    *:443
  birim    baglanti
  kural    sirali
  havuz    ozne-01 ... ozne-40
}

dengeleyici uygulama {
  dinle    *:443
  birim    istek
  kural    sirali
  eslesme  /etkilesim/*  -> havuz-etkilesim
  eslesme  /toplu/*      -> havuz-toplu
  eslesme  /yedek/*      -> havuz-yedek
}

Bu döküm bir belge, bir ölçüm değil. Sayılar aşağıdaki ölçümden gelir.

Denetim de Bir Kaldıraçtır

Dengeleyicinin dağıtımdan başka bir kaldıracı daha vardır: sağlık denetimi (health check). Bir aralık, bir zaman aşımı ve ard arda kaç başarısızlığın öznenin havuzdan çıkarılmasına yeteceği yazılır. Yazılan bu üç sayı da tek tek özneye değil, kırkına birden uygulanır.

Denetimin var olup olmamasının hizmete etkisi Sistem Tasarımı müfredatının Trafik Katmanı kursunda ölçüldü ve burada tekrarlanmıyor. Fark tek cümledir: orada denetimin varlığı ölçüldü, burada tek bir eşiğin kırk öznede bıraktığı kuyruk.

Eşiğin kuyruğu iki uçludur ve uçlar birlikte kapanmaz. Zaman aşımı gevşek yazılırsa, yavaşlamış ama hâlâ yanıt veren özne sağlıklı sayılır ve kendisine iş yönlendirilmeye devam eder; kuyruk, o özneye giden isteklerdir. Zaman aşımı sıkı yazılırsa, gecikmesi zaten yüksek olan özneler denetimden geçemez ve havuzdan düşer; kuyruk bu kez düşen öznelerin yükünü üstlenen kalan öznelerdir. Kırk öznenin gecikmeleri birbirinden ayrı olduğu için tek bir zaman aşımı ikisini birden yapamaz.

Denetimin okuduğu şeyin öznenin kendi bildirimi olduğu da unutulmamalı: özne sağlıklı olduğunu söyler, denetim buna inanır. Uygulama Katmanı Protokolleri kursunun bıraktığı gözlem burada da geçerlidir — bildirimi doğrulayan bir şey yoktur, yalnızca bildirimin gelmemesi bir bilgidir.

Aynı ikilik özne havuzdan çıkarılırken de görülür. Çıkarma anında var olan bağlantılar kesilmez, bir boşaltma (draining) süresi tanınır. Bu süre de tek bir sayıdır ve kırk özneye birden uygulanır: uzun yazılırsa arızalı öznenin üstündeki iş uzun süre orada kalır, kısa yazılırsa yarım kalmış işler kesilir. Kaldıraç aynı kaldıraçtır; yalnız kuyruğun kimden oluştuğu değişir.

Kaldıracın Kendi Göstergesi

Aktarım katmanındaki dengeleyicinin sayabildiği tek şey bağlantıdır. Sıralı bir kuralla dağıtım yaptığında kendi sayacı, tanımı gereği, kırk öznenin kırkında da aynı değeri gösterir. Gösterge düzdür ve düz olması kuralın doğruluğunun kanıtı gibi okunur.

Oysa bağlantıların taşıdığı iş eşit değildir. Kalıcı bağlantı bir isteği de taşır, otuz isteği de. Dengeleyici bunu göremez, çünkü göremediği şey bağlantının içidir. Eşit dağıtılan şey ile öznenin gerçekten yüklendiği şey aynı değildir, ve ikisinin arasındaki fark kaldıracın göstergesine hiç yansımaz.

Uygulama katmanındaki dengeleyici bu farkı kapatır: istek sayar, istek dağıtır, göstergesi gerçek iş birimini gösterir. Ölçüm bunun ne kadarını çözdüğünü sorar.

Ölçümün varsayımları:

  • TY1 — Kırk özne kursun sabit kümesidir; kapasite, gecikme ve sınıf alanları ölçüm boyunca değiştirilmez. Kâhin bu kümenin kendisidir.
  • TY2 — Dört yüz bağlantı üretilir ve her biri değişken sayıda istek taşır. Bağlantıların sekizde biri uzun ömürlüdür ve yirmi ile kırk arasında istek taşır; kalanı bir ile dört arasında.
  • TY3 — Dengeleyici sıralı kuralla dağıtır. Kural üç ölçümde de aynıdır; değişen tek şey dağıtımın birimidir — bağlantı, istek, ya da sınıf havuzundaki istek.
  • TY4 — Aktarım katmanındaki dengeleyici bağlantının taşıdığı istek sayısını okuyamaz; uygulama katmanındaki okur. Kurgu bu ayrımı doğrudan kodlar.
  • TY5 — Kapasite bir öznenin aynı anda karşılayabileceği istek sayısıdır. Bu sayının üstüne çıkan her birim aşımdır; altında kalan her birim boştadır.
  • TY6 — Ölçüm bir ağ ölçümü değildir; hiçbir bağlantı açılmaz. Sayılan şey kurgudaki dağıtımın kendisidir.

Ölçüm

"""Katman 4 ile katman 7 dengeleme: ayni kirk oznede iki kaldirac."""
TOHUM = 20260812
SINIFLAR = ("etkilesim", "toplu", "yedek")


def uretec(tohum):
    d = tohum % 2147483646 + 1

    def r(n):
        nonlocal d
        d = (d * 48271) % 2147483647
        return d % n
    return r


def ozneler(sayi=40, tohum=TOHUM):
    r, liste = uretec(tohum), []
    for i in range(sayi):
        liste.append({"no": i + 1, "kapasite": 20 + r(81), "gecikme": 5 + r(45),
                      "sinif": SINIFLAR[r(3)], "ozel": r(9) == 0})
    return liste


def baglantilar(sayi=400, tohum=TOHUM + 11):
    r, liste = uretec(tohum), []
    for i in range(sayi):
        uzun = r(8) == 0
        liste.append({"istek": 20 + r(21) if uzun else 1 + r(4),
                      "sinif": SINIFLAR[r(3)]})
    return liste


def katman4(bag, oz):
    """Bagi dagitir; bagin kac istek tasidigini bilmez."""
    pay = {o["no"]: 0 for o in oz}
    sayac = {o["no"]: 0 for o in oz}
    for i, b in enumerate(bag):
        o = oz[i % len(oz)]
        sayac[o["no"]] += 1
        pay[o["no"]] += b["istek"]
    return pay, sayac


def katman7(bag, oz, havuzla):
    """Istegi dagitir; istenirse sinifin havuzuna."""
    havuz = {s: [o for o in oz if o["sinif"] == s] for s in SINIFLAR}
    sayac = {s: 0 for s in SINIFLAR}
    pay, i = {o["no"]: 0 for o in oz}, 0
    for b in bag:
        h = havuz[b["sinif"]] if havuzla else oz
        for _ in range(b["istek"]):
            if havuzla:
                pay[h[sayac[b["sinif"]] % len(h)]["no"]] += 1
                sayac[b["sinif"]] += 1
            else:
                pay[h[i % len(h)]["no"]] += 1
                i += 1
    return pay


def asan(pay, oz):
    s = b = 0
    for o in oz:
        f = pay[o["no"]] - o["kapasite"]
        if f > 0:
            s, b = s + 1, b + f
    return s, b


oz, bag = ozneler(), baglantilar()
print(f"özne {len(oz)} | toplam kapasite {sum(o['kapasite'] for o in oz)} | "
      f"en küçük {min(o['kapasite'] for o in oz)} en büyük {max(o['kapasite'] for o in oz)}")
print(f"bağlantı {len(bag)} | istek {sum(b['istek'] for b in bag)}")
for s in SINIFLAR:
    h = [o for o in oz if o["sinif"] == s]
    print(f"  {s:10s} özne {len(h):2d} kapasite {sum(o['kapasite'] for o in h):5d} "
          f"istek {sum(b['istek'] for b in bag if b['sinif'] == s):5d}")

pay4, sayac = katman4(bag, oz)
olcum = (("katman 4 (bağlantı)", pay4), ("katman 7 (istek)", katman7(bag, oz, False)),
         ("katman 7 (sınıf havuzu)", katman7(bag, oz, True)))
print()
print(f"{'kaldıraç':<24s} {'aşan':>5s} {'aşan birim':>11s} {'boşta':>7s} "
      f"{'en az':>6s} {'en çok':>7s} {'hiç yük almayan':>16s}")
for ad, pay in olcum:
    s, b = asan(pay, oz)
    print(f"{ad:<24s} {s:5d} {b:11d} "
          f"{sum(max(0, o['kapasite'] - pay[o['no']]) for o in oz):7d} "
          f"{min(pay.values()):6d} {max(pay.values()):7d} "
          f"{sum(1 for o in oz if pay[o['no']] == 0):16d}")
print()
print(f"katman 4'ün kendi göstergesi — bağlantı sayısı: en az {min(sayac.values())}, "
      f"en çok {max(sayac.values())}; kapasitesini aşan {asan(pay4, oz)[0]} özne "
      f"bu göstergede görünmez")
özne 40 | toplam kapasite 2336 | en küçük 22 en büyük 99
bağlantı 400 | istek 2193
  etkilesim  özne 11 kapasite   580 istek   655
  toplu      özne 20 kapasite  1346 istek   700
  yedek      özne  9 kapasite   410 istek   838

kaldıraç                  aşan  aşan birim   boşta  en az  en çok  hiç yük almayan
katman 4 (bağlantı)         17         438     581     21     164                0
katman 7 (istek)            16         310     453     54      55                0
katman 7 (sınıf havuzu)     18         558     701     35      94                0

katman 4'ün kendi göstergesi — bağlantı sayısı: en az 10, en çok 10; kapasitesini aşan 17 özne bu göstergede görünmez

Kuyruk Nerede

Son satır dersin çekirdeğidir. Aktarım katmanındaki dengeleyicinin sayacı kırk öznenin kırkında da 10 gösteriyor; en az ile en çok arasında hiç fark yok. Aynı anda kırk öznenin 17’si kapasitesini aşmış durumda ve gerçek yük 21 ile 164 arasında dağılıyor. Kaldıraç doğru çalışıyor — kendi tanımına göre. Kuyruk, kaldıracın ölçtüğü boyutta görünmüyor.

Uygulama katmanına geçmek bunun bir kısmını çözüyor. İstek dağıtıldığında yük 54 ile 55 arasına sıkışıyor; artık gösterge gerçekten dağıtılan şeyi gösteriyor. Ama aşan özne 17’den 16’ya, aşan birim 438’den 310’a iniyor. Kırk öznede kazanılan tek bir özne. Kırk öznelik bir kümede ölçülebilen en küçük fark 1/40 = 0,025’tir; bir öznelik kazanç tam olarak o eşiktedir ve daha küçük bir fark bu kümeyle savunulamaz.

Kazancın küçük kalmasının nedeni açık. Uygulama katmanı eşit istek dağıtıyor, ama özneler eşit değil: kapasiteler 22 ile 99 arasında. Herkese 54 istek düşürmek, 22 kapasiteli özne için üç katlık bir aşım, 99 kapasiteli özne için yarı yarıya boşluktur. Kaldıracın çözünürlüğünü artırmak kuyruğu taşıdı, kaldırmadı.

Üçüncü satır bunu daha net söylüyor. Sınıf havuzu, uygulama katmanının kazandırdığı asıl yeteneği kullanıyor: istek yoluna bakıp özneyi seçmek. Sonuç daha kötü — aşan özne 18, aşan birim 558. Sebep üstteki üç satırda duruyor: yedek sınıfı 9 özne ve 410 kapasite taşıyor ama 838 istek alıyor; toplu sınıfı 20 özne ve 1346 kapasiteyle 700 istek alıyor. Havuzlara ayırmak, kapasitesi olan özneleri kullanılamaz hâle getirdi. Boşta kalan birim 453’ten 701’e çıktı.

Dördüncü sütun bu yüzden ölçümün parçasıdır. Üç kaldıraçta da hiç yük almayan özne 0: hiçbir özne dışarıda kalmıyor, kimse kapının önünde değil. Yine de sistemde 581, 453 ve 701 birim boşta duruyor. Yalnız aşımı sayan bir gösterge bu sütunu hiç göstermez ve kapasitenin dörtte birinin kullanılmadığını söylemez.

Bu tabloyu yazabilmemizin tek nedeni kapasiteleri bilmemizdir. İşletmede böyle bir sütun hazır durmaz: dengeleyici öznenin kapasitesini ölçmez, ona verdiği işi sayar. Aşım sütunu ancak kapasite başka bir yerden — özne başına ayrı bir ölçümden — getirildiğinde hesaplanabilir; getirilmezse gösterge yine düzdür ve yine yanlış değildir. Bu dersin kurgusunda kâhin elimizde olduğu için iki sütunu yan yana koyabiliyoruz, ve kursun geri kalanının sorduğu şey tam olarak budur: kaldıracın göstergesi ile kaldıracın sonucu arasındaki fark nereden okunur? Sonraki iki konu, önce trafiğin kendisinde, sonra telemetride bu farkı sayacak.

Özet

  • İşletmenin birimi tek nesne değil kaldıraçtır: operatör bir kural yazar, kural kırk özneye birden uygulanır ve ölçülen şey kaldıracın yanlış hizmet ettiği azınlık, yani kuyruktur.
  • Aktarım katmanındaki dengeleyici bağlantı dağıtır ve bağlantının taşıdığı isteği göremez; kendi göstergesi kırk öznede de 10 gösterirken gerçek yük 21 ile 164 arasındadır ve 17 özne kapasitesini aşmıştır.
  • Uygulama katmanındaki dengeleyici istek dağıtır ve yükü 54–55 aralığına sıkıştırır; aşan özne yalnız 16’ya, aşan birim 310’a iner. Kırk öznede kazanç bir öznedir.
  • Eşit istek dağıtmak eşit yük değildir: kapasiteler 22 ile 99 arasında olduğu için aynı pay bir özne için aşım, başkası için boşluktur.
  • Sınıf havuzuna ayırmak kuyruğu büyütür — aşan özne 18, boşta kalan birim 701 — çünkü havuzların kapasitesi ile aldıkları istek birbirini tutmaz.
  • Sağlık denetimi de tek bir kaldıraçtır ve kuyruğu iki uçludur: gevşek eşik yavaşlamış özneye iş yollamayı sürdürür, sıkı eşik gecikmesi yüksek özneleri düşürüp yüklerini kalanlara bindirir; kırk öznenin gecikmesi ayrı olduğu için tek eşik ikisini birden kapatmaz.

Sonraki Adım

Bu derste kural üç ölçümde de aynıydı: sıralı dağıtım. Değişen tek şey dağıtımın birimiydi ve birim değiştirmek kuyruğu kırkta bir kadar oynattı. Öyleyse asıl soru birim değil kuralın kendisidir: yükü kapasiteye göre bölen ya da her adımda en az yüklü özneyi seçen bir kural, kuyruğu gerçekten kaldırır mı? Sonraki ders üç dağıtım kuralını aynı kırk öznede ve iki ayrı yükte yan yana koyar, ve kuralı iyileştirmenin kuyruğa ne yaptığını — kaldırıp kaldırmadığını, yoksa yalnız kimin kuyrukta olacağını mı seçtiğini — sayar.

İ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