---
title: 'Servis Keşfi'
source: 'https://academia.sh/tr/kurslar/uygulama-katmani/servis-kesfi'
course: 'Uygulama Katmanı ve Servis Etkileşimi'
language: tr
updated: '2026-08-17T18:10:55+00:00'
license: 'CC BY-SA 4.0'
---

# Servis Keşfi

Kopya adreslerinin elle yazılan bir listeden çıkarılıp kayıt defterine taşınması: servis keşfinin yük dengeleyicinin sağlık denetiminden ayrılması, kayıt yaşam süresi ile çözümleme önbelleğinin bir arızayı fark etme penceresini ne kadar uzattığının modelle ölçülmesi, zarif kapanmanın pencereyi sıfırlaması ve pencerenin giriş kursundaki kesinti bütçesine çevrilmesi.

Önceki ders kopyaları birbirinin eşi hâline getirdi: durum süreç dışına taşındı, yük serbestçe
bölünebilir oldu ve gereken kopya sayısı 3'e indi. Ama ölçüm düzeneğinin bir parçası hâlâ el
yazısıyla duruyordu — sürücü betik kopyaların bağlantı noktalarını komut satırından aldı, istemci
aynı sayıları elle taşıdı. Trafik Katmanı kursunun yük dengeleyicisi de kopya listesini aynı
biçimde almıştı. Kopya sayısı değiştiğinde, bir kopya düştüğünde ya da yeni bir kopya ayağa
kalktığında bu listeyi kimin güncellediği hiçbir yerde yazılı değil.

**Servis keşfi** (service discovery), bir servisin o anda ayakta olan kopyalarının adreslerinin
çalışma zamanında bulunmasıdır. Yük dengeleyiciyle karıştırılmaya açıktır ve ikisi ayrı işler
yapar: **dengeleyici isteği dağıtır, keşif adresi bulur.** Dengeleyicinin havuzu, keşfin
ürettiği listedir; keşif olmadan o liste bir yapılandırma dosyasında durur. Bu ders listenin
nereden geldiğini, güncellenmesinin ne kadar sürdüğünü ve o sürede kaç isteğin ölü bir adrese
gittiğini ölçer.

## İki Yerleşim

**Statik liste.** Adresler her çağıran servisin yapılandırmasında yazılıdır. Bir kopya
düştüğünde hiçbir çağıran bunu kendiliğinden fark etmez; liste değiştiğinde her çağıranın
yapılandırması ayrı ayrı güncellenir.

**Kayıt defteri.** Kopyalar ayağa kalkınca kendilerini bir kayıt defterine yazar ve düzenli
aralıklarla **kalp atışı** (heartbeat) gönderir. Kaydın bir **yaşam süresi** vardır; kalp atışı
kesildiğinde kayıt bu süre dolunca düşer. Çağıran adresi çağrı anında defterden çözer.

İki yerleşimde de bir gecikme vardır ve dersin ölçtüğü sayı odur: bir kopya susmasıyla listeden
düşmesi arasında geçen **fark etme penceresi**.

## Model

Aşağıdaki düzenek bir **modeldir**: kayıt defteri, kalp atışı ve çözümleme birer modüldür,
süreler mantıksal saatle ilerler, arıza ve yeni kopya birer parametreyle tetiklenir. Gerçek bir
keşif altyapısı, hizmet ağı ürünü ya da bulut ortamı kurulmaz. Modelin iki sayısı **bu kursun
varsayımıdır** ve K01'in tablosuna eklenmez.

**U2 — kalp atışı aralığı 1000 ms, kayıt yaşam süresi 3000 ms.** Gerekçe: yaşam süresi, tek bir
kayıp kalp atışının kaydı düşürmemesi için aralığın birkaç katı seçilir; burada üç katı alındı.
Duyarlılığı aşağıda hesaplandı.

