İçeriğe geç
academia.sh

Ders 09 / 20

Kuyruk ve Konu Servisleri

Kuyruğun hizmet olarak alınmasının getirdiği kısıtlar: geriye kalan beş yapılandırma kaleminin sayılması, görünürlük süresinin altı değerde taranarak kısa sürenin ürettiği çift işleme ile uzun sürenin ürettiği kurtarma gecikmesinin ölçülmesi, ölü mektup kutusuna düşme süresinin türetilmiş bir sayı olması ve kuyruk ile konu arasındaki fan-out farkının teslim ve yapılandırma kalemi cinsinden karşılaştırılması.

İçindekiler

Önceki ders olayları kurallara göre hedeflere yönlendirdi ve her teslimi başarılı saydı. Gerçek akışta bu varsayım tutmaz: hedef kısılmış olabilir, hata verebilir, hiç ayakta olmayabilir. Aradaki tamponu kuyruk servisi kurar — olayı tutar, tüketici hazır olana kadar bekletir, başarısız işi yeniden görünür kılar.

Kuyruğun mekaniği yeni değildir. Eşzamansız İşleme kursunun Teslim Semantiği dersi onay ile etkinin sırasını ölçtü ve en az bir kez ile tekilleştirmenin farkını sayılarla gösterdi; o ölçüm burada tekrarlanmaz ve sonuçları veri olarak alınır. Bu dersin sorusu başkadır: kuyruk kendi işlettiğin bir aracı değil de bir hizmet olduğunda ne değişir?

Devredilen Kararlar ve Geriye Kalan Yüzey

Hizmet olarak alınan bir kuyrukta şu kararlar elden çıkar: kaç düğüm çalışacağı, iletinin kaç kopyayla saklanacağı, diskin nereye yazacağı, sürümün ne zaman yükseltileceği, kuyruk derinliği arttığında kaç tüketicinin ekleneceği. Sonuncusu en önemlisidir; kuyruk servisi işlev çalıştırma ortamına bağlandığında ölçekleme kararı da devredilir — derinlik arttıkça örnek eklenir, azaldıkça silinir.

Devredilen ölçekleme kararının bedeli, artışın hızının da elden çıkmasıdır. Kuyruğa bir anda 400 ileti düştüğünde kaç örneğin ne kadar sürede ekleneceğini belirleyen kural hizmetin içindedir; dışarıdan görünen tek şey bir tavan sayısıdır. Bu, iki yönlü bir kısıt üretir. Artış yavaşsa gece toplu işi beklenenden geç biter ve kuyruk derinliği saatlerce yüksek kalır. Artış hızlıysa aynı anda uyanan yüzlerce örnek, arkadaki veritabanının bağlantı havuzunu tüketir — kuyruk kendi ölçeğini bulur, ama bulduğu ölçek aşağı akıştaki bir kısıtı aşar. Kuyruk derinliğine bakan bir tüketici sayısını kendi ayarlamak bu ikisini de çözerdi; devredilen kararla birlikte o kol da gitmiştir. Geriye kalan tek denetim, tavanın kendisini düşürmektir ve bunun bedeli birinci durumun kalıcı hale gelmesidir.

Geriye kalan yüzey küçüktür ve sayılabilir. Bu derste kullanılan modelde kuyruk başına beş kalem vardır: görünürlük süresi, azami teslim sayısı, ölü mektup kutusu, saklama süresi, yığın boyu. Beş kalem, devredilen onca kararın karşılığında elde kalan tüm denetimdir. Kısıt buradadır: ayarlanamayan hiçbir şey düzeltilemez de. Saklama süresi dolan ileti silinir ve bu silme, önceki dersteki eşleşmeyen olay gibi, sessizdir.

