---
title: 'Bildirim Sistemi'
source: 'https://academia.sh/tr/kurslar/vaka-calismalari/bildirim-sistemi'
course: 'Vaka Çalışmaları'
language: tr
updated: '2026-08-17T18:10:56+00:00'
license: 'CC BY-SA 4.0'
---

# Bildirim Sistemi

Aynı iletinin birden çok yoldan gidebildiği vaka: kanal başına geçici ve kalıcı hata oranının ayrılması, tek kanalda üç denemenin teslim oranını eşiğin 3,01 puan altında bırakması, tek kanal ile paralel ve kademeli kanal sırasının teslim oranı, dış çağrı, yinelenen teslim ve gecikme cinsinden ölçülmesi ve paralel dağıtımın çağrı çarpanıyla elenmesi.

Önceki vakada teslim tek bir yol üzerinden yürüdü ve başarısızlığa verilen tek yanıt aynı yolu
yeniden denemekti. Bu vakada yol birden fazladır. Aynı bildirim uygulama itmesiyle, kısa
iletiyle ya da e-postayla gidebilir; kanalların başarısızlık oranları birbirinden farklıdır ve
birinin başarısızlığı ötekini denemek için gerekçedir.

Bu, yeniden deneme sorusunu değiştirir. Bir denemenin nereye harcanacağı artık "aynı yere mi,
başka yere mi" sorusudur ve yanıtı iki sayıyı birden oynatır: toplam teslim oranını ve dışarıya
yapılan çağrı sayısını.

## Kısıtlar ve Kapsam

İşlevsel gereksinimler: bildirim isteğini kabul etmek, alıcının tercihine göre kanal seçmek,
kanal başına biçimlendirmek, teslim durumunu kaydetmek, aynı olayın alıcıya ikinci kez
gitmesini engellemek.

Tasarlanmayan işler: bildirim metninin yazımı ve şablon dili, çeviri, izin ekranı, alıcı
kümelerinin seçilmesi ve kanal sağlayıcılarının kendi iç işleyişi.

İşlevsel olmayan gereksinimler eşikle ve kaynağıyla yazılır: toplam teslim oranı 0,99'un
altına inmez (kaynak: bildirimin bir işlemin tek habercisi olması), acil bildirimin ortalama
teslim gecikmesi 5 saniyeyi geçmez (kaynak: alıcının işlemi yaptığı anda haberi beklemesi),
bir olay için alıcıya giden teslim sayısı birdir (kaynak: aynı haberi iki kanaldan almanın
alıcı için hata sayılması).

## Varsayımlar ve Ölçek

| Kod | Varsayım | Değer | Gerekçe |
|---|---|---|---|
| BI1 | günlük etkin alıcı | 5.000.000 | bildirim alabilir durumdaki hesap |
| BI2 | alıcı başına günlük bildirim | 6 | işlem haberleri ve hatırlatmalar |
| BI3 | tepe çarpanı | 5 | bildirimlerin gün içinde birkaç saate yığılması |
| BI4 | kanal payı | 0,55 / 0,25 / 0,20 | itme, kısa ileti, e-posta tercih dağılımı |
| BI5 | kanal başına geçici hata | 0,05 / 0,02 / 0,01 | anlık ulaşılamama, yeniden deneme düzeltir |
| BI6 | kanal başına kalıcı hata | 0,06 / 0,02 / 0,01 | geçersiz adres, kapalı izin, yeniden deneme düzeltmez |
| BI7 | bildirim kaydı | 300 bayt | olay kimliği, alıcı, kanal, durum, zaman damgası |
| BI8 | deneme bütçesi | 3 | bildirim başına yapılacak en çok dış çağrı |
| BI9 | denemeler arası bekleme | 30 saniye | geçici hatanın geçmesine bırakılan süre |

BI5 ile BI6 ayrımı bu vakanın belirleyici varsayımıdır. Geçici hata aynı kanalda tekrar
denendiğinde düzelir; kalıcı hata düzelmez ve aynı kanalda harcanan her deneme boşa gider.

