---
title: 'Gömülü Sunucu ve İstek İşleme Modeli'
source: 'https://academia.sh/tr/kurslar/kurumsal-uygulama-cercevesi/gomulu-sunucu-ve-istek-isleme-modeli'
course: 'Kurumsal Uygulama Çerçevesi'
language: tr
updated: '2026-08-23T14:25:05+00:00'
license: 'CC BY-SA 4.0'
---

# Gömülü Sunucu ve İstek İşleme Modeli

İstek işleme zincirinin halkaları üç kaynağa ayrılır: nesne kabının kendi varsayılanı, bir açıklama ve açık bir çağrı. Aynı halka kümesi farklı sırayla bildirildiğinde kabın ürettiği çalışma sırası değişmiyor; açıklama taşıyan bir sınıf kabın dışında elle çağrıldığında ise açıklamanın hiçbir etkisi kalmıyor.

Önceki konunun son dersi çağrı yerine hiç dokunmadan davranış eklenebildiğini, bunun sınırının
da vekilin ulaşabildiği yer olduğunu gösterdi. Bu konu aynı kabı bir soruyla izliyor: kap bir
isteği karşılarken aynı üç kaynak — çağrı, açıklama, varsayılan — hangi oranda devrede? Uç
noktalar, doğrulama ve veri erişimi de aynı üç kaynaktan doğuyor; bu ders zincirin en dışındaki
katmandan başlıyor ve isteğin kaba girişinden çıkışına kadar hangi halkadan geçtiğini sayıyor.

Sunucu burada **modellenir**. Gerçek bir soket açılmaz, gerçek bir bağlantı noktası
dinlenmez, ağdan gerçek bir bayt okunmaz — bir isteğin kaptan geçerken izlediği yol, bir
dizgenin üzerinden sırayla geçen küçük işlev nesneleri olarak kurulur. Bu basitleştirme
dersin sorusunu değiştirmiyor: gerçek bir gömülü sunucuda da istek, dinleyici soketten
uygulama koduna ulaşana kadar sabit bir **halka** dizisinden geçer, ve bu dizinin kaç
halkasının kaynakta bir karşılığı olduğu sorusu soket gerçek olsun ya da olmasın aynı kalır.
Sunucunun kendisinin görevi, bağlantıyı kabul etmesi ve isteği bu zincire sokması —
**M16/K01 Sunucu Temelleri ve Backend'in Rolü** kursu bunu ve zincirin genel fikrini kavram
olarak kurdu, burada tekrarlanmıyor. Kursun kendi terimi **istek işleme zinciri**, aynı
kursun **ara katman zinciri** teriminden ayrı tutulur: ara katman zinciri çağıranın elle
dizdiği bir sıradır, istek işleme zinciri ise bu derste görüleceği gibi kabın kendi kuralına
göre kurduğu bir sıradır.

Sunucunun modellenmesinin bir başka nedeni ölçümün kendisiyle ilgili: gerçek bir bağlantı
noktası açılsaydı, hangi bağlantı noktasının boşta olduğu makineye göre değişir ve bu ders
serisinin bütününde geçerli olan ortama bağlı veri yasağı böyle bir değeri yazmayı zaten
engeller. Dizgeyle kurulan model bu sorunu baştan kaldırıyor — aynı programın iki ayrı
makinede iki ayrı çıktı verme ihtimali sıfıra iniyor, çünkü ölçülen şey ağdaki bir gecikme ya
da bir bağlantı noktası numarası değil, kabın sabit bir sırayla uyguladığı işlev zinciri.
Gerçek bir gömülü sunucuda bu zincirin en dış halkası ağdan okuma ve ağa yazmadır; burada o
halka atlanıyor ve zincir doğrudan uygulama kodunun gördüğü ilk noktadan, isteğin kendisinden
başlıyor.

## Halkaların Üç Kaynağı

