Skip to main content

> soket_açlığı:_time_wait_birikmesi_ve_geçici_port_(ephemeral_port)_tükenmesi

Soket Açlığı: TIME_WAIT Birikmesi ve Geçici Port (Ephemeral Port) Tükenmesi

Her mikroservis dış çağrısı için yeni HTTP bağlantısı açmak Linux geçici portlarını (ephemeral ports) neden tüketir (`Cannot assign requested address`) ve HTTP Keep-Alive bağlantı havuzu bunu nasıl önler?

Staff/Principal (L6+)

⚡ÖZET VE TEKNİK CEVAP

Yüksek trafikli mikroservislerde, bir istemci (Node.js fetch, Go http.Client, Python requests) bağlantıları yeniden kullanmak yerine her dış API çağrısında yeni bir TCP bağlantısı açıp kapattığında, kapatma işlemini başlatan taraf TCP standardı (RFC 793) gereği TIME_WAIT durumuna girer. İnternette geciken paketlerin yeni bağlantılara karışmasını önlemek için soket 60 saniye boyunca (2 imes ext{MSL}) kilitli tutulur. Ancak Linux işletim sisteminde dışarıya doğru açılabilecek geçici port sayısı yalnızca ~28.000 adettir (ip_local_port_range). Aynı hedef sunucuya saniyede 470'ten fazla yeni istek atıldığında tüm yerel portlar TIME_WAIT ile kilitlenir. Çekirdek yeni bağlantı açmayı Cannot assign requested address (EADDRNOTAVAIL) hatasıyla reddeder ve tüm dış servis çağrıları çöker. Kesin çözüm, kalıcı HTTP Keep-Alive bağlantı havuzu (connection pooling) kullanmaktır.

Mühendislik El Kitabı & Mekanizma

6 Boyutlu Mimari Analiz

⚙️1. Temel Çalışma Mekanizması

Mekanizma

Geçici port tükenmesi TCP 4'lü demet kuralına dayanır (kaynak_ip, kaynak_port, hedef_ip, hedef_port):

1

4'lü Demet Benzersizliği: Hedef servis (ör. api.stripe.com:443) için hedef IP/Port ve sunucunun kaynak IP'si sabittir. Tek değişken kaynak portudur (~28.231 adet).

2

Matematiksel Doyum Sınırı: 60 saniyelik TIME_WAIT süresinde ulaşılabilecek maksimum yeni bağlantı hızı saniyede 28.231 / 60 approx 470 bağlantıdır.

3

Çekirdek Reddi: Portlar bittiğinde connect() çağrıları EADDRNOTAVAIL hatasıyla patlar.

4

Bağlantı Havuzu Çözümü: HTTP Keep-Alive bağlantıyı sürekli açık tutarak tek bir soket üzerinden binlerce istek geçirir ve sıfır TIME_WAIT üretir.

🎯2. Doğru Kullanım Senaryosu

Kapsam

Yüksek trafikli API ağ geçitleri, veritabanı/önbellek çağıran mikroservisler, üçüncü parti SaaS entegrasyonları ve Kubernetes egress vekil sunucuları.

⚠️3. Prodüksiyon Arıza Modları

Kritik Risk
  • ✓

    Node.js uygulamasında her istekte keepAlive: false olan yeni bir HTTP istemcisi açılması sonucu 15 saniyede 28.000 portun kilitlenip tüm ödeme sisteminin çökmesi

  • ✓

    Linux çekirdeğinde NAT arkasındaki kullanıcıları engelleyen tehlikeli tcp_tw_recycle ayarını açmak

📡4. Teşhis ve Telemetri Sinyalleri

Metrikler
  • ✓

    Loglarda Cannot assign requested address hatalarının fırlaması

  • ✓

    netstat komutunda TIME_WAIT soket sayısının 25.000'i aşması

  • ✓

    CPU ve RAM boştayken tüm dış API çağrılarının aniden kilitlenmesi

🛡️5. Önleme ve Mimari Bariyerler