```js
// bildirim/olcek.mjs — BI varsayim tablosundan cikan kabaca buyukluk hesabi
export const BI = {
  gunlukAlici: 5_000_000,        // BI1
  aliciBasinaBildirim: 6,        // BI2
  tepeCarpani: 5,                // BI3
  pay: { itme: 0.55, "kisa-ileti": 0.25, "e-posta": 0.20 },        // BI4
  gecici: { itme: 0.05, "kisa-ileti": 0.02, "e-posta": 0.01 },     // BI5
  kalici: { itme: 0.06, "kisa-ileti": 0.02, "e-posta": 0.01 },     // BI6
  kayitBayt: 300,                // BI7
  butce: 3,                      // BI8
  bekleme: 30,                   // BI9
};
const GUN = 86_400;

const gunluk = BI.gunlukAlici * BI.aliciBasinaBildirim;
const tepe = (gunluk / GUN) * BI.tepeCarpani;
console.log(`gunluk bildirim        ${gunluk}`);
console.log(`tepe bildirim/s        ${tepe.toFixed(2)}`);
console.log(`gunluk veri artisi GB  ${((gunluk * BI.kayitBayt) / 1e9).toFixed(2)}`);

console.log(`\n${"kanal".padEnd(11)}${"pay".padStart(6)}${"tepe cagri/s".padStart(14)}${"gecici".padStart(8)}` +
  `${"kalici".padStart(8)}${"3 denemeden sonra kalan".padStart(25)}`);
let karmaKalan = 0;
for (const k of Object.keys(BI.pay)) {
  const kalan = BI.kalici[k] + BI.gecici[k] ** BI.butce;
  karmaKalan += BI.pay[k] * kalan;
  console.log(`${k.padEnd(11)}${BI.pay[k].toFixed(2).padStart(6)}${(tepe * BI.pay[k]).toFixed(2).padStart(14)}` +
    `${BI.gecici[k].toFixed(2).padStart(8)}${BI.kalici[k].toFixed(2).padStart(8)}${kalan.toFixed(6).padStart(25)}`);
}
console.log(`\ntek kanalda ${BI.butce} deneme -> karma kalan hata ${karmaKalan.toFixed(6)}, ` +
  `teslim orani ${(1 - karmaKalan).toFixed(4)}`);
console.log(`esik 0.9900 -> tek kanal ${1 - karmaKalan >= 0.99 ? "gecer" : "gecmez"}; ` +
  `acigi ${((0.99 - (1 - karmaKalan)) * 100).toFixed(2)} puan`);
console.log(`ulasilamayan bildirim: tepe ${(tepe * karmaKalan).toFixed(2)}/s, ` +
  `gunde ${Math.round(gunluk * karmaKalan)}`);
console.log(`kademeli en kotu teslim = (${BI.butce} - 1) x ${BI.bekleme} s = ${(BI.butce - 1) * BI.bekleme} s`);
```

```
gunluk bildirim        30000000
tepe bildirim/s        1736.11
gunluk veri artisi GB  9.00

kanal         pay  tepe cagri/s  gecici  kalici  3 denemeden sonra kalan
itme         0.55        954.86    0.05    0.06                 0.060125
kisa-ileti   0.25        434.03    0.02    0.02                 0.020008
e-posta      0.20        347.22    0.01    0.01                 0.010001

tek kanalda 3 deneme -> karma kalan hata 0.040071, teslim orani 0.9599
esik 0.9900 -> tek kanal gecmez; acigi 3.01 puan
ulasilamayan bildirim: tepe 69.57/s, gunde 1202129
kademeli en kotu teslim = (3 - 1) x 30 s = 60 s
```