```js
// kesif/defter.mjs — kayit defteri MODELI: kayit, kalp atisi, yasam suresi ve zarif kapanma.
// Sure gercek degil, mantiksal saattir (ms); ariza ve yeni kopya parametreyle tetiklenir.
export const KALP = 1000;              // varsayim U2: kalp atisi araligi (ms)
export const YASAM = 3000;             // varsayim U2: kaydin yasam suresi (ms)

export function defter() {
  const kayit = new Map();
  return {
    kalpAtisi: (ad, adres, t) => kayit.set(adres, { ad, son: t }),
    kaydiSil: (adres) => kayit.delete(adres),
    coz: (ad, t) => [...kayit.entries()]
      .filter(([, k]) => k.ad === ad && t - k.son < YASAM)
      .map(([adres]) => adres),
  };
}

// Cozumleme onbellegi: cagiran cozdugu listeyi sure kadar elinde tutar.
export function cozucu(d, ad, onbellekMs) {
  let liste = [], tazeleme = -Infinity;
  return (t) => {
    if (t - tazeleme >= onbellekMs) { liste = d.coz(ad, t); tazeleme = t; }
    return liste;
  };
}
```

Koşum aynı arızayı dört yerleşimde tekrarlar. `k2` kopyası beşinci saniyede susar, `k4` kopyası
altıncı saniyede ayağa kalkar; çağıran on milisaniyede bir istek gönderir ve listeden sırayla bir
adres seçer.

```js
// kesif/olc.mjs — ayni arizada dort yerlesim: statik liste, kayit defteri, cozumleme onbellegi, zarif kapanma
import { defter, cozucu, KALP, YASAM } from "./defter.mjs";

const KOPYA = ["k1", "k2", "k3"];      // baslangicta ayakta olan kopyalar
const ARIZA = 5000;                    // k2 bu anda susuyor (model parametresi)
const YENI = 6000;                     // k4 bu anda ayaga kalkiyor (model parametresi)
const BAS = 5000, BIT = 11000, ADIM = 10;   // istek penceresi ve istek araligi (ms)
const TUKETICI = 4;                    // cagiran servis sayisi: gecit, ucretlendirme, teslimat-op, toplu isci

function kosum({ onbellek = 0, zarifKapanma = false, statik = false }) {
  const d = defter();
  const coz = cozucu(d, "takip", onbellek);
  let sira = 0, dusen = 0, yeniyeGiden = 0, sonDusen = null, sondaListede = false;
  for (let t = 0; t <= BIT; t += ADIM) {
    for (const k of KOPYA) {                       // kalp atislari
      if (t % KALP === 0 && (k !== "k2" || t <= ARIZA)) d.kalpAtisi("takip", k, t);
    }
    if (t % KALP === 0 && t >= YENI) d.kalpAtisi("takip", "k4", t);
    if (zarifKapanma && t === ARIZA) d.kaydiSil("k2");
    if (t < BAS) continue;
    const liste = statik ? [...KOPYA] : coz(t);    // statik liste arizadan haberdar olmaz
    sondaListede = liste.includes("k2");
    const secilen = liste[sira++ % liste.length];
    if (secilen === "k2") { dusen += 1; sonDusen = t; }
    if (secilen === "k4") yeniyeGiden += 1;
  }
  const pencere = sondaListede ? "elle" : sonDusen === null ? "0" : String(sonDusen - ARIZA + ADIM);
  return { dusen, yeniyeGiden, pencere };
}

const YERLESIM = [
  ["statik liste", { statik: true }, TUKETICI],
  ["kayit defteri", {}, 1],
  ["defter + onbellek 800", { onbellek: 800 }, 1],
  ["defter + zarif kapanma", { zarifKapanma: true }, 1],
];

console.log(`kalp atisi ${KALP} ms, yasam suresi ${YASAM} ms; k2 ${ARIZA} ms'de susuyor, ` +
  `k4 ${YENI} ms'de kaydoluyor`);