- **WV1.** İstek burada bir dizge (`govde`) olarak modellenir; her halka bu dizgeye kendi
  imzasını ekler, ağdan okuma ve ağa yazma modellenmez.
- **WV2.** Açıklamalı sınıfların keşfi gerçek bir sınıf yolu taraması yapmaz; kap, `tara`
  çağrısına verilen aday sınıf listesini gözden geçirir. Bu, gerçek bir çerçevenin sınıf
  yolunu dolaşan taramasının modellenmiş bir karşılığıdır.

Zincirin bir halkası üç yoldan biriyle var olabiliyor. Kabın kendi gövdesine yazılmış, hiçbir
sınıfa hiçbir açıklama koymadan hep çalışan bir halka **varsayılandır** — burada isteğe bir
kimlik ekleyen ve zincirin sonunda hataları yakalayan iki halka bu gruba giriyor, ikisi de
`Kap` sınıfının kendi `calistir` yönteminin içinde yazılı ve hiçbir dış çağrıya ihtiyaç
duymuyor. Bir sınıfın üzerine konan `@Halka` açıklaması, kap o sınıfı tanıdığında zincire
eklenmesini **istiyor**; bu istek kabın `tara` yöntemine bir aday listesi verilmeden hiçbir
şey yapmıyor. Üçüncü yol ise en çıplak olanı: kodun kendisi `kap.ekle(...)` çağrısıyla bir
halkayı doğrudan zincire koyuyor — kaynakta bunu doğuran satır tam olarak bu satır.

