Bloga geri dön

Mikroservis Mimarisi için Proxy: API Koruması, Yük Dengeleme ve Güvenlik

Proxy'nin mikro hizmet mimarisine entegrasyonu için kapsamlı rehber: API koruması, yük dengeleme, hizmetler arası iletişim güvenliği ve yapılandırma örnekleri.

📅18 Şubat 2026
```html

Mikroservis mimarisi, hizmetler arasında güvenilir iletişim, dış API isteklerinin korunması ve yük dengelemesi gerektirir. Proxy sunucuları, hizmetler, dış API'ler ve istemciler arasında aracılık yaparak bu sorunları çözer. Bu kılavuzda, proxy'yi mikroservis altyapısına nasıl doğru bir şekilde entegre edeceğimizi, farklı senaryolar için hangi proxy türlerini kullanacağımızı ve güvenli iletişimi nasıl ayarlayacağımızı inceleyeceğiz.

Mikroservis mimarisinde proxy'nin rolü

Mikroservis mimarisinde proxy sunucuları, anonimlik veya engelleri aşmak için geleneksel proxy kullanımından farklı olarak birkaç kritik işlevi yerine getirir. Burada proxy, sistem bileşenleri arasında güvenilir ve güvenli iletişim sağlayarak altyapının ayrılmaz bir parçası haline gelir.

Mikroservislerde proxy'nin ana rolleri:

  • API Gateway — tüm istemci istekleri için tek giriş noktası, istekleri ilgili mikroservislere yönlendirir ve sistemin iç mimarisini gizler
  • Sidecar Proxy — her hizmetin yanında çalışan proxy konteyneri (Service Mesh modeli), tüm gelen ve giden trafiği yakalar
  • Reverse Proxy — bir hizmetin birden fazla örneği arasında yük dağılımı, hata toleransı sağlar
  • Forward Proxy — dış API'lere yapılan giden isteklerin kontrolü ve korunması, iç altyapının IP adreslerini gizler
  • Güvenlik Proxy'si — SSL/TLS sonlandırması, kimlik doğrulama, yetkilendirme, DDoS ve diğer saldırılara karşı koruma

Proxy'ler, önemli mimari kalıpların uygulanmasına olanak tanır: circuit breaker (çalışmayan hizmetlerin otomatik olarak devre dışı bırakılması), retry logic (hatalarda tekrar deneme), rate limiting (istek sıklığının sınırlanması), request/response transformation (veri formatlarının dönüştürülmesi). Tüm bunlar, sistemi hatalara karşı daha dayanıklı hale getirir ve karmaşık dağıtık altyapının yönetimini kolaylaştırır.

Önemli: Mikroservis mimarisinde proxy'ler iki düzeyde çalışır — istemciler için dış bir geçit (API Gateway) ve hizmetler arasında iç proxy'ler (Service Mesh). Her iki düzey de sistemin güvenliği ve güvenilirliği için kritik öneme sahiptir.

Farklı kullanım senaryoları için proxy türleri

Proxy türünün seçimi, mikroservis mimarisindeki belirli bir göreve bağlıdır. Farklı senaryolar, hız, güvenilirlik, anonimlik veya coğrafi dağılım gibi farklı özellikler gerektirir.

Senaryo Proxy Türü Neden
Hizmetler arası iç iletişim HTTP/HTTPS proxy (Envoy, NGINX) Maksimum hız, düşük gecikme, HTTP/2 desteği
Rate limitleri olan dış API'lere istekler Konut proxy'leri Rate limitlerin aşılması, gerçek kullanıcı IP'leri, düşük blokaj riski
Analiz için veri kazıma Veri merkezi proxy'leri Yüksek hız, düşük maliyet, toplu istekler için uygun
Mobil API'lerle çalışma Mobil proxy'ler Gerçek mobil kullanıcıları taklit etme, yalnızca mobil API'lere erişim
Yük dengeleme Reverse Proxy (HAProxy, NGINX) Trafiğin dağıtımı, sağlık kontrolleri, arızalarda otomatik geçiş
Coğrafi olarak dağıtılmış sistem Coğrafi hedefleme ile konut proxy'leri Bölgesel API'lere erişim, veri yerelleştirme gereksinimlerine uyum

Mikroservisler arasındaki iç iletişim için genellikle, düşük gecikme ve yüksek bant genişliği için optimize edilmiş Envoy Proxy veya NGINX gibi özel proxy çözümleri kullanılır. Bu çözümler, modern protokolleri (HTTP/2, gRPC) destekler ve Service Mesh sistemleriyle entegre olur.

Dış API'lerle çalışırken, seçim belirli hizmetin gereksinimlerine bağlıdır. Eğer API, katı rate limitlere sahipse veya veri merkezi IP'lerinden gelen istekleri engelliyorsa, konut proxy'leri gereklidir. Hızın anonimlikten daha önemli olduğu toplu veri toplama durumlarında, veri merkezi proxy'leri uygundur. Mobil proxy'ler, cihaz türünü kontrol eden veya mobil IP adresleri gerektiren API'lerle çalışırken gereklidir.

Proxy olarak API Gateway: koruma ve yönlendirme

API Gateway, mikroservis sistemine yapılan tüm istemci istekleri için tek giriş noktası olan özel bir proxy sunucusudur. İstemciler, doğrudan birçok farklı hizmete erişmek yerine, tüm isteklerini tek bir API Gateway adresine gönderir ve bu sunucu, istekleri gerekli hizmetlere yönlendirir.

API Gateway'in ana işlevleri:

  • İstek yönlendirme — hangi mikroservisin isteği işlemesi gerektiğini URL, başlıklar veya diğer parametreler temelinde belirleme
  • Kimlik doğrulama ve yetkilendirme — token'ların (JWT, OAuth) kontrolü, farklı hizmetlere erişim yönetimi
  • Rate Limiting — aşırı yüklenme ve DDoS koruması için bir istemciden gelen isteklerin sayısını sınırlama
  • Cevap toplama — birkaç hizmetten gelen verileri tek bir yanıt halinde birleştirme
  • Protokol dönüştürme — REST'i gRPC'ye, HTTP/1.1'i HTTP/2'ye dönüştürme
  • Önbellekleme — sıkça talep edilen verileri saklayarak hizmetlerin yükünü azaltma
  • Günlükleme ve izleme — tüm isteklerin merkezi metrik ve günlük toplama

Popüler API Gateway çözümleri: Kong, Tyk, AWS API Gateway, Azure API Management, NGINX Plus, Traefik. Seçim, sistemin ölçeğine, performans gereksinimlerine ve kullanılan bulut platformuna bağlıdır.

// NGINX'in API Gateway olarak yapılandırma örneği
upstream auth_service {
    server auth:8001;
}

upstream user_service {
    server user:8002;
}

upstream order_service {
    server order:8003;
}

server {
    listen 80;
    server_name api.example.com;

    # İstek sıklığı sınırlaması
    limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;

    location /api/auth/ {
        limit_req zone=api_limit burst=20;
        proxy_pass http://auth_service/;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

    location /api/users/ {
        # Proxy öncesi token kontrolü
        auth_request /auth/verify;
        proxy_pass http://user_service/;
    }

    location /api/orders/ {
        auth_request /auth/verify;
        proxy_pass http://order_service/;
    }

    # Token'ların kontrolü için iç endpoint
    location = /auth/verify {
        internal;
        proxy_pass http://auth_service/verify;
        proxy_pass_request_body off;
        proxy_set_header Content-Length "";
    }
}

API Gateway, sistemin iç mimarisini dış istemcilerden gizler. İstemciler, kaç tane mikroservisin olduğunu ve bunların nasıl etkileştiğini bilmez — sadece tek bir API görürler. Bu, sürümlemeyi kolaylaştırır, iç yapıyı değiştirmeye olanak tanır ve güvenliği artırır, çünkü iç hizmetler doğrudan internete erişilemez.

Service Mesh ile entegrasyon (Istio, Linkerd)

Service Mesh, mikroservisler arasındaki iletişimi yönetmek için proxy sunucularını kullanan bir altyapı katmanıdır; her hizmetin yanında (Sidecar modeli) dağıtılır. API Gateway'den farklı olarak, yalnızca dış trafiği değil, hizmetler arasındaki tüm iç trafiği kontrol eder.

En popüler Service Mesh çözümleri — Istio (Envoy Proxy'yi sidecar olarak kullanır) ve Linkerd (kendi hafif proxy'sini kullanır). Kubernetes'teki her pod'un yanına otomatik olarak bir proxy konteyneri yerleştirir, tüm gelen ve giden trafiği yakalar.

Proxy üzerinden Service Mesh'in sağladığı olanaklar:

  • Mutual TLS (mTLS) — hizmetler arasındaki tüm trafiğin otomatik şifrelenmesi ve karşılıklı kimlik doğrulama
  • Trafik Yönetimi — yönlendirme yönetimi, kanarya dağıtımları, A/B testleri
  • Gözlemlenebilirlik — kodda değişiklik yapmadan otomatik metrik, iz ve günlük toplama
  • Dayanıklılık — devre kesici, tekrar deneme mantığı, zaman aşımı yönetimi, hata enjekte etme ile test etme
  • Hizmet Keşfi — hizmetlerin otomatik keşfi ve yük dengelemesi
# Yönlendirme için Istio VirtualService yapılandırma örneği
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: user-service
spec:
  hosts:
  - user-service
  http:
  - match:
    - headers:
        version:
          exact: "v2"
    route:
    - destination:
        host: user-service
        subset: v2
  - route:
    - destination:
        host: user-service
        subset: v1
      weight: 90
    - destination:
        host: user-service
        subset: v2
      weight: 10  # Kanarya dağıtımı: v2 için %10 trafik

---
# Circuit Breaker ile kaskad hatalardan korunma
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: user-service
spec:
  host: user-service
  trafficPolicy:
    connectionPool:
      tcp:
        maxConnections: 100
      http:
        http1MaxPendingRequests: 50
        maxRequestsPerConnection: 2
    outlierDetection:
      consecutiveErrors: 5
      interval: 30s
      baseEjectionTime: 30s
      maxEjectionPercent: 50

Service Mesh, "dağıtık monolit" sorununu çözer — hizmetler arasındaki etkileşim mantığının (tekrar deneme, zaman aşımı, devre kesici) her hizmetin kodunda tekrarlanması. Bunun yerine, tüm bu mantık proxy katmanına taşınır, bu da hizmetlerin kodunu basitleştirir ve sistemin tutarlı davranışını sağlar.

Önemli bir avantaj — trafiğin tam şeffaflığı. Hizmetler arasındaki her istek, metrikleri günlüğe kaydeden proxy üzerinden geçer: yanıt süresi, hata kodları, yük boyutu. Bu veriler otomatik olarak izleme sistemlerine (Prometheus, Grafana) ve izleme sistemlerine (Jaeger, Zipkin) gönderilir ve dağıtık sistemin çalışması hakkında tam bir resim oluşturur.

Dış API'lere yapılan isteklerin proxy üzerinden korunması

Mikroservisler genellikle dış API'lerle etkileşimde bulunur: ödeme sistemleri, coğrafi konum servisleri, sosyal medya API'leri, veri sağlayıcıları. Dış API'lere doğrudan yapılan istekler, birkaç sorunu beraberinde getirir: iç altyapının IP adreslerinin açığa çıkması, rate limitlerin aşılması durumunda engellenme riski, giden trafiğin kontrolünün olmaması.

Giden istekler için proxy kullanmak, bu sorunları çözer ve ek olanaklar sunar:

  • Altyapının gizlenmesi — dış API'ler proxy'nin IP adreslerini görür, sunucularınızın IP adreslerini değil
  • Rate limitlerin aşılması — istekleri dağıtmak için IP adreslerinin döndürülmesi
  • Coğrafi dağılım — gerekli ülkelerdeki proxy üzerinden bölgesel API'lere erişim
  • Merkezi yönetim — tüm giden isteklerin tek bir kontrol noktası
  • Cevapların önbelleğe alınması — pahalı API'lere yapılan isteklerin sayısını azaltma
  • İzleme ve günlüğe kaydetme — dış hizmetlere yapılan tüm çağrıların izlenmesi
// Python: dış API'lere yapılan istekler için proxy ayarı
import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry

class ExternalAPIClient:
    def __init__(self, proxy_url, proxy_rotation=False):
        self.session = requests.Session()
        
        # Proxy ayarı
        self.proxies = {
            'http': proxy_url,
            'https': proxy_url
        }
        
        # Dayanıklılık için tekrar deneme mantığı
        retry_strategy = Retry(
            total=3,
            backoff_factor=1,
            status_forcelist=[429, 500, 502, 503, 504],
            allowed_methods=["GET", "POST"]
        )
        adapter = HTTPAdapter(max_retries=retry_strategy)
        self.session.mount("http://", adapter)
        self.session.mount("https://", adapter)
    
    def call_payment_api(self, data):
        """Ödeme API'sine proxy üzerinden istek"""
        try:
            response = self.session.post(
                'https://api.payment-provider.com/charge',
                json=data,
                proxies=self.proxies,
                timeout=10,
                headers={'User-Agent': 'MyService/1.0'}
            )
            response.raise_for_status()
            return response.json()
        except requests.exceptions.RequestException as e:
            # Hata günlüğü
            print(f"Ödeme API hatası: {e}")
            raise

# Proxy havuzuyla döndürme için kullanım
class ProxyPool:
    def __init__(self, proxy_list):
        self.proxies = proxy_list
        self.current = 0
    
    def get_next(self):
        proxy = self.proxies[self.current]
        self.current = (self.current + 1) % len(self.proxies)
        return proxy

# Başlatma
proxy_pool = ProxyPool([
    'http://user:pass@proxy1.example.com:8080',
    'http://user:pass@proxy2.example.com:8080',
    'http://user:pass@proxy3.example.com:8080'
])

# Her istek için bir sonraki proxy kullanılır
client = ExternalAPIClient(proxy_pool.get_next())

Sıkı kısıtlamalara sahip veya veri merkezi IP'lerinden gelen istekleri engelleyen dış API'lerle çalışırken, konut proxy'leri gereklidir. Bunlar, gerçek ev kullanıcılarının IP adreslerini sağlar, bu da blokaj riskini azaltır ve coğrafi kısıtlamaları aşmayı mümkün kılar.

// Node.js: dış API'ler için otomatik döndürme ile proxy
const axios = require('axios');
const HttpsProxyAgent = require('https-proxy-agent');

class ExternalAPIService {
  constructor(proxyList) {
    this.proxyList = proxyList;
    this.currentProxyIndex = 0;
    this.requestCounts = new Map(); // Rate limiting için istek sayacı
  }

  getNextProxy() {
    const proxy = this.proxyList[this.currentProxyIndex];
    this.currentProxyIndex = (this.currentProxyIndex + 1) % this.proxyList.length;
    return proxy;
  }

  async callAPI(endpoint, data, options = {}) {
    const proxyUrl = this.getNextProxy();
    const agent = new HttpsProxyAgent(proxyUrl);

    // Rate limiting: proxy başına dakikada en fazla 100 istek
    const proxyKey = proxyUrl;
    const now = Date.now();
    const count = this.requestCounts.get(proxyKey) || { count: 0, resetTime: now + 60000 };
    
    if (count.count >= 100 && now < count.resetTime) {
      // Bir sonraki proxy'ye geçiyoruz
      return this.callAPI(endpoint, data, options);
    }

    try {
      const response = await axios({
        method: options.method || 'POST',
        url: endpoint,
        data: data,
        httpsAgent: agent,
        timeout: options.timeout || 10000,
        headers: {
          'User-Agent': 'Mozilla/5.0 (compatible; MyService/1.0)',
          ...options.headers
        }
      });

      // Sayacı güncelle
      if (now >= count.resetTime) {
        this.requestCounts.set(proxyKey, { count: 1, resetTime: now + 60000 });
      } else {
        count.count++;
      }

      return response.data;
    } catch (error) {
      if (error.response?.status === 429) {
        // Rate limit aşıldı - başka bir proxy'ye geçiyoruz
        console.log(`Rate limit ${proxyUrl} üzerinde, proxy değiştiriliyor`);
        return this.callAPI(endpoint, data, options);
      }
      throw error;
    }
  }
}

// Kullanım
const apiService = new ExternalAPIService([
  'http://user:pass@proxy1.example.com:8080',
  'http://user:pass@proxy2.example.com:8080'
]);

module.exports = apiService;

Yük dengeleme ve hata toleransı

Proxy sunucuları, yük dengelemesi ve arızalarda otomatik geçiş yoluyla mikroservis sisteminin yüksek erişilebilirliğini sağlamakta önemli bir rol oynar. Bir hizmetin birden fazla örneği çalıştığında (yatay ölçeklendirme için), proxy istekleri bunlar arasında dağıtır ve dengeli bir yük sağlar.

Yük dengeleme için temel algoritmalar:

  • Round Robin — listedeki her sunucuya sırayla istek gönderme, homojen sunucular için basit ve etkili
  • Least Connections — en az aktif bağlantıya sahip sunucuya istek gönderme, uzun süreli istekler için uygundur
  • IP Hash — istemcileri IP'lerine göre belirli bir sunucuya bağlama, sticky session'ları sağlar
  • Weighted Round Robin — sunucuların gücüne göre dağıtım (daha güçlü olanlar daha fazla istek alır)
  • Random — rastgele sunucu seçimi, durumdan bağımsız hizmetler için uygundur
# HAProxy yapılandırması sağlık kontrolleri ile yük dengelemesi için
global
    maxconn 4096
    log stdout format raw local0

defaults
    mode http
    timeout connect 5s
    timeout client 50s
    timeout server 50s
    option httplog

frontend api_frontend
    bind *:80
    default_backend api_servers

backend api_servers
    balance roundrobin
    
    # Sağlık kontrolü: her 2 saniyede bir /health kontrolü
    option httpchk GET /health
    http-check expect status 200
    
    # Tekrar deneme mantığı
    retries 3
    option redispatch
    
    # Ağırlıklı sunucular (server3 iki kat daha güçlü)
    server server1 10.0.1.10:8080 check weight 1 maxconn 500
    server server2 10.0.1.11:8080 check weight 1 maxconn 500
    server server3 10.0.1.12:8080 check weight 2 maxconn 1000
    
    # Yedek sunucu (sadece ana sunucular kullanılamıyorsa)
    server backup1 10.0.2.10:8080 check backup

Sağlık kontrolleri, hata toleransı için kritik bir işlevdir. Proxy, her sunucunun erişilebilirliğini düzenli olarak kontrol eder (genellikle /health veya /ready HTTP endpoint'i üzerinden) ve çalışmayan sunucuları otomatik olarak dengeleme havuzundan çıkarır. Sunucu geri döndüğünde ve sağlık kontrollerine yanıt vermeye başladığında, otomatik olarak havuza geri döner.

Proxy üzerinden hata toleransı stratejileri:

  • Aktif Sağlık Kontrolleri — proxy, sunucuların erişilebilirliğini kontrol etmek için aktif olarak sorgular
  • Pasif Sağlık Kontrolleri — proxy, gerçek istekleri izler ve hata birikimi durumunda sunucuları çıkarır
  • Circuit Breaker — kaskad hataları önlemek için sorunlu hizmetin geçici olarak devre dışı bırakılması
  • Graceful Degradation — hatalar durumunda basitleştirilmiş çalışma modu veya önbelleğe alınmış verilere geçiş
  • Yedek Sunucuya Geçiş — otomatik olarak yedek sunuculara veya bölgelere geçiş
// Python: dış hizmetlere proxy için Circuit Breaker uygulaması
from datetime import datetime, timedelta
from enum import Enum

class CircuitState(Enum):
    CLOSED = "closed"      # Normal çalışma
    OPEN = "open"          # Hizmet erişilemez, istekler engelleniyor
    HALF_OPEN = "half_open"  # Kurtarma sonrası test modu

class CircuitBreaker:
    def __init__(self, failure_threshold=5, timeout=60, success_threshold=2):
        self.failure_threshold = failure_threshold  # Açılmadan önceki hata sayısı
        self.timeout = timeout  # Kurtarma denemeleri için saniye
        self.success_threshold = success_threshold  # Kapatma için başarı sayısı
        
        self.state = CircuitState.CLOSED
        self.failures = 0
        self.successes = 0
        self.last_failure_time = None
    
    def call(self, func, *args, **kwargs):
        if self.state == CircuitState.OPEN:
            if datetime.now() - self.last_failure_time > timedelta(seconds=self.timeout):
                self.state = CircuitState.HALF_OPEN
                print("Devre kesici: HALF_OPEN'a geçiş")
            else:
                raise Exception("Devre kesici AÇIK: hizmet erişilemez")
        
        try:
            result = func(*args, **kwargs)
            self._on_success()
            return result
        except Exception as e:
            self._on_failure()
            raise e
    
    def _on_success(self):
        self.failures = 0
        if self.state == CircuitState.HALF_OPEN:
            self.successes += 1
            if self.successes >= self.success_threshold:
                self.state = CircuitState.CLOSED
                self.successes = 0
                print("Devre kesici: kurtarma, CLOSED'a geçiş")
    
    def _on_failure(self):
        self.failures += 1
        self.last_failure_time = datetime.now()
        if self.failures >= self.failure_threshold:
            self.state = CircuitState.OPEN
            print(f"Devre kesici AÇIK: {self.failures} ardışık hata")

# Kullanım
breaker = CircuitBreaker(failure_threshold=3, timeout=30)

def call_external_service():
    # Proxy üzerinden dış API'ye istek kodunuz
    pass

try:
    result = breaker.call(call_external_service)
except Exception as e:
    # Yedekleme mantığı: önbellek, varsayılan değerler vb.
    print(f"Hizmet erişilemez: {e}")

Hizmetler arası iletişim güvenliği

Mikroservis mimarisinde proxy sunucuları, birkaç güvenlik katmanı sağlar: trafik şifreleme, hizmet kimlik doğrulama, saldırılara karşı koruma ve ağ segmentlerinin izolasyonu. Güvenlik ayarları doğru yapılmadığında, hizmetler arası iç trafik ele geçirilebilir veya sahte olabilir.

Proxy üzerinden güvenlik için ana noktalar:

  • Mutual TLS (mTLS) — hem istemci hem de sunucu, birbirlerinin sertifikalarını kontrol eder. Service Mesh, tüm hizmetler arasında mTLS'yi otomatik olarak ayarlar
  • TLS Sonlandırması — proxy, HTTPS trafiğini sınırda şifreler, kontrol eder ve hizmetlere güvenli bir kanaldan iletir
  • JWT Doğrulaması — istek hizmete ulaşmadan önce proxy düzeyinde erişim token'larının kontrolü
  • IP Beyaz Listeleme — hizmetlere yalnızca izin verilen IP adreslerinden erişim kısıtlaması
  • DDoS Koruması — rate limiting, bağlantı limitleri, SYN flood koruması proxy düzeyinde
  • WAF (Web Uygulama Güvenlik Duvarı) — kötü niyetli isteklerin filtrelenmesi, SQL injection, XSS koruması
# SSL/TLS ve güvenlik ile NGINX yapılandırması
server {
    listen 443 ssl http2;
    server_name api.internal.example.com;

    # SSL sertifikaları
    ssl_certificate /etc/nginx/certs/api.crt;
    ssl_certificate_key /etc/nginx/certs/api.key;
    
    # Modern protokoller ve şifreler
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;
    
    # mTLS için istemci sertifikası
    ssl_client_certificate /etc/nginx/certs/ca.crt;
    ssl_verify_client on;
    
    # Güvenli başlıklar
    add_header Strict-Transport-Security "max-age=31536000" always;
    add_header X-Frame-Options "DENY" always;
    add_header X-Content-Type-Options "nosniff" always;
    
    # Rate limiting
    limit_req_zone $binary_remote_addr zone=api:10m rate=100r/s;
    limit_req zone=api burst=200 nodelay;
    
    # Bağlantı sınırlaması
    limit_conn_zone $binary_remote_addr zone=addr:10m;
    limit_conn addr 10;
    
    # IP beyaz listeleme
    allow 10.0.0.0/8;      # İç ağ
    allow 172.16.0.0/12;   # VPC
    deny all;
    
    location / {
        # JWT token kontrolü
        auth_jwt "Kısıtlı API";
        auth_jwt_key_file /etc/nginx/jwt_key.json;
        
        proxy_pass http://backend_service;
        
        # İstemci sertifikası bilgilerini iletme
        proxy_set_header X-Client-DN $ssl_client_s_dn;
        proxy_set_header X-Client-Verify $ssl_client_verify;
    }
}

Service Mesh, mTLS için otomatik olarak sertifikaları oluşturup döndürerek, erişim politikalarını uygulayarak ve hizmetler arasındaki tüm trafiği şifreleyerek güvenlik ayarlarını önemli ölçüde basitleştirir. Örneğin, Istio'da "payment" hizmetinin yalnızca "order" hizmetinden gelen istekleri kabul edebileceği bir politika belirlenebilir ve bu, hizmetlerin kodunda değişiklik yapmadan proxy düzeyinde otomatik olarak uygulanır.

Üretim için önemli: Hizmetler arası iletişim için her zaman mTLS kullanın, hatta aynı özel ağda bulunsalar bile. Bu, man-in-the-middle türü saldırılara karşı koruma sağlar ve hizmetler düzeyinde kimlik doğrulama sağlar, yalnızca ağ düzeyinde değil.

Proxy trafiğinin izlenmesi ve günlüğe kaydedilmesi

Proxy sunucuları, mikroservis sistemindeki tüm trafiği merkezi olarak izlemek için benzersiz bir fırsat sunar. Tüm trafik, proxy üzerinden geçer (API Gateway aracılığıyla dış ve Service Mesh aracılığıyla iç), bu da her hizmeti izlemek için ek bir araç eklemeden sistemin çalışmasını tam olarak görmenizi sağlar.

Proxy düzeyinde izleme için ana metrikler:

  • Gecikme — her aşamada isteğin işlenme süresi: proxy, hizmet, dış API'ler
  • Yüksek Hız — saniyede istek sayısı, iletilen veri hacmi
  • Hata Oranı — hata yüzdesi (4xx, 5xx), hata türleri, sorunlu endpoint'ler
  • Bağlantı Metrikleri — aktif bağlantı sayısı, bağlantı havuzu kullanımı
  • Circuit Breaker Durumu — her hizmet için devre kesicilerin durumu
  • SSL/TLS Metrikleri — sertifikaların durumu, protokol sürümleri, handshake hataları
# NGINX yapılandırması metrikleri Prometheus'a aktarmak için
server {
    listen 9113;
    location /metrics {
        stub_status;
        access_log off;
        allow 10.0.0.0/8;  # Sadece Prometheus sunucusu için
        deny all;
    }
}

# Yapılandırılmış günlüğe kaydetme için JSON formatında günlüğe kaydetme
log_format json_combined escape=json
  '{'
    '"time_local":"$time_local",'
    '"remote_addr":"$remote_addr",'
    '"request":"$request",'
    '"status": "$status",'
    '"body_bytes_sent":"$body_bytes_sent",'
    '"request_time":"$request_time",'
    '"upstream_response_time":"$upstream_response_time",'
    '"upstream_addr":"$upstream_addr",'
    '"http_referrer":"$http_referer",'
    '"http_user_agent":"$http_user_agent",'
    '"http_x_forwarded_for":"$http_x_forwarded_for"'
  '}';

access_log /var/log/nginx/access.log json_combined;

Dağıtık İzleme, proxy üzerinden izleme için en güçlü olanaklardan biridir. Her isteğe benzersiz bir izleme kimliği atanır, bu proxy başlıklara ekler ve hizmetler zinciri boyunca iletir. İzleme sistemleri (Jaeger, Zipkin), tüm proxy'lerden bilgi toplar ve sistemdeki isteğin tam yolunu oluşturur, her hizmette ne kadar zaman geçirdiğini gösterir.

// Node.js: proxy middleware'da izleme ekleme
const express = require('express');
const { v4: uuidv4 } = require('uuid');
const axios = require('axios');

const app = express();

// İzleme kimliği eklemek için middleware
app.use((req, res, next) => {
  // Başlıktan izleme kimliğini al veya yeni oluştur
  const traceId = req.headers['x-trace-id'] || uuidv4();
  const spanId = uuidv4();
  
  // Devam ettirmek için başlıklara ekle
  req.traceId = traceId;
  req.spanId = spanId;
  res.setHeader('x-trace-id', traceId);
  
  // İşlemenin başlangıcını günlüğe kaydet
  const startTime = Date.now();
  
  res.on('finish', () => {
    const duration = Date.now() - startTime;
    
    // Analiz için yapılandırılmış günlüğe kaydet
    console.log(JSON.stringify({
      timestamp: new Date().toISOString(),
      traceId: traceId,
      spanId: spanId,
      method: req.method,
      path: req.path,
      status: res.statusCode,
      duration: duration,
      userAgent: req.headers['user-agent'],
      ip: req.ip
    }));
  });
  
  next();
});

// İzleme başlıklarını ileten proxy endpoint'i
app.all('/api/*', async (req, res) => {
  const targetService = determineTargetService(req.path);
  
  try {
    const response = await axios({
      method: req.method,
      url: `http://${targetService}${req.path}`,
      data: req.body,
      headers: {
        ...req.headers,
        'x-trace-id': req.traceId,
        'x-parent-span-id': req.spanId,
        'x-span-id': uuidv4()  // Aşağı akış isteği için yeni span
      }
    });
    
    res.status(response.status).json(response.data);
  } catch (error) {
    console.error(JSON.stringify({
      traceId: req.traceId,
      error: error.message,
      service: targetService
    }));
    res.status(500).json({ error: 'Hizmet mevcut değil' });
  }
});