Ölçüm yine kurgu bölgesel ölçüm ağı üzerinde yapılır: sayaç okumaları bir kuyruğa yazılır, doğrulama işlevi kuyruktan okur, doğrulanan okuma fatura akışına girer.

  • OS7. İş yükü 400 iletidir; işleme süresi üç kümede toplanır — olağan doğrulama 2–6 birim, toplu okuma 12–31 birim, gecikmiş yığın 40–69 birim.
  • OS8. İletilerin 12’si zehirlidir (her denemede başarısız), 16’sında tüketici işi bitirmeden ölür; iki küme çakışmaz ve konum olarak sabittir.
  • OS9. Azami teslim sayısı 5’tir; bu sayıya ulaşan ileti ölü mektup kutusuna taşınır.
  • OS10. Görünürlük süresi dolduğunda ileti yeniden görünür olur; hâlâ çalışan tüketici durdurulmaz, yani ikinci tüketici işi koşut olarak yeniden yapar.
  • OS11. Süre birimi kurgudur; ölçülen şey oranlardır, saniye değildir.
  • OS12. Model yalnız tek bir kuyruğu kurar; sıra, bölümleme ve taşıma gecikmesi ölçülmez.

Görünürlük Süresi

Görünürlük süresi (visibility timeout), bir tüketici iletiyi aldıktan sonra iletinin kuyrukta ne kadar gizli kalacağıdır. Tüketici bu süre içinde işi bitirip iletiyi silerse iş biter; bitiremezse ileti yeniden görünür olur ve başka bir tüketici onu alır. Tek sayıdır ve iki ayrı şeyi birden belirler: yavaş işin ne zaman ikinci kez başlatılacağını ve ölü tüketicinin elindeki işin ne zaman kurtarılacağını. Bu iki gereksinim ters yönlere çeker; aşağıdaki tarama ikisini de aynı iş yükü üzerinde sayar.

// gorunurluk.mjs — kuyruk servisi modeli: gorunurluk suresi degisince ne olur
// Model: gercek bir kuyruk degil, hizmetin tek ayarinin sonuclarinin sayilmasi.
const TOHUM = 20260518;                        // uretec tohumu: kosum tekrarlanabilir
let d = TOHUM;
const r = () => (d = (d * 1103515245 + 12345) % 2147483648) / 2147483648;

const N = 400, AZAMI = 5;                      // AZAMI teslimden sonra ileti olu mektup kutusuna
const ILETI = [];
for (let i = 0; i < N; i++) {
  const p = r();
  const sure = p < 0.88 ? 2 + Math.floor(r() * 5)        // olagan dogrulama: 2-6 birim
             : p < 0.97 ? 12 + Math.floor(r() * 20)      // toplu okuma: 12-31 birim
             : 40 + Math.floor(r() * 30);                // gecikmis yigin: 40-69 birim
  ILETI.push({ sure, zehirli: i % 33 === 7, coken: i % 25 === 3 });   // ikisi hic cakismaz
}
const ZEHIRLI = ILETI.filter((i) => i.zehirli).length;
const COKEN = ILETI.filter((i) => i.coken).length;

function kosum(T) {
  let teslim = 0, cift = 0, bekleme = 0;
  for (const i of ILETI) {
    if (i.zehirli) { teslim += AZAMI; continue; }         // her denemede yeniden basarisiz
    if (i.coken) { teslim += 2; bekleme += T; continue; } // tuketici oldu: T kadar gizli kalir
    const tur = Math.ceil(i.sure / T);                    // T dolmadan bitmeyen is yeniden gorunur
    teslim += tur;
    if (tur > 1) cift++;
  }
  return { teslim, cift, bekleme: bekleme / COKEN, olu: AZAMI * T };
}

console.log("gorunurluk".padEnd(12) + "cift isleme".padStart(12) + "toplam teslim".padStart(15) +
  "kurtarma gecikmesi".padStart(20) + "olu kutuya dusme".padStart(18));
for (const T of [5, 10, 20, 30, 60, 120]) {
  const s = kosum(T);
  console.log(String(T).padEnd(12) + String(s.cift).padStart(12) + String(s.teslim).padStart(15) +
    s.bekleme.toFixed(0).padStart(20) + String(s.olu).padStart(18));
}
const ENUZUN = Math.max(...ILETI.map((i) => i.sure));
console.log(`ileti: ${N}, zehirli: ${ZEHIRLI}, tuketicisi coken: ${COKEN}, ` +
  `en uzun is: ${ENUZUN} birim, tohum: ${TOHUM}`);