console.log(`istek penceresi ${BAS}-${BIT} ms, ${ADIM} ms'de bir istek = ${(BIT - BAS) / ADIM + 1} istek\n`);
console.log(`${"yerlesim".padEnd(26)}${"fark etme penceresi(ms)".padStart(24)}` +
  `${"olu adrese giden".padStart(18)}${"yeni kopyaya giden".padStart(20)}${"yapilandirma noktasi".padStart(22)}`);
for (const [ad, secenek, nokta] of YERLESIM) {
  const r = kosum(secenek);
  console.log(`${ad.padEnd(26)}${r.pencere.padStart(24)}${String(r.dusen).padStart(18)}` +
    `${String(r.yeniyeGiden).padStart(20)}${String(nokta).padStart(22)}`);
}
```

```
kalp atisi 1000 ms, yasam suresi 3000 ms; k2 5000 ms'de susuyor, k4 6000 ms'de kaydoluyor
istek penceresi 5000-11000 ms, 10 ms'de bir istek = 601 istek

yerlesim                   fark etme penceresi(ms)  olu adrese giden  yeni kopyaya giden  yapilandirma noktasi
statik liste                                  elle               200                   0                     4
kayit defteri                                 2980                83                 150                     1
defter + onbellek 800                         3180                93                 134                     1
defter + zarif kapanma                           0                 0                 167                     1
```

## Ölçülen Etki

Bu sayılar modelden çıkar ve belirlenimlidir: mantıksal saat ve sabit istek aralığı aynı sonucu
her koşumda verir.

**Statik liste hiç fark etmiyor.** Ölü adrese 601 isteğin 200'ü gidiyor ve pencere kapanmıyor;
kapanması için bir kişinin dört ayrı yapılandırmayı değiştirmesi gerekir. `yeni kopyaya giden`
sütunu ikinci yarıyı veriyor: `k4` ayağa kalktı ve statik düzende hiç istek almadı. Ölçek
artışının yararı da aynı gecikmeyle bekliyor.

**Kayıt defteri pencereyi kapatıyor ama anında değil.** Pencere 2980 milisaniye, yani yaşam
süresinin neredeyse tamamı. Sekseniki isteğin ölü adrese gitmesi bir kusur değil, seçilen yaşam
süresinin doğrudan sonucudur: kayıt, kalp atışı kesildikten sonra üç saniye daha listede durur.
`k4` bu düzende 150 istek alıyor — kayıt defteri yalnız düşeni çıkarmakla kalmıyor, yeni geleni
de tanıtıyor.

**Çözümleme önbelleği pencereyi uzatıyor.** Çağıran listeyi 800 milisaniye elinde tuttuğunda
pencere 2980'den 3180'e, ölü adrese giden istek 83'ten 93'e çıkıyor. Önbellek defterin yükünü
düşürür ve bunu pencereyi büyüterek yapar; iki sayı aynı kararın iki yüzüdür.

**Zarif kapanma pencereyi sıfırlıyor.** Kopya kapanmadan önce kaydını kendisi siliyor ve ölü
adrese hiç istek gitmiyor. Bu satır önemlidir çünkü kopyaların çoğu **planlı** olarak kapanır —
yayın, ölçek küçültme, taşınma. Planlı kapanmalarda pencereyi ödemek gerekmiyor; yaşam süresi
yalnız plansız susmalar için bir sigortadır.

Son sütun ayrı bir ölçüdür: yapılandırma noktası statik düzende 4, defterle 1. Sayı çağıran
servis sayısıyla büyür; kopya listesinin her tüketicide tekrarlanması, kopya sayısı değiştiğinde
yapılacak işin tüketici sayısıyla çarpılması demektir.

## Hesaba Geri Dönüş

Pencere bir süredir ve K01 ile K02'nin sayıları onu isteğe çevirir. Trafik Katmanı kursu aynı
hesabı sağlık denetimi için yapmış, arıza başına 34,26 istek bulmuştu.

```js
// kesif/butce.mjs — fark etme penceresinin K01 istek hizi ve kesinti butcesindeki karsiligi
const TEPE_UC = 513.89;                          // K01 Kabaca Buyukluk Hesabi: tepe ucta istek/s
const KOPYA = 3;                                 // K02 Yuk Dengeleyici Rolu: en az kopya sayisi
const ARIZA_AY = 2.82;                           // K01 Erisilebilirligin Sayisal Ifadesi: ayda butceye sigan ariza
const AY_ISTEK = (12_000_000 + 2_800_000) * 30;  // K01: gunluk takip sorgusu + durum olayi
const SAGLIK = 0.2, DEFTER = 2.98;               // K02 varsayim Y3 penceresi ve modelin olctugu pencere
const PENCERE = [
  ["saglik denetimi (K02 Y3)", SAGLIK], ["kayit defteri (U2)", DEFTER],
  ["defter + onbellek 800", 3.18], ["zarif kapanma", 0], ["elle mudahale (K01)", 600],
];