```java
// Kap.java — istek isleme zincirinin halkalarini kim ekledi: cagiran mi, aciklama mi, kabin varsayilani mi
import java.lang.annotation.*;
import java.lang.reflect.*;
import java.util.*;

public class Kap {

    @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE)
    @interface Halka { int oncelik() default 100; }

    interface HalkaIslevi { String uygula(String govde, List<String> iz); }

    final List<Class<?>> aciklamaliSinif = new ArrayList<>();
    final List<HalkaIslevi> cagriliHalka = new ArrayList<>();
    final List<String> cagriliAd = new ArrayList<>();

    void tara(Class<?>... adaylar) {
        for (Class<?> aday : adaylar)
            if (aday.isAnnotationPresent(Halka.class)) aciklamaliSinif.add(aday);
    }

    void ekle(String ad, HalkaIslevi h) {
        cagriliAd.add(ad);
        cagriliHalka.add(h);
    }

    String calistir(String govde, List<String> iz) {
        try {
            String s = govde;
            iz.add("istek-kimligi(varsayilan)");

            List<Class<?>> siraliAciklamali = new ArrayList<>(aciklamaliSinif);
            siraliAciklamali.sort(Comparator.comparingInt(c -> c.getAnnotation(Halka.class).oncelik()));
            for (Class<?> c : siraliAciklamali) {
                HalkaIslevi h = (HalkaIslevi) c.getDeclaredConstructor().newInstance();
                iz.add(c.getSimpleName() + "(aciklama)");
                s = h.uygula(s, iz);
            }
            for (int i = 0; i < cagriliHalka.size(); i++) {
                iz.add(cagriliAd.get(i) + "(cagri)");
                s = cagriliHalka.get(i).uygula(s, iz);
            }
            iz.add("hata-yakalama(varsayilan)");
            return s;
        } catch (ReflectiveOperationException e) {
            throw new RuntimeException(e);
        }
    }

    public static void main(String[] args) {
        Kap kap1 = new Kap();
        kap1.tara(GunlukHalkasi.class, SikistirmaHalkasi.class);
        kap1.ekle("baslik-ekleme", (g, iz) -> g + "+baslik");
        kap1.ekle("uzunluk-yazma", (g, iz) -> g + "+uzunluk");
        List<String> iz1 = new ArrayList<>();
        String sonuc1 = kap1.calistir("istek", iz1);

        Kap kap2 = new Kap();
        kap2.tara(SikistirmaHalkasi.class, GunlukHalkasi.class);
        kap2.ekle("baslik-ekleme", (g, iz) -> g + "+baslik");
        kap2.ekle("uzunluk-yazma", (g, iz) -> g + "+uzunluk");
        List<String> iz2 = new ArrayList<>();
        String sonuc2 = kap2.calistir("istek", iz2);

        Kap kap3 = new Kap();
        kap3.tara(GunlukHalkasi.class, SikistirmaHalkasi.class);
        kap3.ekle("uzunluk-yazma", (g, iz) -> g + "+uzunluk");
        kap3.ekle("baslik-ekleme", (g, iz) -> g + "+baslik");
        List<String> iz3 = new ArrayList<>();
        String sonuc3 = kap3.calistir("istek", iz3);

        System.out.println("-- kurulum-1: G,S tarandi; baslik sonra uzunluk eklendi --");
        iz1.forEach(x -> System.out.println("  " + x));
        System.out.println("-- kurulum-2: S,G tarandi (aday sirasi ters); baslik sonra uzunluk eklendi --");
        iz2.forEach(x -> System.out.println("  " + x));
        System.out.println("-- kurulum-3: G,S tarandi; uzunluk sonra baslik eklendi (cagri sirasi ters) --");
        iz3.forEach(x -> System.out.println("  " + x));

        System.out.println("kurulum-1 ile kurulum-2 sirasi ayni mi (aciklamali kisim): " + iz1.equals(iz2));
        System.out.println("kurulum-1 ile kurulum-3 sirasi ayni mi (cagrili kisim de dahil): " + iz1.equals(iz3));
        System.out.println("govde sonuclari ayni mi (1 ve 2): " + sonuc1.equals(sonuc2));

        int varsayilan = 0, aciklama = 0, cagri = 0;
        for (String satir : iz1) {
            if (satir.contains("(varsayilan)")) varsayilan++;
            else if (satir.contains("(aciklama)")) aciklama++;
            else if (satir.contains("(cagri)")) cagri++;
        }
        System.out.printf("zincir: %d varsayilan, %d aciklama, %d cagri, toplam %d halka%n",
                varsayilan, aciklama, cagri, varsayilan + aciklama + cagri);

        System.out.println("-- elle kurulan zincir: kap hic devrede degil --");
        List<String> izElle = new ArrayList<>();
        SikistirmaHalkasi s1 = new SikistirmaHalkasi();
        GunlukHalkasi g1 = new GunlukHalkasi();
        String govdeElle = "istek";
        izElle.add("SikistirmaHalkasi(elle)");
        govdeElle = s1.uygula(govdeElle, izElle);
        izElle.add("GunlukHalkasi(elle)");
        govdeElle = g1.uygula(govdeElle, izElle);
        izElle.forEach(x -> System.out.println("  " + x));
        System.out.println("elle kurulumda varsayilan halka sayisi: "
                + izElle.stream().filter(x -> x.contains("varsayilan")).count());
        System.out.println("elle kurulumda ilk cagrilan sinif Sikistirma mi (kap'ta oncelik 20, Gunluk'ten sonra gelmesi gerekirdi): "
                + izElle.get(0).startsWith("Sikistirma"));
        System.out.println("kusur turu: etkisiz (istisna yok, @Halka.oncelik degeri hic okunmadi, sira degismedi)");
    }
}

@Kap.Halka(oncelik = 10)
class GunlukHalkasi implements Kap.HalkaIslevi {
    public String uygula(String govde, List<String> iz) { return govde + "+gunluk"; }
}

@Kap.Halka(oncelik = 20)
class SikistirmaHalkasi implements Kap.HalkaIslevi {
    public String uygula(String govde, List<String> iz) { return govde + "+sikistirma"; }
}
```