node gorunurluk.mjs
gorunurluk   cift isleme  toplam teslim  kurtarma gecikmesi  olu kutuya dusme
5                    102            745                   5                25
10                    40            562                  10                50
20                    28            505                  20               100
30                    11            480                  30               150
60                     5            469                  60               300
120                    0            464                 120               600
ileti: 400, zehirli: 12, tuketicisi coken: 16, en uzun is: 69 birim, tohum: 20260518

İlk satır kısa sürenin bedelini gösteriyor. Görünürlük süresi 5 birimken 102 ileti çift işlendi ve 400 iletilik iş yükü 745 teslime çıktı. Buradaki çift işleme, yeniden denemeden farklı bir şeydir: birinci tüketici hâlâ çalışırken ileti yeniden görünür olur ve ikinci tüketici aynı işi aynı anda yapar. Ölçüm ağında bu, aynı sayaç okumasının iki kez doğrulanması ve fatura akışına iki kez girmesi demektir.

Son satır uzun sürenin bedelidir. 120 birimde çift işleme sıfıra iner, ama tüketicisi ölen 16 ileti ortalama 120 birim gizli bekler — o süre boyunca kuyrukta görünmezdir, hiçbir tüketici alamaz, hiçbir ölçüt bir şey göstermez. Zehirli iletinin ölü mektup kutusuna düşmesi ise 600 birim sürer.

Bu ayrımın pratik sonucu, koşut çift işlemenin tekilleştirme bekçisini de zorlamasıdır. Bekçi “bu ileti daha önce işlendi mi” sorusunu sorar; koşut koşumda ikinci tüketici bu soruyu, birinci tüketici sonucunu henüz yazmadan sorar ve yanıt “hayır” olur. Sıralı yeniden denemede işe yarayan bekçi burada iki koşumu da geçirir. Çift işlemeyi kapatan şey bekçinin varlığı değil, bekçinin yazma anındaki tekillik kısıtına dayanmasıdır.

Aradaki kural çıktının son satırından okunur: en uzun iş 69 birimdir. Çift işlemenin sıfıra inmesi için görünürlük süresinin en uzun işi aşması gerekir; 60 birimde hâlâ 5 ileti çift işleniyor, 120’de sıfır. Yani işleme süresinin kuyruğu, kurtarma gecikmesinin alt sınırını belirler. Tek bir uzun iş türü, bütün kuyruğun kurtarma davranışını aşağı çeker.

Kısıtın etrafından dolaşmanın yolu, iş sürerken görünürlük süresini uzatmaktır: tüketici çalıştığını düzenli aralıklarla bildirir, servis de sayacı ileri alır. Bedeli iki kalemdir. Birincisi, 10 birimlik bir süreyle 69 birimlik bir işi tamamlamak için altı uzatma çağrısı gerekir — tek iletilik iş yedi isteğe çıkar ve istek başına ücretlendirilen bir hizmette bu doğrudan faturadır. İkincisi, tüketici artık işini yapmakla kalmaz, kendi ömrünü de yönetir; uzatmayı unutan ya da uzatma çağrısı hata alan tüketici birinci satırdaki çift işlemeye geri düşer.

Ölü Mektup Kutusunun Otomatikliği

Tablodaki son sütun, hiç kimsenin doğrudan ayarlamadığı bir sayıdır. Zehirli iletinin ölü mektup kutusuna düşmesi için geçen süre, azami teslim sayısı ile görünürlük süresinin çarpımıdır: 5 × 30 = 150, 5 × 120 = 600. İki ayrı kalem ayrı gerekçelerle seçilir, üçüncü bir sayı kendiliğinden ortaya çıkar. Kısıtın en sinsi biçimi budur — ayarlanan şeyle ölçülen şey aynı değildir.

Hizmet olmanın buradaki kazancı gerçektir: zehirli ileti elle ayıklanmaz, beşinci teslimden sonra otomatik olarak taşınır ve ana kuyruğu tıkamaz. Modelde 12 zehirli ileti, hangi görünürlük süresi seçilirse seçilsin, toplam 60 teslim harcayıp yoldan çekilir. Bunun karşılığında gelen kısıt şudur: ölü mektup kutusu öntanımlı olarak tüketicisi olmayan bir kuyruktur. İleti oraya taşınır, saklanır ve saklama süresi dolunca silinir. Kimse okumazsa sonuç, önceki dersteki sessiz düşmenin makbuzlu biçimidir — kayıp aynı kayıptır, yalnız bir yerde yazılıdır.