function determineTargetService(path) {
  if (path.startsWith('/api/users')) return 'user-service:8080';
  if (path.startsWith('/api/orders')) return 'order-service:8080';
  return 'default-service:8080';
}

app.listen(3000);

Proxy metriklerine dayalı uyarılar, sorunları hızlı bir şekilde tespit etmeyi sağlar. Örneğin, gecikmenin ani artışı (bir hizmetin kötüleşiyor olabileceği), hata oranının belirli bir eşiğin üzerine çıkması (kod veya bağımlılıklarda sorunlar), trafik desenlerindeki değişiklikler (olası DDoS saldırısı veya virüs yükü) için uyarılar ayarlanabilir.

Python ve Node.js ile uygulama örnekleri

Farklı senaryolar için proxy entegrasyonunun Python ve Node.js'de pratik örneklerini inceleyelim: iç iletişim, dış API'lerle çalışma, yük dengeleme.

Python: Dış API'ler için proxy ile hizmet

from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
import httpx
import asyncio
from typing import List, Optional
import logging

app = FastAPI()
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

class ProxyConfig(BaseModel):
    url: str
    max_requests_per_minute: int = 60

class ProxyPool:
    def __init__(self, proxies: List[ProxyConfig]):
        self.proxies = proxies
        self.current_index = 0
        self.request_counts = {p.url: 0 for p in proxies}
        self.reset_time = asyncio.get_event_loop().time() + 60
    
    async def get_next_proxy(self) -> str:
        # Her dakika sayaçları sıfırla
        current_time = asyncio.get_event_loop().time()
        if current_time >= self.reset_time:
            self.request_counts = {p.url: 0 for p in self.proxies}
            self.reset_time = current_time + 60
        
        # Kullanılabilir istekleri olan proxy'yi bul
        for _ in range(len(self.proxies)):
            proxy = self.proxies[self.current_index]
            self.current_index = (self.current_index + 1) % len(self.proxies)
            
            if self.request_counts[proxy.url] < proxy.max_requests_per_minute:
                self.request_counts[proxy.url] += 1
                return proxy.url
        
        # Tüm proxy'ler limitini doldurmuş
        raise HTTPException(status_code=429, detail="Tüm proxy'ler rate limitlendi")