Bu sayılar **hesap** sınıfındadır. Üçü tasarımı belirliyor. Birincisi, tepe yük kanallara
eşit dağılmıyor: itme kanalı saniyede 954,86 çağrı alırken e-posta 347,22 alıyor, yani en
kalabalık kanal en yüksek kalıcı hata oranına sahip olan kanaldır. İkincisi, aynı kanalda üç
deneme geçici hatayı pratikte siliyor (itmede 0,05 üzeri üç, yani 0,000125) ama kalıcı hataya
dokunmuyor; kalan hata neredeyse tümüyle BI6'dan geliyor. Üçüncüsü, tek kanallı tasarımın
teslim oranı 0,9599 çıkıyor ve 0,99 eşiğinin 3,01 puan altında kalıyor: günde 1.202.129
bildirim hiç ulaşmıyor. Eşik bir kanal sırası kararını zorunlu kılıyor.

## Tasarım

**Alma ucu ve kuyruk.** Bildirim isteği eşzamansız kabul edilir; Uygulama Katmanı ve Servis
Etkileşimi kursunun Mesaj Kuyrukları ve Rekabet Eden Tüketiciler dersleri buradaki yapıyı
verir. Parametre öncelik sınıflarıdır: aynı kursun Öncelikli Kuyruk dersindeki iki sınıf
kullanılır, acil bildirim ve hatırlatma, çünkü eşiklerden yalnız biri gecikme içerir.

**Kanal başına bölme kalıbı.** Dayanıklılık ve Güvenilirlik kursunun Bölme Kalıbı dersindeki
kaynak havuzu kanal başına ayrılır ve havuz payları tepe çağrı hızına göre verilir: 954,86,
434,03 ve 347,22 çağrı/s. Ayrımın gerekçesi, bir kanalın yavaşlamasının öteki kanalların
çağrılarını bekletmemesidir.

**Kanal başına devre kesici.** Aynı kursun Devre Kesici dersindeki eşik burada bir sayaç
seçimidir: devre kesici yalnız **geçici** hataları sayar. Kalıcı hata alıcıya özgüdür ve
kanalın sağlığı hakkında bilgi taşımaz; kalıcı hatalar sayaca girseydi itme kanalının devresi
yüzde 6'lık bir taban yüzünden sürekli açılırdı.

**Deneme bütçesinin yerleşimi.** Yeniden Deneme ve Fırtına Riski dersindeki deneme bütçesi
3'tür ve bu vakanın kararı bütçenin **nereye** harcandığıdır: aynı kanala mı, sıradaki kanala
mı. Ölçüm bölümü bu kararı sayıya çeviriyor.

**Tekillik.** Dayanıklılık ve Güvenilirlik kursunun Etkisiz İşlemler dersindeki tekillik
anahtarının kapsamı burada `(olay kimliği, alıcı)` ikilisidir; **kanal kapsama girmez**, çünkü
aynı olayın iki kanaldan gitmesi tam olarak engellenmek istenen şeydir.

**Bilerek kullanılmayan kalıp.** Sıralı konvoy (Uygulama Katmanı ve Servis Etkileşimi,
Kuyruklar ve İş Akışları) bu tasarımda yoktur: iki bildirim arasında sıra kısıtı yoktur, her
biri bağımsız bir olayın habercisidir ve şerit koymak koşutluğu bedelsiz yere keserdi.

## Kanal Sırası Ölçülüyor

Ölçüm süreç içi bir modeldir: gerçek kanal, dış servis ya da ağ yoktur; her deneme bir
olasılık, tur soyut bir adımdır ve bir tur BI9 ile 30 saniyedir. Model bir dakikalık tepe
penceresini alır: 104.167 bildirim. Üç düzen aynı 3 çağrılık bütçeyi farklı yerlere harcar —
**tek kanal** üçünü de tercih edilen kanala, **paralel** üçünü aynı anda üç kanala, **kademeli**
birini tercih edilen kanala ve kalanları sırayla ötekilere.