const payHiz = TEPE_UC / KOPYA;
console.log(`kopya basina hiz = ${TEPE_UC} / ${KOPYA} = ${payHiz.toFixed(2)} istek/s\n`);
console.log(`${"pencere kaynagi".padEnd(26)}${"sn".padStart(7)}${"ariza basina dusen".padStart(20)}` +
  `${"aylik dusen".padStart(13)}${"istek tabanli erisilebilirlik".padStart(31)}`);
for (const [ad, sn] of PENCERE) {
  const bir = payHiz * sn, aylik = bir * ARIZA_AY;
  console.log(`${ad.padEnd(26)}${String(sn).padStart(7)}${bir.toFixed(2).padStart(20)}` +
    `${aylik.toFixed(0).padStart(13)}${`%${(100 * (1 - aylik / AY_ISTEK)).toFixed(5)}`.padStart(31)}`);
}

console.log(`\nikisi birlikte: etkin pencere = min(${SAGLIK}, ${DEFTER}) = ${Math.min(SAGLIK, DEFTER)} sn ` +
  `-> ${(payHiz * Math.min(SAGLIK, DEFTER)).toFixed(2)} istek; kesif tek basina ${(DEFTER / SAGLIK).toFixed(1)} kat kotu`);
const kalp = (yasam) => (KOPYA * 1000) / (yasam / 3);
console.log(`duyarlilik: U2'nin yasam suresi 3000 -> 1000 ms olsaydi pencere ${(DEFTER - 2).toFixed(2)} sn, ` +
  `ariza basina ${(payHiz * (DEFTER - 2)).toFixed(2)} istek`);
console.log(`  defterin kendi yuku ${kalp(3000).toFixed(2)} -> ${kalp(1000).toFixed(2)} atis/s ` +
  `(K02'nin saglik denetimi yuku 15 istek/s)`);
```

```
kopya basina hiz = 513.89 / 3 = 171.30 istek/s

pencere kaynagi                sn  ariza basina dusen  aylik dusen  istek tabanli erisilebilirlik
saglik denetimi (K02 Y3)      0.2               34.26           97                      %99.99998
kayit defteri (U2)           2.98              510.46         1440                      %99.99968
defter + onbellek 800        3.18              544.72         1536                      %99.99965
zarif kapanma                   0                0.00            0                     %100.00000
elle mudahale (K01)           600           102778.00       289834                      %99.93472