# Proxy havuzunu başlat
proxy_pool = ProxyPool([
    ProxyConfig(url="http://user:pass@proxy1.example.com:8080", max_requests_per_minute=100),
    ProxyConfig(url="http://user:pass@proxy2.example.com:8080", max_requests_per_minute=100),
    ProxyConfig(url="http://user:pass@proxy3.example.com:8080", max_requests_per_minute=100)
])

class ExternalAPIClient:
    def __init__(self, proxy_pool: ProxyPool):
        self.proxy_pool = proxy_pool
    
    async def fetch_data(self, endpoint: str, params: dict = None) -> dict:
        proxy_url = await self.proxy_pool.get_next_proxy()
        
        async with httpx.AsyncClient(proxies={"http://": proxy_url, "https://": proxy_url}) as client:
            try:
                response = await client.get(
                    endpoint,
                    params=params,
                    timeout=10.0,
                    headers={"User-Agent": "MyMicroservice/1.0"}
                )
                response.raise_for_status()
                
                logger.info(f"{proxy_url} üzerinden {endpoint} adresinden başarıyla alındı")
                return response.json()
            
            except httpx.HTTPStatusError as e:
                logger.error(f"{endpoint} adresinden HTTP hatası {e.response.status_code}")
                raise HTTPException(status_code=e.response.status_code, detail=str(e))
            
            except httpx.RequestError as e:
                logger.error(f"{endpoint} adresine istek hatası: {e}")
                raise HTTPException(status_code=503, detail="Dış API mevcut değil")