```js
// bildirim/dagitim.mjs — kanal sirasinin surec ici modeli. Gercek kanal, dis servis ya da ag
// yoktur: her deneme bir olasilik, tur soyut bir adimdir (BI9: tur basina 30 s bekleme).
const KANAL = ["itme", "kisa-ileti", "e-posta"];
const PAY = { itme: 0.55, "kisa-ileti": 0.25, "e-posta": 0.20 };        // BI4
const GECICI = { itme: 0.05, "kisa-ileti": 0.02, "e-posta": 0.01 };     // BI5
const KALICI = { itme: 0.06, "kisa-ileti": 0.02, "e-posta": 0.01 };     // BI6
const BUTCE = 3, BEKLEME = 30;                                          // BI8, BI9
const BILDIRIM = 104_167;                    // hesap: tepe 1736,11 bildirim/s x 60 s penceresi

function uretec(tohum) {                     // 32 bitlik dogrusal esitlikli uretec
  let s = tohum >>> 0;
  return () => { s = (Math.imul(s, 1103515245) + 12345) >>> 0; return s / 4294967296; };
}

export function kos({ duzen, tohum, carpan = 1, dusen = null }) {
  const rnd = uretec(tohum);
  const s = { teslim: 0, disCagri: 0, yinelenen: 0, turToplam: 0 };
  for (let i = 0; i < BILDIRIM; i += 1) {
    let u = rnd(), tercih = KANAL[KANAL.length - 1];
    for (const k of KANAL) { if (u < PAY[k]) { tercih = k; break; } u -= PAY[k]; }
    const kalici = {};
    for (const k of KANAL) kalici[k] = k === dusen || rnd() < Math.min(1, KALICI[k] * carpan);
    const sira = duzen === "tek kanal" ? [tercih, tercih, tercih]
      : [tercih, ...KANAL.filter((k) => k !== tercih)];

    let ulasan = 0, ilkTur = null;
    for (let t = 0; t < BUTCE; t += 1) {
      const k = sira[t];
      s.disCagri += 1;
      const basarili = kalici[k] === false && rnd() >= Math.min(1, GECICI[k] * carpan);
      if (basarili) {
        ulasan += 1;
        if (ilkTur === null) ilkTur = duzen === "paralel" ? 0 : t;
        if (duzen !== "paralel") break;
      }
    }
    if (ulasan > 0) { s.teslim += 1; s.turToplam += ilkTur; s.yinelenen += ulasan - 1; }
  }
  s.oran = s.teslim / BILDIRIM;
  return s;
}

const DUZEN = ["tek kanal", "paralel", "kademeli"];
console.log(`model: ${BILDIRIM} bildirim, ${KANAL.length} kanal, deneme butcesi ${BUTCE}, tohum 20260730`);
console.log(`\n${"duzen".padEnd(11)}${"teslim orani".padStart(14)}${"dis cagri".padStart(11)}` +
  `${"cagri/bildirim".padStart(16)}${"yinelenen".padStart(11)}${"ort. teslim s".padStart(15)}`);
const R = {};
for (const d of DUZEN) {
  const r = (R[d] = kos({ duzen: d, tohum: 20260730 }));
  console.log(`${d.padEnd(11)}${r.oran.toFixed(4).padStart(14)}${String(r.disCagri).padStart(11)}` +
    `${(r.disCagri / BILDIRIM).toFixed(3).padStart(16)}${String(r.yinelenen).padStart(11)}` +
    `${((r.turToplam / r.teslim) * BEKLEME).toFixed(2).padStart(15)}`);
}

console.log(`\n${"hata carpani".padEnd(13)}${DUZEN.map((d) => `${d} orani`.padStart(19)).join("")}`);
for (const c of [1, 2, 3]) {
  const satir = DUZEN.map((d) => kos({ duzen: d, tohum: 20260730, carpan: c }).oran.toFixed(4).padStart(19));
  console.log(`${`x${c}`.padEnd(13)}${satir.join("")}`);
}

console.log(`\n${"itme kanali tumden dustu".padEnd(25)}${DUZEN.map((d) => d.padStart(12)).join("")}`);
const dusuk = DUZEN.map((d) => kos({ duzen: d, tohum: 20260730, dusen: "itme" }));
console.log(`${"teslim orani".padEnd(25)}${dusuk.map((r) => r.oran.toFixed(4).padStart(12)).join("")}`);
console.log(`${"dis cagri".padEnd(25)}${dusuk.map((r) => String(r.disCagri).padStart(12)).join("")}`);

const tek = R["tek kanal"], par = R["paralel"], kad = R["kademeli"];
console.log(`\nkademeli - tek kanal teslim orani farki = ${((kad.oran - tek.oran) * 100).toFixed(2)} puan`);
console.log(`paralelin bedeli: dis cagri x${(par.disCagri / kad.disCagri).toFixed(2)}, ` +
  `${par.yinelenen} yinelenen teslim, bildirim basina ${(par.yinelenen / BILDIRIM).toFixed(2)} fazladan`);
console.log(`paralelin kazanci: ort. teslim ${((par.turToplam / par.teslim) * BEKLEME).toFixed(2)} s, ` +
  `kademelide ${((kad.turToplam / kad.teslim) * BEKLEME).toFixed(2)} s`);
```

