Reverse Proxy Nedir? Nginx ile Gerçek Bir Kullanım Senaryosu
Node.js uygulamasını Nginx arkasına alırken URI yönlendirme, forwarded header, timeout ve 502/504 teşhisinin nasıl birlikte tasarlanacağını inceleyelim.
Bir Node.js uygulamasını doğrudan internete açabilirsiniz. Ancak TLS, istek boyutu, bağlantı yönetimi ve birden fazla uygulamaya yönlendirme gibi sorumlulukları tek tek uygulamanın içine taşımak zorunda kalabilirsiniz. Reverse proxy, istemcinin önünde görünen sunucu olup isteği uygun arka uç servise aktarır.
Forward proxy istemci adına dış dünyaya erişirken, reverse proxy sunucu tarafındaki hizmetler adına trafik kabul eder. Kullanıcı çoğunlukla hangi arka uç instance'ının yanıt verdiğini bilmez.
Örnek mimariyi tanımlamak
Aynı Linux makinesinde iki Node.js instance'ımız olduğunu varsayalım: 127.0.0.1:3001 ve 127.0.0.1:3002. Uygulamalar zaten /api/tasks endpoint'ini sunuyor. Nginx isteği bu instance'lardan birine aktaracak.
İstemci → Nginx → Node.js instance 1
→ Node.js instance 2
Bu kurulum arka uç process sayısını artırır, fakat tek makineyi hata noktası olmaktan çıkarmaz. Makine kapanırsa her iki instance da erişilemez. Load balancing ile yüksek erişilebilirliği aynı şey kabul etmemek gerekir.
Çalışılabilir bir HTTP laboratuvarı
Aşağıdaki yapılandırma, http bağlamında include edilen bir dosya için örnektir. Yalnızca localhost:8080 üzerinde dinler; internete açık production TLS yapılandırması değildir.
upstream task_api {
server 127.0.0.1:3001;
server 127.0.0.1:3002;
keepalive 16;
}
server {
listen 127.0.0.1:8080;
server_name localhost;
client_max_body_size 1m;
location /api/ {
proxy_pass http://task_api;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_connect_timeout 3s;
proxy_read_timeout 30s;
}
}
Nginx host üzerindeyken upstream localhost adresleri aynı host'u ifade eder. Nginx başka bir container içindeyse localhost artık o container'dır; servis ağına uygun adres gerekir. Yanlış localhost varsayımı, proxy kurulumlarında sık görülen bağlantı hatalarındandır.
Değişikliği etkinleştirmeden önce:
sudo nginx -t
sudo systemctl reload nginx
curl -i http://127.0.0.1:8080/api/tasks
Reload komutu systemd kullanan örnek ortam içindir. nginx -t başarısızsa yapılandırmayı düzeltmeden yeniden yüklemeyin.
proxy_pass sonundaki slash neden önemli?
Örnekte proxy_pass http://task_api; kullanıldığı için gelen URI korunur. /api/tasks isteği arka uca yine /api/tasks olarak gider.
Bu location içinde proxy_pass http://task_api/; yazarsanız URI bölümü bulunduğundan eşleşen /api/ öneki değiştirilebilir ve arka uç /tasks görebilir. Davranış location türü, rewrite ve değişken kullanımına göre farklılaşabileceğinden genellemeyi dikkatle yapın. Ayrıntılar proxy modülü belgesinde yer alır.
Arka uçta 404 alıyorsanız önce doğru uygulamaya ve doğru path'e ulaşıp ulaşmadığınızı kontrol edin. Her proxy hatası ağ bağlantı hatası değildir.
İstemci IP'si ve güven sınırı
Proxy arkasındaki uygulama TCP bağlantısının kaynağı olarak Nginx'i görür. Gerçek istemci bilgisini header'larla aktarabilirsiniz. Fakat bu header'lar dışarıdan gönderilebildiği için güvenilir sınırda yeniden yazılmaları gerekir.
Örnekte Nginx'in ilk ve tek güvenilir proxy olduğu varsayımıyla X-Forwarded-For doğrudan remote_addr ile belirleniyor. Önünde CDN veya başka proxy varsa o zincir için ayrı güven politikası gerekir.
Express tarafındaki trust proxy ayarı da yalnızca gerçek proxy topolojisine uygun yapılandırılmalıdır. Kontrolsüz güven; IP tabanlı rate limit, protokol algısı veya güvenli cookie davranışını bozabilir. Express güvenlik rehberi uygulama sınırlarını ayrıca değerlendirmek için iyi bir başlangıçtır.
Timeout ve retry iş kuralıdır
proxy_read_timeout, basitçe bütün isteğin toplam süresi değildir; upstream'den ardışık okuma işlemleri arasındaki beklemeyi kontrol eder. Uygulama ve dış servis timeout'larını birlikte tasarlayın. Her katmanda farklı ve aşırı uzun süreler, kullanıcı vazgeçse bile işlerin kaynak tüketmeye devam etmesine yol açabilir.
Retry özellikle yan etkili işlemlerde dikkat ister. Bir ödeme oluşturma isteği upstream'de tamamlanmış, ancak cevap kaybolmuş olabilir. Körlemesine tekrar, ikinci ödeme üretir. İdempotency stratejisi olmadan her başarısız isteği başka instance'a göndermek güvenilirlik sağlamaz.
Load balancing ve durum paylaşımı
Nginx bir upstream grubundaki sunucular arasında istek dağıtabilir. Yöntemler ve başarısız sunucu davranışı HTTP load balancing belgesinde açıklanır.
Ancak uygulama session bilgisini yalnızca kendi belleğinde tutuyorsa sonraki istek diğer instance'a gittiğinde kullanıcı çıkış yapmış görünebilir. Session store, dosya depolama ve arka plan işleri çoklu instance modeline uygun olmalıdır.
502, 504 ve canlıya geçiş
502 için upstream process'i, portu ve hata loglarını inceleyin. 504 için bekleme sürelerini ve arka uç bağımlılıklarını araştırın. Önce upstream'e doğrudan yerel istek atıp sonra proxy üzerinden karşılaştırmak arızanın sınırını daraltır.
Canlıya geçerken geçerli TLS sertifikası, doğru DNS, sertifika yenileme, erişim logları ve kontrollü trafik boşaltma eklenmelidir. WebSocket ve SSE gibi uzun bağlantılar için buffering ve bağlantı seçeneklerini ayrıca değerlendirin. Reverse proxy'nin değeri, uygulamanın önüne bir kutu koymak değil; ağ ve uygulama arasındaki sözleşmeyi açık hale getirmektir.
Related Posts
Monitoring ve Logging Arasındaki Fark: Sistemde Sorun Olduğunu Nasıl Anlarız?
Metrik, log ve trace verilerini kullanıcı etkisi etrafında birleştirelim; SLI/SLO, anlamlı alarmlar ve yüksek cardinality sorununu pratik örneklerle ele alalım.
Terraform ile Infrastructure as Code Mantığını Anlamak
Terraform'u komut otomasyonu yerine istenen durum yönetimi olarak ele alalım; plan, state, drift, bağımlılık grafiği ve güvenli apply sürecini örnekleyelim.
Docker Container Nasıl Çalışır? Image, Container ve Volume Mantığı
Image katmanları, çalışan container, izolasyon ve kalıcı veriyi birbirinden ayıralım; Node.js örneğiyle build ve işletim kararlarını inceleyelim.