api_client = ExternalAPIClient(proxy_pool)

@app.get("/data/{resource_id}")
async def get_external_data(resource_id: str):
    """Dış API'den verileri proxy üzerinden alan endpoint"""
    external_endpoint = f"https://api.external-service.com/v1/resources/{resource_id}"
    
    try:
        data = await api_client.fetch_data(external_endpoint)
        return {"status": "success", "data": data}
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Beklenmedik hata: {e}")
        raise HTTPException(status_code=500, detail="İç sunucu hatası")

@app.get("/health")
async def health_check():
    return {"status": "healthy", "service": "external-api-proxy"}

# Başlatma: uvicorn main:app --host 0.0.0.0 --port 8000

Node.js: Yük dengelemesi ile API Gateway

const express = require('express');
const axios = require('axios');
const rateLimit = require('express-rate-limit');

const app = express();
app.use(express.json());

// Mikroservislerin yapılandırması
const services = {
  users: [
    { url: 'http://user-service-1:8001', healthy: true, activeConnections: 0 },
    { url: 'http://user-service-2:8001', healthy: true, activeConnections: 0 },
    // Diğer kullanıcı hizmetleri...
  ],
  orders: [
    { url: 'http://order-service-1:8002', healthy: true, activeConnections: 0 },
    { url: 'http://order-service-2:8002', healthy: true, activeConnections: 0 },
    // Diğer sipariş hizmetleri...
  ]
};

// Yük dengeleme ve istek yönlendirme
app.use('/api/users', async (req, res) => {
  // Yük dengeleme mantığı
  const service = services.users.find(s => s.healthy);
  if (!service) {
    return res.status(503).json({ error: 'Tüm kullanıcı hizmetleri mevcut değil' });
  }
  try {
    const response = await axios({
      method: req.method,
      url: `${service.url}${req.path}`,
      data: req.body,
      headers: req.headers
    });
    res.status(response.status).json(response.data);
  } catch (error) {
    res.status(500).json({ error: 'Hizmet mevcut değil' });
  }
});

// Diğer API endpoint'leri...

app.listen(3000, () => {
  console.log('API Gateway 3000 portunda çalışıyor');
});
```