```
model: 104167 bildirim, 3 kanal, deneme butcesi 3, tohum 20260730

duzen        teslim orani  dis cagri  cagri/bildirim  yinelenen  ort. teslim s
tek kanal          0.9590     116305           1.117          0           1.08
paralel            0.9999     312501           3.000     190861           0.00
kademeli           0.9999     112357           1.079          0           2.35

hata carpani     tek kanal orani      paralel orani     kademeli orani
x1                        0.9590             0.9999             0.9999
x2                        0.9199             0.9993             0.9994
x3                        0.8790             0.9979             0.9979

itme kanali tumden dustu    tek kanal     paralel    kademeli
teslim orani                   0.4443      0.9993      0.9991
dis cagri                      220661      312501      166806

kademeli - tek kanal teslim orani farki = 4.09 puan
paralelin bedeli: dis cagri x2.78, 190861 yinelenen teslim, bildirim basina 1.83 fazladan
paralelin kazanci: ort. teslim 0.00 s, kademelide 2.35 s
```

Bu sayılar **ölçüm** sınıfındadır; tohum 20260730 ile yeniden üretilir.

İlk tablo bütçenin yerleşimini fiyatlandırıyor. Tek kanal 0,9590 teslim oranı veriyor ve
hesapla bulunan 0,9599 ile aynı büyüklükte; kademeli aynı üç çağrılık bütçeyle 0,9999'a
çıkıyor, fark 4,09 puan. Dikkat çekici olan ikinci sütundur: kademeli düzen bunu **daha az**
dış çağrıyla yapıyor, bildirim başına 1,079 çağrı, tek kanalın 1,117 çağrısının altında. Kalıcı
hataya çarpan bir bildirim tek kanallı düzende üç çağrıyı da boşa harcar; kademeli düzende
ikinci çağrı işi bitirir. Yeniden denemenin yeri, sayısından önemlidir.

İkinci tablo hata oranlarının duyarlılığını veriyor. Bütün kanalların hata oranları üç katına
çıktığında tek kanal 0,8790'a düşüyor, kademeli 0,9979'da kalıyor. Kanal çeşitliliğinin
kazancı hata oranı büyüdükçe artıyor: fark 4,09 puandan 11,89 puana çıkıyor.

## Elenen Alternatif: Paralel Dağıtım

Paralel düzen teslim oranında kademeliyle aynı sonucu veriyor (0,9999) ve gecikmede onu
geçiyor: ortalama teslim 0,00 saniye, kademelide 2,35 saniye. Buna karşın iki sayıyla eleniyor.