```
-- kurulum-1: G,S tarandi; baslik sonra uzunluk eklendi --
  istek-kimligi(varsayilan)
  GunlukHalkasi(aciklama)
  SikistirmaHalkasi(aciklama)
  baslik-ekleme(cagri)
  uzunluk-yazma(cagri)
  hata-yakalama(varsayilan)
-- kurulum-2: S,G tarandi (aday sirasi ters); baslik sonra uzunluk eklendi --
  istek-kimligi(varsayilan)
  GunlukHalkasi(aciklama)
  SikistirmaHalkasi(aciklama)
  baslik-ekleme(cagri)
  uzunluk-yazma(cagri)
  hata-yakalama(varsayilan)
-- kurulum-3: G,S tarandi; uzunluk sonra baslik eklendi (cagri sirasi ters) --
  istek-kimligi(varsayilan)
  GunlukHalkasi(aciklama)
  SikistirmaHalkasi(aciklama)
  uzunluk-yazma(cagri)
  baslik-ekleme(cagri)
  hata-yakalama(varsayilan)
kurulum-1 ile kurulum-2 sirasi ayni mi (aciklamali kisim): true
kurulum-1 ile kurulum-3 sirasi ayni mi (cagrili kisim de dahil): false
govde sonuclari ayni mi (1 ve 2): true
zincir: 2 varsayilan, 2 aciklama, 2 cagri, toplam 6 halka
-- elle kurulan zincir: kap hic devrede degil --
  SikistirmaHalkasi(elle)
  GunlukHalkasi(elle)
elle kurulumda varsayilan halka sayisi: 0
elle kurulumda ilk cagrilan sinif Sikistirma mi (kap'ta oncelik 20, Gunluk'ten sonra gelmesi gerekirdi): true
kusur turu: etkisiz (istisna yok, @Halka.oncelik degeri hic okunmadi, sira degismedi)
```

Toplam altı halka üç kaynağa bölünüyor: `istek-kimligi` ve `hata-yakalama` **varsayılan**dır
— `Kap` sınıfının hiçbir dış girdiye ihtiyaç duymadan kendi gövdesine yazdığı davranış.
`GunlukHalkasi` ve `SikistirmaHalkasi` **açıklama**dır — kaynakta bu iki sınıfı çağıran hiçbir
satır yok, yalnız üzerlerinde bir `@Halka` işareti var ve o işareti okuyan `tara` çağrısı var.
`baslik-ekleme` ile `uzunluk-yazma` ise **çağrı**dır — `kap.ekle(...)` satırı olmadan bu iki
halka zincirde hiç bulunmaz. Altı halka üç kaynağa eşit bölünüyor — ikişer ikişer — ama bu
eşitlik bir kural değil, bu dersin seçtiği örneğin bir özelliği; ortak tanımın on iki
davranışı çağrı, açıklama ve varsayılan arasında eşit bölünmüyordu, açıklama ağır basıyordu.
Kursun sorduğu soru burada da aynı: bu kez ölçülen şey bir bileşenin kuruluşu değil, bir
isteğin bir kaptan geçerken izlediği yol.

Kaynak metni yukarıdan aşağı okuyan biri bu altı halkanın yalnızca ikisini doğrudan görüyor.
`kap.ekle("baslik-ekleme", ...)` ve `kap.ekle("uzunluk-yazma", ...)` satırları oradadır, ve
bir okuyucu bu iki halkanın var olduğunu ve hangi sırayla eklendiğini kaynaktan çıkarabilir.
Geri kalan dördü kaynağın başka bir yerinde iz bırakıyor: `GunlukHalkasi` ile
`SikistirmaHalkasi` için tek iz sınıf tanımının üzerindeki `@Halka` satırı, `istek-kimligi`
ile `hata-yakalama` için ise hiçbir iz yok — bu ikisi yalnız `Kap.calistir` yönteminin
gövdesini okuyarak bulunabiliyor, ve o yöntem çağıran kodun hiç görmediği bir dosyada
duruyor. Kaynağı yalnız çağıran tarafın dosyasından okuyan biri, zincirin üçte ikisinin
nereden geldiğini kaçırıyor.

