Spring Cloud Gateway
Mikroservis mimarisinde düzinelerce servis vardır ve her birinin farklı adresi/portu bulunur. İstemcilerin (web, mobil) tüm bu adresleri bilmesi ve her servisle ayrı ayrı iletişim kurması pratik değildir. API Gateway, istemci ile mikroservisler arasında tek bir giriş noktası (single entry point) sağlar. Spring Cloud Gateway, Spring ekosisteminin resmi API Gateway çözümüdür.
API Gateway vs Reverse Proxy
İkisi benzer görünse de kapsamları farklıdır:
Reverse Proxy (Nginx, HAProxy): Temel yönlendirme, SSL termination, static file serving, basit load balancing. Uygulama mantığı yoktur.
API Gateway: Reverse proxy'nin tüm yeteneklerini içerir + authentication/authorization, request/response transformation, rate limiting, circuit breaker, logging, monitoring, API composition. İş mantığı katmanı içerir.
Spring Cloud Gateway Kurulumu
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>Önemli: Spring Cloud Gateway, Spring WebFlux (reactive) üzerine kuruludur. spring-boot-starter-web (servlet-based) ile birlikte kullanılamaz.
Route Kavramı
Gateway'in temel yapı taşı route'tur. Her route üç bileşenden oluşur:
Predicate — İsteğin bu route ile eşleşip eşleşmediğini belirler.
Filter — İstek veya yanıtı dönüştürür.
URI — İsteğin yönlendirileceği hedef.
YAML ile Route Tanımlama
spring:
cloud:
gateway:
routes:
- id: user-service
uri: lb://user-service # lb = load balanced
predicates:
- Path=/api/users/**
filters:
- StripPrefix=0
- id: order-service
uri: lb://order-service
predicates:
- Path=/api/orders/**
filters:
- StripPrefix=0
- id: product-service
uri: lb://product-service
predicates:
- Path=/api/products/**
- Method=GET,POST
filters:
- AddRequestHeader=X-Gateway, true
- AddResponseHeader=X-Response-Time, processedlb:// prefix'i Eureka'dan servis adresini çözümlemek için Spring Cloud LoadBalancer'ı kullanır.
Java DSL ile Route Tanımlama
@Configuration
public class GatewayConfig {
@Bean
public RouteLocator customRoutes(RouteLocatorBuilder builder) {
return builder.routes()
.route("user-service", r -> r
.path("/api/users/**")
.filters(f -> f
.stripPrefix(0)
.addRequestHeader("X-Source", "gateway")
.retry(config -> config
.setRetries(3)
.setStatuses(HttpStatus.SERVICE_UNAVAILABLE)))
.uri("lb://user-service"))
.route("order-service", r -> r
.path("/api/orders/**")
.and()
.method(HttpMethod.GET, HttpMethod.POST)
.filters(f -> f
.circuitBreaker(config -> config
.setName("orderCB")
.setFallbackUri("forward:/fallback/orders")))
.uri("lb://order-service"))
.build();
}
}Route Predicates (Eşleştirme Kuralları)
Gateway zengin bir predicate seti sunar:
predicates:
- Path=/api/users/** # URL path eşleştirme
- Method=GET,POST # HTTP metot filtresi
- Header=X-Request-Id, \d+ # Header regex ile eşleştirme
- Query=category # Query parameter varlığı
- Query=category, electronics # Query parameter değeri
- After=2024-01-01T00:00:00+03:00 # Belirli tarihten sonra
- Before=2025-12-31T23:59:59+03:00 # Belirli tarihten önce
- Between=2024-01-01T00:00:00+03:00, 2024-12-31T23:59:59+03:00
- Cookie=session, abc.* # Cookie eşleştirme
- RemoteAddr=192.168.1.0/24 # IP adresi filtresi
- Weight=group1, 8 # Ağırlıklı yönlendirmeGateway Filters
Pre-filters — İstek servise ulaşmadan önce çalışır:
filters:
- AddRequestHeader=X-Request-Source, gateway
- RemoveRequestHeader=Cookie
- SetPath=/internal{path}
- StripPrefix=1 # /api/users/42 → /users/42
- PrefixPath=/v1 # /users/42 → /v1/users/42
- RequestSize=5000000 # max 5MB requestPost-filters — Yanıt istemciye dönmeden önce çalışır:
filters:
- AddResponseHeader=X-Powered-By, Spring Gateway
- RemoveResponseHeader=Server
- SetStatus=200Global Filter (Tüm Route'lara Uygulanan)
@Component
public class LoggingGlobalFilter implements GlobalFilter, Ordered {
private static final Logger log =
LoggerFactory.getLogger(LoggingGlobalFilter.class);
@Override
public Mono<Void> filter(ServerWebExchange exchange,
GatewayFilterChain chain) {
String path = exchange.getRequest().getPath().toString();
String method = exchange.getRequest().getMethod().name();
long start = System.currentTimeMillis();
log.info(">>> {} {}", method, path);
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
long duration = System.currentTimeMillis() - start;
int status = exchange.getResponse().getStatusCode() != null
? exchange.getResponse().getStatusCode().value() : 0;
log.info("<<< {} {} → {} ({}ms)",
method, path, status, duration);
}));
}
@Override
public int getOrder() {
return -1; // düşük sıra = önce çalışır
}
}Rate Limiting ve Circuit Breaker Entegrasyonu
Gateway, route seviyesinde RequestRateLimiter filtresi ile rate limiting ve CircuitBreaker filtresi ile circuit breaker entegrasyonu sunar. Rate limiting için Redis backend, circuit breaker için Resilience4j kullanılır:
filters:
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 10
redis-rate-limiter.burstCapacity: 20
key-resolver: "#{@userKeyResolver}"
- name: CircuitBreaker
args:
name: orderServiceCB
fallbackUri: forward:/fallback/orders@RestController
public class FallbackController {
@GetMapping("/fallback/orders")
public ResponseEntity<Map<String, String>> ordersFallback() {
return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE)
.body(Map.of("message", "Order service temporarily unavailable"));
}
}Spring Cloud Gateway, mikroservis mimarinizin ön kapısıdır. Tüm cross-cutting concern'leri merkezi olarak yönetir ve servislerinizi dış dünyadan soyutlar.
AI Asistan
Sorularını yanıtlamaya hazır