Kutuyu boşaltmanın yolu iletileri ana kuyruğa geri basmaktır ve bunun da bir sayısı vardır. Nedeni düzeltilmeden geri basılan 12 ileti yeniden beş kez teslim edilir; 60 teslim daha harcanır ve iletiler aynı kutuya döner. Geri basma bu yüzden bir onarım değil, bir sınamadır: önce zehirlenmenin nedeni bulunur, sonra kutu boşaltılır.

Saklama süresi de aynı biçimde bir üst sınırdır. Tüketici tarafı saklama süresinden uzun bir kesinti yaşarsa kuyruktaki iletiler tek tek silinmeye başlar ve kesinti bittiğinde kuyruk boş görünür. Ölçüm ağında bu, kesinti penceresine denk gelen sayaç okumalarının hiç faturalanmaması demektir. Kısıtın etrafından dolaşmanın yolu saklama süresini üst sınırına çekmektir; bedeli, kuyruğun bir yedekleme katmanı gibi kullanılmaya başlaması ve derinlik ölçütü izlenmiyorsa kaybın ancak fatura döneminde fark edilmesidir.

Kuyruk ile Konu Arasındaki Fark

İkinci servis türü aynı iletiyi birden çok tarafa verir. Fark tek cümleyle yazılır: kuyruk işi paylaştırır, konu iletiyi çoğaltır.

// fanout.mjs — ayni 400 olay iki servisten gecerse: kuyruk servisi ve konu servisi
const N = 400;
const KUYRUK_KALEM = 5;   // gorunurluk suresi, azami teslim, olu mektup kutusu, saklama, yigin boyu
const KONU_KALEM = 2;     // konunun kendi kalemleri: ad ve erisim kurali

console.log("tuketici".padEnd(10) + "kuyruk teslim".padStart(14) + "kuyruk kalem".padStart(14) +
  "konu teslim".padStart(13) + "konu kalem".padStart(12));
for (const k of [1, 2, 3, 4]) {
  const konuKalem = KONU_KALEM + k * (KUYRUK_KALEM + 1);  // her abonelik kendi kuyrugu + suzgeci
  console.log(String(k).padEnd(10) + String(N).padStart(14) + String(KUYRUK_KALEM).padStart(14) +
    String(N * k).padStart(13) + String(konuKalem).padStart(12));
}
console.log("tuketici basina is: kuyrukta " + N / 4 + ", konuda " + N + " (dort tuketicide)");
node fanout.mjs
tuketici   kuyruk teslim  kuyruk kalem  konu teslim  konu kalem
1                    400             5          400           8
2                    400             5          800          14
3                    400             5         1200          20
4                    400             5         1600          26
tuketici basina is: kuyrukta 100, konuda 400 (dort tuketicide)

Kuyruk sütunu düzdür: tüketici sayısı ne olursa olsun teslim 400’de kalır, tüketici başına iş dörtte bire iner, yapılandırma kalemi beşte sabit durur. Tüketici eklemek bir ölçekleme kararıdır ve maliyeti değiştirmez.

Konu sütunu doğrusal artar. Dördüncü aboneyle teslim 1.600’e, yapılandırma kalemi 26’ya çıkar. Abone eklemek bir ölçekleme kararı değil, yeni bir iş kolu açmaktır: her abone iletinin kendi kopyasını alır, kendi görünürlük süresini, kendi azami teslim sayısını, kendi ölü mektup kutusunu ve kendi süzgecini taşır. 26 kalem, yanlış ayarlanabilecek 26 yerdir ve bunların altısı her yeni aboneyle gelir.

Bu artışın önceki derste ölçülen şeyle aynı yüzey olduğuna dikkat edilmeli. Abone eklemek üreticide tek satır değiştirmez, var olan abonelerin sayılarını bozmaz ve hiçbir hata üretmez — kuralın görünmezliği burada aboneliğin görünmezliği olarak geri gelir. Fark şudur: kuralda fazladan teslimin bedeli çağrıydı, konuda bedel çağrı artı 400 kopyanın saklanmasıdır.

