Blog
Mert Özen'in yazılım geliştirme, backend, frontend ve DevOps üzerine blog yazıları.
Yavaş İstek Nereden Geliyor: curl -w, DevTools Timing ve Wireshark ile Network Teşhisi
Yavaş bir isteğin süresi DNS, TCP, TLS, sunucu (TTFB) ve indirme fazlarına bölünür; her fazın tanınabilir bir imzası var. netem ile 50 ms RTT altında curl -w ile beş vaka (keep-alive yok, IPv6 denemesi, TLS 1.2, yavaş sunucu, büyük cevap), .NET'in System.Net metric'leri, dotnet-counters ve Wireshark için TLS key log dosyası.
HTTP/3 ve QUIC: UDP Üzerinde Güvenli Transport, Alt-Svc ve .NET'te HTTP/3
HTTP/3, TCP yerine UDP üzerinde çalışan QUIC'i kullanır: TLS 1.3 gömülü, sıralama stream başına, yeni bağlantıda bir RTT daha az. Alt-Svc ve DNS HTTPS kaydıyla keşif, macOS'ta QuicConnection.IsSupported=false, Linux container'da libmsquic ile çalışan Kestrel HTTP/3'ü loopback'te HTTP/3'ün neden daha hızlı çıkmadığı ve 50 ms RTT'de kazandırdığı tam bir RTT gerçek ölçümlerle.
HTTP/2: Binary Framing, Multiplexing, HPACK ve Kestrel'de HTTP/2
HTTP/2 semantiği değiştirmez; mesajları stream'lere ait binary frame'lere bölüp tek TCP bağlantısında iç içe taşır, header'ları HPACK ile sıkıştırır. curl ile pseudo-header'lar ve h2c, 20 eşzamanlı istekte 20 bağlantıya karşı tek bağlantı, Kestrel'in 100 stream limiti, HttpClient'ın varsayılan 1.1'i ve Server Push yerine 103 Early Hints.
HTTP Caching ve Conditional Request'ler: Cache-Control, ETag ve 304
HTTP cache, Cache-Control ile kopyanın ne kadar taze kalacağına, ETag veya Last-Modified ile süresi dolunca 304 Not Modified ile ucuzca doğrulanmasına karar verir. no-cache ile no-store farkı, Cache-Control'süz statik dosyaların heuristic freshness'ı, deploy sonrası eski index.html bug'ı ve HttpClient'ın kendi cache'i olmadığı için yazılan bir ETag handler'ı.
HTTP/1.1'i Kablodan Okumak: Request/Response Formatı, Method Semantiği ve Keep-Alive
HTTP/1.1 bir metin protokolü: start line, header'lar, boş satır ve Content-Length ya da chunked ile çerçevelenen body. nc ve openssl s_client ile elle yazılan istekler, Host'suz isteğe 400, chunked'daki 3d'nin anlamı, safe/idempotent method'lar ve yalnız idempotent istekleri tekrar deneyen bir handler, keep-alive ve request smuggling'e karşı Kestrel.
TLS 1.3 Handshake'i: Sertifika Zinciri, SNI, ALPN ve Post-Quantum Key Exchange
TLS 1.3, key_share'i ClientHello'ya koyarak şifreli kanalı tek RTT'de kurar; ECDHE forward secrecy, X25519MLKEM768 ise post-quantum koruma sağlar. openssl s_client ile handshake, 285'ten 1.525 byte'a büyüyen ClientHello, sertifika zinciri hataları, SNI/ECH/ALPN, 0-RTT ve .NET'in macOS'ta TLS 1.2'de kalması.
DNS Nasıl Çalışır: Resolver, Record Tipleri, TTL ve dig ile Sorgulamak
DNS bir ismi stub resolver, recursive resolver, root, TLD ve authoritative sunucu zinciriyle çözer ve her cevabı TTL süresince cache'ler. dig +trace, A/AAAA/CNAME/MX/TXT/CAA/HTTPS kayıtları, negatif cache, DoH ve HttpClient'ın açık bağlantılarının DNS değişikliğini neden görmediğini gösteren blue-green denemesi.
TCP Nasıl Çalışır: 3-Way Handshake, Congestion Control ve HttpClient Socket Exhaustion
TCP güvenilir bir byte akışı için 3-way handshake ile bağlantı kurar, slow start ile yavaş başlar ve kapanışta TIME_WAIT'te bekler; her istekte new HttpClient bu yüzden port'ları tüketir. 500 istekte 500 TIME_WAIT, TLS ile 6 kat yavaşlık, IHttpClientFactory, PooledConnectionLifetime ve handler varsayılanları gerçek çıktılarla.
IP Adresi, Subnet, Port ve NAT: localhost, 0.0.0.0 ve Container'larda Bağlantı
IP adresi bir arayüzü, port o makinedeki bir socket'i bulur; 127.0.0.1'e bind olan bir sunucuya yalnızca o makinenin içinden ulaşılır. RFC 1918 özel adresleri, CIDR ile subnet, NAT, ephemeral port'lar, address already in use ve container'da localhost'a bind olan Kestrel'in neden Empty reply verdiği gerçek çıktılarla.
Bir URL'e Enter'a Bastığında Ne Olur: DNS'ten Render'a Uçtan Uca
Enter'a bastığında tarayıcı URL'i parçalar, DNS ile IP'yi bulur, TCP ve TLS 1.3 ile bağlantı kurar, HTTP isteğini gönderir ve cevabı render eder; yeni bir bağlantıda ilk byte'tan önce en az üç-dört RTT harcanır. Kendi Kestrel sunucumuza curl -v ve curl -w ile her fazı satır satır okuyoruz.
Big-O'nun Söylemedikleri: Sabitler, Cache ve BenchmarkDotNet ile Ölçmek
Big-O büyümeyi söyler ama gerçek süreyi sabitler, cache, allocation ve girdi dağılımı belirler. 10 kitapta O(n²) insertion sort'un LINQ'ten iki kat hızlı olması, LinkedList'in 3,8 kat yavaşlığı, kötü GetHashCode ile Dictionary'nin O(n²)'ye düşmesi ve doubling experiment ile complexity'yi ölçerek tahmin etmek.
Amortized Analysis: List<T>.Add Neden O(1) Sayılır
List<T>.Add bazen bütün listeyi kopyalar ama kapasite ikiye katlandığı için n Add'in toplam maliyeti 3n'i geçmez; bu yüzden amortized O(1) sayılır. Aggregate, accounting ve potential method, +10 büyümenin 50 milyar kopyası, Dictionary'nin asal boyutları ve 38 ms'lik resize spike'ı gerçek ölçümlerle.