Birincisi, dış çağrı sayısı kademelinin 2,78 katıdır ve bildirim başına 3,000 çağrıda sabittir;
kanal başarısızlığı düşse bile azalmaz, çünkü paralel düzen sonucu beklemeden hepsini gönderir.
İkincisi ve belirleyicisi, 190.861 yinelenen teslim üretir: bildirim başına 1,83 fazladan
teslim. Bu doğrudan işlevsel olmayan gereksinimin ihlalidir — alıcı aynı haberi ortalama üç
kanaldan birden alır.

Alternatifin kazandığı da yazılır: paralel düzen 60 saniyelik en kötü teslim penceresini
sıfırlar. Gecikme eşiği 5 saniye yerine 1 saniye olsaydı ve "tek teslim" gereksinimi kalksaydı
seçim tersine dönerdi; iki kanalın aynı anda denendiği bir orta yol da bu eşikte savunulabilir
olurdu.

## Arıza Davranışı ve Feda Edilen

Arıza senaryosu bir kanalın tümden durmasıdır: itme kanalı bütün alıcılar için başarısız
oluyor. Üçüncü tablo sonucu veriyor. Tek kanallı düzen 0,4443'e düşüyor — bildirimlerin yarıdan
fazlası hiç ulaşmıyor — ve dış çağrısı 220.661'e, yani normalin 1,90 katına çıkıyor, çünkü boşa
giden denemeler bütçeyi sonuna kadar kullanıyor. Kademeli düzen 0,9991'de kalıyor ve dış
çağrısı 166.806'ya çıkıyor. Kanal başına devre kesicinin görevi burada görünür: itme kanalının
devresi açıldığında sıra doğrudan ikinci kanaldan başlar ve arızanın eklediği 54.449 boşa
çağrı (166.806 eksi 112.357) yapılmaz.

Feda edilen tek cümlededir: kademeli sıra, teslim oranını gecikmeyle satın alır — ilk kanalı
kalıcı hataya çarpan alıcı bildirimi 30 saniye, ikincisi de başarısızsa 60 saniye geç alır.

## Özet

- Kanal hatası ikiye ayrılmadan tasarım yapılamaz: geçici hata üç denemede siliniyor
  (0,05 üzeri üç), kalıcı hata aynı kanalda hiç azalmıyor ve kalan hatanın tamamına yakınını o
  oluşturuyor.
- Tek kanallı düzen 0,9599 hesaplanmış, 0,9590 ölçülmüş teslim oranı veriyor; 0,99 eşiğinin
  3,01 puan altında ve günde 1.202.129 bildirim ulaşmıyor.
- Kademeli sıra aynı üç çağrılık bütçeyle 0,9999 veriyor ve bunu daha az dış çağrıyla yapıyor:
  bildirim başına 1,079 çağrı, tek kanalın 1,117 çağrısına karşı.
- Hata oranları üç katına çıktığında tek kanal 0,8790'a iniyor, kademeli 0,9979'da kalıyor;
  çeşitliliğin kazancı 4,09 puandan 11,89 puana çıkıyor.
- Paralel dağıtım aynı teslim oranını veriyor ama 2,78 kat dış çağrı ve bildirim başına 1,83
  fazladan teslim üretiyor; tek teslim gereksinimini ihlal ettiği için eleniyor.
- İtme kanalı tümden düştüğünde tek kanal 0,4443'e iniyor, kademeli 0,9991'de kalıyor; bedeli
  bildirimin 30 ya da 60 saniye gecikmesidir.

## Sonraki Adım

Bu iki vakada da sistemin işi bir isteği **karşılamaktı** ve başarısızlık kötü bir sonuçtu.
Sonraki vaka tersini tasarlar: işi isteği **reddetmek** olan bir bileşen. Reddetme kararı
paylaşılan bir sayaca bakarak verilir ve sayaç dağıtıktır; iki soru buradan çıkar. Sayacın
tuttuğu pencere hangi biçimde tanımlanırsa sınırın üstüne çıkılabilir, ve eşzamanlı okuyup
yazan düğümler sayaçta ne kadar sapma üretir. İkisi de sayılabilir.