## Kap Kendi Sırasını Uygular

- **WV3.** `oncelik` değeri küçük olan açıklamalı halka önce çalışır; bu, kabın kendi
  kuralıdır ve kaynakta hiçbir yerde yazılı değildir.

Kurulum-1 ile kurulum-2 arasındaki tek fark `tara` çağrısına verilen sınıfların sırası:
birinde önce günlük, sonra sıkıştırma sınıfı taranıyor, ötekinde tam tersi. Kaynak metni
farklı yazıldığı hâlde iz listesi birebir aynı çıkıyor, çünkü kap taranan sınıfları kendi
`oncelik` alanına göre yeniden sıralıyor ve `tara` çağrısına verilen dizinin sırasını hiç
kullanmıyor. **Halkaların çalışma sırası çağıranın kaynakta yazdığı sıra değildir; kap kendi
sırasını uygular, ve iki farklı yazım aynı sırayı üretir.**

Ama bu kural yalnız açıklamayla bulunan halkalar için geçerli. Kurulum-3, kurulum-1'le aynı
tarama sırasını kullanıyor, farkı yalnız iki `ekle` çağrısının sırası: önce uzunluk, sonra
başlık. İz listesi bu kez farklı çıkıyor — `uzunluk-yazma` önce, `baslik-ekleme` sonra
görünüyor. Kap, açıklamayla bulduğu halkalar için kendi sıralama kuralını uyguluyor, ama açık
bir `ekle` çağrısıyla eklenen halkalar için hiçbir sıralama yapmıyor; onları tam olarak
çağrıldıkları sırada zincire koyuyor. Sıra kuralı yalnız kabın **keşfettiği** şeye uygulanıyor,
kabın **söylenildiği** şeye değil — bir açıklama kabın kendi kararına bırakılmış bir istektir,
bir çağrı ise çağıranın kendi kararıdır ve kap onu değiştirmiyor.

Bu ayrımın pratik bir sonucu var: iki geliştirici aynı iki açıklamalı sınıfı farklı bir
sırayla `tara`'ya verse — biri dosyaları alfabetik, öteki değişiklik tarihine göre listeleyen
bir araçla topladıysa — kaynak metinleri farklı görünür ama üretilen zincir birebir aynı
kalır. Sıra kaynakta değil, `oncelik` alanında yaşıyor; kod incelemesi yapan biri iki
sürümün de aynı davranışı ürettiğini görmek için `tara` çağrısındaki sıraya değil, açıklama
tiplerinin kendi tanımına bakmak zorunda. Açık çağrı için bu güvence yok — `ekle` çağrılarının
sırasını değiştirmek zincirin sırasını da değiştiriyor, çünkü kap orada hiçbir kural
uygulamıyor.

## Elle Kurulan Zincirde Açıklamanın Hiçbir Etkisi Yok

- **WV4.** Elle kurulan çağrıda `SikistirmaHalkasi` ile `GunlukHalkasi` doğrudan
  örnekleniyor ve `uygula` yöntemleri sırasıyla çağrılıyor; hiçbir `Kap` nesnesi
  oluşturulmuyor.
- **WV5.** `@Halka` açıklaması iki sınıfın üzerinde durmaya devam ediyor; kaldırılmadı,
  silinmedi. Elle kurulumda etkisiz kalmasının nedeni açıklamanın kaybolması değil, onu
  okuyan bir tarafın olmaması.

