Üç servisle başlayan bir projede işler basittir: mobil uygulama api.firmaniz.com:8001'e, panel api.firmaniz.com:8002'ye gider, sen de her birine ayrı ayrı TLS sertifikası ve token doğrulaması koyarsın. Sekizinci servise geldiğinde ise aynı JWT doğrulama kodunu sekiz farklı yerde güncellemeye çalıştığını fark edersin. İşte API Gateway tam olarak bu noktada devreye giren şeydir: istemci ile arka uç servisleri arasına konumlanan, tüm trafiğin geçtiği tek bir giriş noktası.
Bu rehberde API Gateway'in ne olduğunu, ters proxy'den (reverse proxy) hangi noktada ayrıldığını, hangi görevleri üstlenmesi gerektiğini ve gerçekten hangilerini üstlenmemesi gerektiğini anlatacağım. Nginx ile sıfırdan çalışan bir gateway kuracağız, kimlik doğrulama ve hız sınırlama katmanlarını ekleyeceğiz, Kong ve Traefik gibi hazır ürünlerle ne zaman uğraşmaya değdiğine bakacağız. Sonunda da bu mimaride en sık düşülen tuzakları — özellikle gateway'i tek arıza noktasına çevirme klasiğini — tek tek konuşacağız.
API Gateway Tam Olarak Neyi Çözer#
Bir gateway'in çözdüğü asıl problem teknik değil, örgütsel bir problemdir: kesişen ilgi alanlarının (cross-cutting concerns) tekrarlanması. Kimlik doğrulama, hız sınırlama, CORS başlıkları, istek kimliği üretimi, erişim logu, TLS sonlandırma, gzip sıkıştırma — bunların hepsi her servisin ihtiyaç duyduğu ama hiçbirinin asıl işi olmayan görevlerdir. Bu görevleri her serviste ayrı ayrı uygularsan, altı ay sonra elinde altı farklı sürümde altı farklı davranış olur. Birinde token süresi 24 saat, diğerinde 12 saattir; birinde rate limit IP başına, diğerinde kullanıcı başınadır. Gateway bu mantığı tek bir yere toplar.
İkinci çözdüğü problem ise istemciyi iç topolojiden yalıtmaktır. İstemci firmaniz.com/api/siparis adresini bilir; bu isteğin arka planda siparis-servisi:8003 mi yoksa yeni yazdığın siparis-v2:9010 mu tarafından karşılandığını bilmesi gerekmez. Servisleri bölebilir, birleştirebilir, taşıyabilir ya da farklı bir dile geçirebilirsin — istemcinin gördüğü URL değişmez. Bu yalıtım aynı zamanda bir güvenlik önlemidir: arka uç servisleri yalnızca iç ağda dinler, dışarıya açık tek port gateway'in portudur. Docker ağ yapılandırması yazısındaki iç ağ mantığı, gateway'li bir kurulumda tam olarak bu amaca hizmet eder.
Üçüncü olarak gateway, istemci başına farklı ihtiyaçları karşılamayı kolaylaştırır. Mobil uygulaman az veri isteyip pil harcamak istemez, yönetim paneli ise geniş nesneleri tek seferde çeker. Aynı arka uç servislerinin önüne iki farklı gateway rotası koyup her birine kendi yanıt biçimlendirmesini uygulayabilirsin — bu yaklaşıma literatürde "Backend for Frontend" (BFF) deniyor.
Ters Proxy ile API Gateway Arasındaki Fark#
Bu ikisi sık sık birbirine karıştırılır ve haklı bir sebebi vardır: her API Gateway aynı zamanda bir ters proxy'dir. Fark, sorumluluk kapsamındadır. Ters proxy ağ katmanında düşünür — "gelen isteği hangi arka uca yollayayım?" sorusunu cevaplar. API Gateway ise uygulama katmanında düşünür — "bu isteği yapan kim, bunu yapmaya hakkı var mı, bu ay kaç istek yaptı, yanıtı nasıl biçimlendireyim?" sorularını da cevaplar.
| Yetenek | Ters Proxy | API Gateway |
|---|---|---|
| Yol tabanlı yönlendirme | Var | Var |
| TLS sonlandırma | Var | Var |
| Yük dağıtımı | Var | Var |
| Kimlik doğrulama / yetkilendirme | Genelde yok | Temel görev |
| İstemci başına hız sınırlama | Sınırlı | Temel görev |
| API anahtarı / kota yönetimi | Yok | Var |
| İstek/yanıt dönüştürme | Yok | Var |
| Servis keşfi (service discovery) | Genelde yok | Sık sık var |
| Eklenti / plugin ekosistemi | Yok | Var |
Pratikte bu ayrım keskin değildir. Nginx bir ters proxy'dir ama auth_request, limit_req ve map direktifleriyle küçük ölçekte gayet iyi bir gateway olur. Kong da zaten Nginx üzerine kurulmuştur. Yani "gateway kuruyorum" demek çoğu zaman "ters proxy'me uygulama katmanı kuralları ekliyorum" demektir.
Nginx ile Çalışan Bir Gateway Kurmak#
En yalın haliyle başlayalım. Üç arka uç servisin var: kullanıcı servisi, sipariş servisi ve statik dosyaları veren bir servis. Hepsi Docker ağında kendi isimleriyle çalışıyor ve dışarıya port açmıyor. Gateway yalnızca 443'ü dinliyor.
# /etc/nginx/conf.d/gateway.conf
# Arka uç havuzları — servis adları Docker iç DNS'inden çözülür
upstream kullanici_servisi { server kullanici:8001; keepalive 16; }
upstream siparis_servisi { server siparis:8002; keepalive 16; }
# İstemci IP'si başına hız sınırlama bölgesi: saniyede 10 istek
limit_req_zone $binary_remote_addr zone=api_genel:10m rate=10r/s;
server {
listen 443 ssl http2;
server_name api.firmaniz.com;
ssl_certificate /etc/letsencrypt/live/api.firmaniz.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/api.firmaniz.com/privkey.pem;
# Her isteğe izlenebilir bir kimlik ver; loglarda ve arka uçta aynı değer görünür
add_header X-Request-Id $request_id always;
location /api/kullanici/ {
limit_req zone=api_genel burst=20 nodelay;
proxy_pass http://kullanici_servisi/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Request-Id $request_id;
proxy_http_version 1.1;
proxy_set_header Connection "";
}
location /api/siparis/ {
limit_req zone=api_genel burst=20 nodelay;
proxy_pass http://siparis_servisi/;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Request-Id $request_id;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_read_timeout 30s;
}
# Bilinmeyen yollar için sızıntı yapmayan tek tip cevap
location / { return 404 '{"error":"not_found"}'; default_type application/json; }
}
Burada gözden kaçan ama kritik iki ayrıntı var. Birincisi proxy_pass değerinin sonundaki eğik çizgi: proxy_pass http://kullanici_servisi/; yazdığında Nginx location ön ekini (/api/kullanici/) URL'den keser ve arka uca /profil olarak iletir. Eğik çizgiyi koymazsan arka uç /api/kullanici/profil görür. Bu tek karakter, "neden 404 alıyorum" sorusunun en yaygın cevabıdır. İkincisi keepalive ve proxy_http_version 1.1 ikilisidir: bunlar olmadan Nginx her istek için arka uca yeni bir TCP bağlantısı açar, yüksek trafikte binlerce TIME_WAIT soketi birikir.
Yapılandırmayı devreye almadan önce mutlaka söz dizimini sınayın:
# Söz dizimi ve dosya yolu kontrolü
sudo nginx -t
# Kesintisiz yeniden yükleme (açık bağlantılar korunur)
sudo nginx -s reload
# Yönlendirmenin doğru çalıştığını dışarıdan doğrula
curl -sS -o /dev/null -w '%{http_code} %{time_total}s\n' \
https://api.firmaniz.com/api/siparis/saglik
Kimlik Doğrulama Katmanını Gateway'e Taşımak#
Gateway'in en değerli görevi, kimlik doğrulamayı arka uçlardan almaktır. Nginx'te bunun standart yolu auth_request direktifidir: gelen isteği arka uca yollamadan önce küçük bir doğrulama servisine sorar, o servis 2xx dönerse istek devam eder, 401 dönerse istemciye reddedilir.
location /api/ {
# Önce doğrula: /_dogrula 200 dönmezse istek arka uca hiç gitmez
auth_request /_dogrula;
# Doğrulama servisinin döndüğü kullanıcı kimliğini arka uca aktar
auth_request_set $kullanici_id $upstream_http_x_kullanici_id;
proxy_set_header X-Kullanici-Id $kullanici_id;
proxy_pass http://siparis_servisi/;
}
location = /_dogrula {
internal; # dışarıdan çağrılamaz
proxy_pass http://auth:9000/dogrula;
proxy_pass_request_body off; # gövdeyi taşımaya gerek yok
proxy_set_header Content-Length "";
proxy_set_header X-Original-URI $request_uri;
}
Bu yapının güzelliği, arka ucun artık JWT kütüphanesi taşımak zorunda olmamasıdır: X-Kullanici-Id başlığı varsa istek doğrulanmıştır, yoksa gateway zaten geçirmemiştir. Ancak burada hayati bir kural vardır: arka uç servisleri dış dünyaya asla doğrudan açılmamalıdır. Aksi halde saldırgan gateway'i atlayıp servise doğrudan X-Kullanici-Id: 1 başlığı göndererek yönetici olur. Servisleri iç ağa kapatmak bu mimaride bir tercih değil, zorunluluktur.
Hız sınırlama tarafında ise IP başına sınır tek başına yetmez; kimliği doğrulanmış kullanıcı başına sınır koymak istersin. Nginx'te bunu map ile kurabilirsin:
# Kullanıcı kimliği varsa ona göre, yoksa IP'ye göre kova seç
map $http_x_kullanici_id $limit_anahtari {
default $binary_remote_addr;
~.+ $http_x_kullanici_id;
}
limit_req_zone $limit_anahtari zone=kullanici_bazli:20m rate=30r/s;
Hazır Gateway Ürünleri: Kong, Traefik, Envoy#
Nginx yapılandırmasını elle yazmak belli bir ölçeğe kadar en hızlı yoldur. Ama servis sayısı arttıkça, rotaların çalışma anında (yeniden yükleme olmadan) değişmesi, API anahtarı yönetimi ve eklenti ekosistemi gibi ihtiyaçlar doğar. O noktada hazır ürünlere bakmak mantıklı olur.
| Ürün | Öne çıkan yanı | Yapılandırma biçimi | Ne zaman tercih edilir |
|---|---|---|---|
| Nginx | Hafif, öngörülebilir, her yerde var | Statik dosya + reload | Servis sayısı azsa, ekip küçükse |
| Traefik | Docker/Kubernetes etiketlerinden rotayı kendi bulur | Etiket / CRD | Konteyner yoğun, sık değişen ortam |
| Kong | Eklenti ekosistemi, API anahtarı ve kota yönetimi | Admin API / declarative | Dışa açık, ücretli API sunuyorsan |
| Envoy | Gelişmiş trafik yönetimi, gözlemlenebilirlik | xDS / YAML | Service mesh'e geçiş düşünülüyorsa |
| HAProxy | Çok yüksek bağlantı sayısında kararlılık | Statik dosya | L4 ağırlıklı, yoğun TCP trafiği |
Traefik'in en sevdiğim yanı, Docker etiketlerinden rota üretmesidir; docker-compose.yml içine birkaç etiket eklediğinde yeni servis kendiliğinden yayına girer. Docker Compose kullanımı rehberindeki çok servisli yapıya bir gateway eklemek istiyorsan başlangıç için en az sürtünmeli yol budur. Kong ise API'ni dış geliştiricilere açıyorsan, anahtar üretimi ve kota takibini kendin yazmaktan kurtarır.
Sık Yapılan Hatalar ve Tuzaklar#
Gateway'i tek arıza noktası yapmak. Tüm trafik buradan geçtiğine göre, gateway düşerse her şey düşer. Çözüm en az iki gateway örneği çalıştırmak ve önlerine DNS round-robin ya da bir L4 yük dengeleyici koymaktır. Gateway'in kendisi durum tutmadığı (stateless) sürece bunu yapmak kolaydır — bu yüzden oturum verisini gateway belleğinde tutma, Redis gibi paylaşılan bir yerde tut.
İş mantığını gateway'e sızdırmak. Gateway bir yönlendirme ve politika katmanıdır; "sipariş tutarı 500 TL'yi geçerse indirim uygula" gibi bir kural oraya girmemelidir. Bir kez girdiğinde, üç ay sonra gateway yapılandırması kimsenin okuyamadığı, test edilemeyen bir iş mantığı yığınına döner. Kural şudur: gateway'in bildiği tek şey isteğin kim tarafından yapıldığı ve nereye gideceğidir; ne anlama geldiği arka ucun işidir.
Zaman aşımı değerlerini varsayılanda bırakmak. Nginx'in varsayılan proxy_read_timeout değeri 60 saniyedir. Arka uç servisin takılırsa, gateway'in tüm işçi bağlantıları o bekleyen isteklerde tükenir ve sağlıklı servislere giden trafik de durur. Her rota için gerçekçi bir zaman aşımı belirle; 30 saniyeden uzun süren bir API isteği zaten kuyruğa alınması gereken bir iştir. Bu ayrımı cron mu job queue mu yazısında ayrıntılı konuşuyorum.
X-Forwarded-For başlığına körü körüne güvenmek. Arka uç servisin istemci IP'sini bu başlıktan okuyorsa ve gateway bunu üzerine yazmıyorsa, saldırgan kendi isteğine sahte bir başlık ekleyip IP tabanlı hız sınırını ve erişim listelerini atlar. Gateway'de proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; kullan ve arka uçta yalnızca gateway'in eklediği son değeri güvenilir say.
Hata gövdelerini olduğu gibi geçirmek. Arka uç 500 dönerken yığın izini (stack trace) gövdede yolluyorsa, gateway bunu istemciye aynen iletir ve iç dosya yollarını, kütüphane sürümlerini dışarı sızdırırsın. proxy_intercept_errors on; ile 5xx yanıtlarını yakalayıp kendi tek tip JSON hatanı dönmek doğru davranıştır. Uygulama katmanı saldırılarına karşı ek bir filtre istiyorsan WAF katmanı gateway'in tam önünde durmalıdır.
Gözlemlenebilirlik: Gateway'in En Az Bilinen Süper Gücü#
Tüm trafik tek noktadan geçtiği için gateway, sisteminin en iyi ölçüm noktasıdır. Buradan alacağın üç metrik arka uçlara hiç dokunmadan sağlık tablosunu verir: gecikme, rota başına hata oranı ve arka uç yanıt süresi. Nginx'te bunu log biçimiyle elde edersin:
log_format gateway_json escape=json
'{"ts":"$time_iso8601","id":"$request_id","yol":"$uri",'
'"durum":$status,"sure":$request_time,"arkauc_sure":"$upstream_response_time",'
'"arkauc":"$upstream_addr","yontem":"$request_method"}';
access_log /var/log/nginx/gateway.json gateway_json;
$request_time ile $upstream_response_time arasındaki farkı izlemek özellikle öğreticidir: ikisi birbirine yakınsa darboğaz arka uçtadır, $request_time çok daha büyükse sorun ağda ya da istemcinin yavaş veri almasındadır. Ürettiğin JSON logları hızlıca incelemek için JSON formatlayıcı aracını kullanabilirsin. Ayrıca her isteğe verdiğin X-Request-Id değerini arka uç loglarında da yazdırırsan, tek bir kullanıcı şikâyetini uçtan uca izlemek dakikalar yerine saniyeler alır.
Sıkça Sorulan Sorular#
API Gateway ile load balancer aynı şey mi#
Hayır, ama işlevleri kısmen örtüşür. Yük dengeleyici temel olarak gelen bağlantıları sağlıklı arka uçlar arasında dağıtır ve genellikle ağ katmanında (L4) ya da basit HTTP kurallarıyla (L7) çalışır. API Gateway ise bunun üstüne kimlik doğrulama, hız sınırlama, kota takibi ve istek dönüştürme gibi uygulama katmanı görevleri ekler. Pratikte çoğu gateway zaten içinde bir yük dengeleyici barındırır, tersi doğru değildir.
Küçük bir projede API Gateway kurmaya değer mi#
Tek bir uygulama sunucun varsa ve dışa açık tek bir API'n varsa gateway kurmak fazladan karmaşıklıktır; Nginx'i düz ters proxy olarak kullanman yeterlidir. Gateway'in kazanç sağlamaya başladığı eşik genellikle üç-dört bağımsız servis ya da birden fazla istemci türüdür. Yine de TLS sonlandırma ve hız sınırlamayı en baştan Nginx'te toplamak, ileride gateway'e geçişi neredeyse ücretsiz hale getirir.
API Gateway performansı yavaşlatır mı#
Ek bir ağ atlaması eklediği için teorik olarak evet, ama pratikte bu maliyet çok küçüktür — aynı veri merkezinde iyi yapılandırılmış bir Nginx katmanı istek başına genellikle birkaç milisaniye ekler. Bu maliyeti asıl büyüten şeyler kalıcı bağlantı (keepalive) kullanmamak, her istekte harici bir doğrulama servisine senkron gitmek ve gereksiz gövde tamponlamasıdır. Keepalive'ı açar ve doğrulama sonucunu kısa süreli önbelleğe alırsan fark ölçülemez seviyeye iner.
Gateway'de mi yoksa serviste mi kimlik doğrulaması yapmalıyım#
En sağlıklı model ikisini birden yapmaktır: gateway kaba geçiş kontrolünü üstlenir (token geçerli mi, süresi dolmuş mu, kullanıcı kim), servis ise ince yetkilendirmeyi yapar (bu kullanıcı bu siparişi görebilir mi). Tüm yetkilendirmeyi gateway'e yıkarsan, gateway iş mantığını bilmek zorunda kalır. Tümünü servise bırakırsan, doğrulama kodu her serviste tekrarlanır ve zamanla birbirinden ayrışır.
Rate limit değerini neye göre belirlemeliyim#
Sezgiyle değil, ölçümle. Mevcut erişim loglarından kullanıcı başına saniyelik istek dağılımını çıkar, 99. yüzdelik dilimi (p99) bul ve sınırı bunun iki-üç katına koy. Böylece normal kullanıcıların hiçbiri sınıra çarpmaz, kötüye kullanım ise anında yakalanır. Sınırı devreye alırken önce yalnızca loglama yapıp kaç isteğin engellenecek olduğunu bir hafta izlemek, doğrudan engellemeye geçmekten çok daha güvenlidir.
Gateway'i konteynerde mi yoksa doğrudan sunucuda mı çalıştırmalıyım#
İkisi de geçerli. Arka uçların zaten konteynerde çalışıyorsa gateway'i de aynı ağa koymak servis adlarıyla çözümlemeyi kolaylaştırır ve yapılandırmayı sürüm kontrolünde tutmanı sağlar. Doğrudan sunucuda çalıştırmanın avantajı ise ağ katmanının bir kat daha az olması ve TLS sertifikası yenileme gibi işlerin sistemin standart araçlarıyla yürümesidir. Trafik çok yüksekse konteyner ağ sürücüsünün ek yükünü ölçmeden karar verme.
Gateway çökerse ne olur, nasıl hazırlıklı olurum#
Tek örnek çalıştırıyorsan tüm API'n erişilemez olur — bu yüzden en az iki örnek ve önlerinde bir dağıtım katmanı şarttır. Gateway'i durumsuz tuttuğun sürece ikinci örneği eklemek yalnızca aynı yapılandırmayı kopyalamaktan ibarettir. Ayrıca gateway'in kendi sağlık kontrolü uç noktasını dışarıdan izle; sağlık kontrolü ve otomatik yeniden başlatma kurgusunu uygulama sağlık kontrolü yazısında adım adım anlatıyorum.
Kapanış#
API Gateway, sihirli bir bileşen değil; tekrar eden ilgi alanlarını tek yere toplayan disiplinli bir katmandır. Aklında kalması gereken dört alışkanlık şudur: arka uç servislerini asla dışa açma, kimlik doğrulamayı gateway'de yap ama iş mantığını asla oraya taşıma, her rota için gerçekçi bir zaman aşımı belirle ve gateway'i en baştan iki örnek çalışacak biçimde durumsuz kur. Bir de her isteğe verdiğin X-Request-Id alışkanlığını atlama — ileride en çok teşekkür edeceğin şey o olacak.
Bu mimariyi kendi altyapında kurmak istiyorsan tam root erişimli VDS ya da esnek ölçeklenen bulut sunucu paketlerimiz gateway ve arka uçları aynı iç ağda çalıştırmak için yeterli alanı verir. Gateway'in önüne saldırı filtresi koymak istersen DDoS koruma ve WAF hizmetlerimiz uygulama katmanına ulaşmadan zararlı trafiği eler; kurulum ve bakım kısmını hiç üstlenmek istemiyorsan sunucu yönetimi ekibimiz yapılandırmayı sizin yerinize kurup izler.