ikisi birlikte: etkin pencere = min(0.2, 2.98) = 0.2 sn -> 34.26 istek; kesif tek basina 14.9 kat kotu
duyarlilik: U2'nin yasam suresi 3000 -> 1000 ms olsaydi pencere 0.98 sn, ariza basina 167.87 istek
  defterin kendi yuku 3.00 -> 9.00 atis/s (K02'nin saglik denetimi yuku 15 istek/s)
```

Bu sayılar **hesap** sınıfındadır. Tablo bir sıralama veriyor: sağlık denetimi 34,26, kayıt
defteri 510,46, elle müdahale 102.778 istek. Keşif, elle tutulan listeye göre iki yüz kat iyi,
sağlık denetimine göre on beş kat kötü. Bu iki karşılaştırma birlikte okunmalıdır, çünkü dersin
asıl savı buradadır: **servis keşfi bir arıza algılama aracı değildir.** İşi, listenin doğru
kaynaktan gelmesini sağlamaktır; arızayı hızlı fark etme işi hâlâ sağlık denetiminindir.

İkisi birlikte kullanıldığında etkin pencere küçük olanla belirlenir. Dengeleyici düşen kopyayı
200 milisaniyede havuzundan çıkarır; defterin kaydı üç saniye daha durur ama o kayıt zaten
dengeleyicinin havuzuna girmez. Bir katman diğerinin yerine geçmiyor, biri ötekinin girdisini
üretiyor.

Duyarlılık satırı U2'nin fiyatını gösteriyor. Yaşam süresi 3000 milisaniyeden 1000'e indirilirse
pencere 0,98 saniyeye ve arıza başına düşen istek 167,87'ye iner, ama kalp atışı aralığı da
üçte birine inmek zorundadır: defterin kendi yükü 3,00 atıştan 9,00 atış/s'ye çıkar. Karşılaştırma
noktası K02'nin sağlık denetimi yüküdür — 15 istek/s. Keşif katmanının gözlem yükü, sağlık
denetiminin yükünün altındadır ve pencereyi kısaltmak onu doğrusal büyütür.

## Özet

- Servis keşfi ile yük dengeleme ayrı işlerdir: dengeleyici isteği dağıtır, keşif adresi bulur;
  keşfin ürettiği liste dengeleyicinin havuzudur.
- Statik listede ölü adrese 601 isteğin 200'ü gitti ve pencere kendiliğinden kapanmadı; yeni
  ayağa kalkan kopya hiç istek almadı ve yapılandırma noktası tüketici sayısı kadar (4) oldu.
- Kayıt defterinde pencere 2980 ms, ölü adrese giden 83 istek; yeni kopya 150 istek aldı ve
  yapılandırma noktası 1'e indi.
- Çözümleme önbelleği defterin yükünü düşürürken pencereyi 3180 ms'ye ve düşen isteği 93'e
  çıkarıyor; zarif kapanma pencereyi 0'a indiriyor, çünkü kopya kaydını kendisi siliyor.
- K01'e dönüş: arıza başına düşen istek sağlık denetiminde 34,26, kayıt defterinde 510,46, elle
  müdahalede 102.778; keşif elle tutulan listeye göre iki yüz kat iyi, sağlık denetimine göre on
  beş kat kötüdür.
- U2 duyarlılığı: yaşam süresi 1000 ms'ye inerse pencere 0,98 saniyeye düşer, defterin kendi yükü
  3,00'ten 9,00 atış/s'ye çıkar (K02'nin sağlık denetimi yükü 15 istek/s).

## Sonraki Adım

Adres artık çalışma zamanında bulunuyor ve liste kendini güncelliyor. Bu, iki servisin
birbirine ulaşabilmesi için gereken son parçaydı; ama ulaştıktan sonra ne konuşacakları
seçilmedi. Ağ geçidi teslimat operasyonu ile ücretlendirme servisini paralel çağırıp yanıtlarını
birleştiriyordu ve o çağrıların biçimi hiçbir yerde tartışılmadı. Sonraki ders o seçimi ele alır:
aynı iç çağrı üç ayrı biçimde yazılır ve üç ölçüyle karşılaştırılır — bir dış istek için yapılan
iç çağrı sayısı, iç sınırdan geçen bayt ve çağıranın bilmek zorunda olduğu ad sayısı.