Son ölçüm kabı tamamen devre dışı bırakıyor: `SikistirmaHalkasi` ile `GunlukHalkasi` `new`
ile elle kuruluyor, `uygula` yöntemleri elle, sırayla çağrılıyor. İki sonuç dikkat çekiyor.
Birincisi, iz listesinde `varsayilan` etiketli hiçbir satır yok — `istek-kimligi` ve
`hata-yakalama` `Kap.calistir` yönteminin gövdesine yazılı, ve bu yöntem hiç çağrılmadığı için
o iki davranış da hiç gerçekleşmiyor. İkincisi, `SikistirmaHalkasi` önce çağrılıyor,
`GunlukHalkasi` sonra — oysa kap içinde bu ikisinin sırası tam tersiydi, çünkü
`SikistirmaHalkasi`'nin `oncelik`i 20, `GunlukHalkasi`'ninki 10. Elle çağrıda bu sayı hiç
okunmuyor; `@Halka(oncelik = 20)` açıklaması sınıfın üzerinde duruyor ama onu okuyacak bir
`tara` çağrısı, bir sıralama adımı yok. Açıklama bir özellik değil bir istektir; isteği yerine
getirecek bir kap yoksa iki sınıf da sıradan iki Java nesnesinden farksız çağrılıyor ve sıra
tamamen çağıranın elinde kalıyor.

Bu, dersin başındaki üç kaynak ayrımını tamamlıyor. Varsayılan davranış kabın kendi kodunun
parçası olduğu için kap yoksa hiç yok; açıklama bir isteği taşıdığı için okuyan kap yoksa
etkisiz; yalnız çağrı — bir yöntemin doğrudan çağrılması — kap olsun olmasın aynı davranışı
üretiyor, çünkü çağrı zaten kaynakta yazılı bir ifadedir. Bu üç davranışın kap içindeki ve kap
dışındaki farkı, kabın asıl kattığı şeyin ne olduğunu gösteriyor: kap yeni bir yetenek
eklemiyor, kaynakta yazılmayan iki türden isteği (varsayılan ve açıklama) okuyup uyguluyor.

Bu sonucun sınayıcı için pratik bir uyarısı var: `GunlukHalkasi` ya da `SikistirmaHalkasi`
sınıfını kap dışında bir birim testinde çağırmak, o sınıfın kendi mantığını doğrular ama
zincirdeki yerini, sırasını ya da onunla birlikte çalışan varsayılan halkaları hiç sınamaz.
İki ölçüm ayrı sorulara yanıt veriyor: sınıfın kendi davranışı doğru mu, ve kap onu doğru
yere mi koyuyor. Birinci soru elle kurulan nesneyle yanıtlanabilir, ikinci soru yalnız kabın
kendisi çalıştırılarak yanıtlanabilir — bu derste kurulum-1, kurulum-2 ve kurulum-3'ün
birlikte yaptığı da tam olarak bu.

## Özet

- İstek işleme zincirinin altı halkası üç kaynağa ayrıldı: ikisi kabın varsayılanı, ikisi bir
  açıklama, ikisi açık bir çağrı.
- Açıklamayla bulunan halkaların çalışma sırası, kabın kendi `oncelik` kuralına göre
  belirleniyor ve kaynaktaki tarama sırasından bağımsız; iki farklı tarama sırası aynı
  sonucu üretti.
- Açık çağrıyla eklenen halkaların sırası kabın kuralına girmiyor; çağıranın yazdığı sıra
  aynen korunuyor.
- Kap devre dışı bırakılıp aynı sınıflar elle çağrıldığında varsayılan halkalar hiç
  çalışmadı ve açıklamadaki `oncelik` değeri hiç okunmadı; açıklama okuyan bir taraf
  olmadan etkisizdi.
- İki kurulumun ürettiği govde sonucu, sıra aynı kaldığı sürece birebir aynı çıktı.

## Sonraki Adım

Bu ders bir isteğin kaptan geçerken izlediği zinciri ölçtü, ama zincirin sonunda isteğin
hangi işi karşıladığı hiç belirlenmedi — halkalar isteği yalnız değiştirdi, yönlendirmedi.
Sıradaki ders bu boşluğu kapatıyor: bir uç noktanın kaynakta hangi ifadeyle değil hangi
açıklamayla bildirildiğini, ve eşleşmeyen bir isteğe kabın ne yanıt verdiğini ölçüyor.