İki servis birbirinin alternatifi olmak zorunda da değildir. Yaygın düzen, konunun her aboneliğini bir kuyruğa bağlamaktır: konu çoğaltır, her kuyruk kendi tarafında paylaştırır. Modeldeki 26 kalemin yapısı zaten budur — konunun iki kalemi ile abone başına beş kuyruk kalemi ve bir süzgeç. Bu düzende önceki dersin süzgeç ölçümü doğrudan geçerlidir: süzgeç abonelikte durursa ilgisiz olay kuyruğa hiç yazılmaz, tüketicide durursa yazılır, saklanır, teslim edilir ve elenir. Fark bu kez üç kalemde birden görünür — teslim sayısı, saklanan ileti sayısı ve tüketicinin boşa uyanması.

Konu servisinin devrettiği karar da kendi başına bir kalemdir: yayıncı abone listesini tutmaz. Kaç abonenin olduğu, birinin eklenip eklenmediği, birinin sürekli hata verip vermediği yayıncı tarafında görünmez. Bir abonenin ölü mektup kutusu dolarken konu sağlıklı çalışmayı sürdürür ve öteki üç abone hiçbir şey fark etmez. Yalıtım budur ve iki yönlüdür: bir abonenin arızası ötekileri durdurmaz, ama bir abonenin arızası da kimseye bildirilmez.

Seçim ölçütü işin niteliğidir. Aynı işi bölüşecek tüketiciler için kuyruk, aynı olaydan farklı işler türetecek taraflar için konu kullanılır. Ölçüm ağında doğrulanmış okuma tek bir işe girer — fatura kalemine dönüşür — ve bu iş bölüştürülür: kuyruk. Aynı okumadan hem fatura hem arşiv hem tüketim eğrisi üretilecekse üç ayrı iş vardır: konu.

Özet

  • Kuyruğun hizmet olarak alınması düğüm sayısı, kopya sayısı, sürüm yükseltmesi ve tüketici ölçekleme kararlarını devreder; geriye ayarlanabilir beş kalem kalır.
  • Görünürlük süresi 5 birimken 400 iletilik iş yükü 745 teslime çıktı ve 102 ileti koşut olarak çift işlendi; 120 birimde çift işleme sıfırlandı ama tüketicisi ölen 16 ileti ortalama 120 birim gizli bekledi.
  • En uzun iş 69 birim olduğu için çift işlemenin sıfırlanması ancak 120 birimde gerçekleşti: işleme süresinin kuyruğu, kurtarma gecikmesinin alt sınırını belirler.
  • Ölü mektup kutusuna düşme süresi ayarlanan bir kalem değil, azami teslim ile görünürlük süresinin çarpımıdır: 5 × 120 = 600 birim. Kutunun kendisi öntanımlı olarak tüketicisizdir.
  • Kuyrukta teslim tüketici sayısından bağımsız olarak 400’de kaldı ve yapılandırma beş kalemde durdu; konuda dört aboneyle teslim 1.600’e, yapılandırma kalemi 26’ya çıktı. Kuyruk işi paylaştırır, konu iletiyi çoğaltır.
  • Görünürlük süresini iş sürerken uzatmak çift işlemeyi kapatır ama 10 birimlik süreyle 69 birimlik bir işi bitirmek altı uzatma çağrısı ister: tek iletilik iş yedi isteğe çıkar ve tüketici kendi ömrünü yönetmek zorunda kalır.

Sonraki Adım

Kuyruk iki işlevi güvenle birbirine bağlıyor: biri yazıyor, öteki alıyor, arada hata olursa ileti geri geliyor. Ama ölçüm ağındaki fatura üretimi iki adım değil; okuma doğrulanır, tüketim hesaplanır, tarife uygulanır, fatura yazılır, bildirim gönderilir. Beş adımın dördüncüsü hata verdiğinde ilk üçünün ne olacağı hiçbir kuyrukta yazılı değildir — kuyruk yalnız kendi iletisini bilir, akışın tamamını bilmez. Sonraki ders bu boşluğu ölçer: adım tabanlı bir durum makinesi koşturulur, adım başına yeniden deneme ile telafi yolu sayılır ve akışın durumunun nerede tutulduğu sorulur.

İ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