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

1. Temel Çalışma Mekanizması

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

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ı

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

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

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)

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 Örneği)

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