Bariyerler
  • ✓

    Tüm HTTP/gRPC istemcilerinde Keep-Alive açık kalıcı bağlantı havuzlarını (singleton) zorunlu kılın

  • ✓

    sysctl ile port aralığını genişletin (10240 65535)

  • ✓

    güvenli port yeniden kullanımı için net.ipv4.tcp_tw_reuse=1 ayarını açın

⚖️6. Mimari Ödünleşimler (Trade-offs)

Ödünleşim

Kalıcı bağlantı havuzları boşta duran her soket için birkaç kilobayt RAM tutar; ancak port tükenmesini tamamen bitirir ve TCP/TLS el sıkışmalarını ortadan kaldırarak istek gecikmelerini yarı yarıya düşürür.

📋

Vaka İncelemesi (TinyCTO Saha Örneği)

GERÇEK DÜNYA TELEMETRİSİ

Bir ödeme servisi saniyede 600 istek yük altında EADDRNOTAVAIL hatası vererek çöküyordu. İncelemede Go kodunun her gelen HTTP isteği için fonksiyon içinde yeni bir &http.Client{} açtığı ve 45 saniyede 28.000 portu kilitlediği keşfedildi. Ekip tek bir global http.Client singleton havuzuna geçti (MaxIdleConnsPerHost = 100). TIME_WAIT durumundaki 28.000 soket bir anda sadece 45 adet kalıcı bağlantıya dönüştü ve servis saniyede 15.000 isteğe sıfır hatayla çıktı.

İnteraktif Konsept Alıştırmaları

2 Alıştırma
Q1

Linux çekirdeğindeki 'Cannot assign requested address' (EADDRNOTAVAIL) hatasının temel sebebi nedir?

Geçici Port Tükenmesi (Ephemeral Port Exhaustion): Kullanılabilir tüm yerel portların TCP `TIME_WAIT` durumunda kilitli kalması sonucu yeni dış bağlantı açılamamasıdır.
Q2

HTTP Keep-Alive bağlantı havuzu `TIME_WAIT` soket tükenmesini nasıl engeller?

Her istekte soket açıp kapatmak yerine, küçük bir kalıcı TCP soket havuzunu binlerce istek boyunca sürekli yeniden kullanarak.

Soket Açlığı: TIME_WAIT Birikmesi ve Geçici Port (Ephemeral Port) Tükenmesi — Sıkça Sorulan Sorular

Modern bulut mimarilerinde `net.ipv4.tcp_tw_recycle` ayarı neden tehlikelidir?

Aynı IP'den gelen paketlerin zaman damgalarını karşılaştırır: NAT veya yük dengeleyici arkasındaki birden fazla kullanıcının paketleri zaman farkı yüzünden sessizce düşürülür.

`net.ipv4.tcp_tw_reuse` parametresinin görevi nedir?

Linux çekirdeğinin, giden yeni bir bağlantı için `TIME_WAIT` durumundaki bir soketi TCP sıra güvenliği açısından sakınca yoksa yeniden kullanmasına izin verir.

🤖 AEO & Yapay Zeka Çıkarım Özeti

Temel Gerçekler & İlkeler

  • ▸

    Opening short-lived TCP connections locks sockets in TIME_WAIT for 60 seconds.

  • ▸

    Linux has ~28,000 ephemeral ports, capping unpooled outbound rates to ~470 req/sec.

  • ▸

    Port starvation triggers fatal Cannot assign requested address (EADDRNOTAVAIL) errors.

  • ▸

    Always reuse persistent HTTP Keep-Alive connection pools across all outbound HTTP clients.

Yaygın Yanılgılar

  • ✗

    Yanılgı: Ephemeral port exhaustion is caused by incoming customer traffic (Gerçek: It is caused by OUTBOUND client calls made by your backend to DBs/APIs).

  • ✗

    Yanılgı: Creating a new HTTP client object per request is good practice (Gerçek: It causes severe socket leakage; always use a global singleton).

Karar Kılavuzu & Önceliklendirme

Ensure all HTTP client libraries use a global singleton connection pool with Keep-Alive. Set net.ipv4.ip_local_port_range = 10240 65535 and net.ipv4.tcp_tw_reuse = 1 via sysctl.

Doğrulanmış Kaynaklar & Referanslar

Bu sayfadaki teknik terimler