Dlaczego potrzebujesz API Gateway?
W architekturze mikrousług klienci muszą komunikować się z wieloma niezależnymi serwisami. Bez API Gateway każdy klient musiałby znać adresy wszystkich mikrousług, obsługiwać autoryzację osobno dla każdego serwisu i radzić sobie z różnymi protokołami. API Gateway rozwiązuje te problemy, działając jako pojedynczy punkt wejścia do całego systemu.
Co się nauczysz:
- Czym jest Spring Cloud Gateway i jak się różni od Zuul
- Jak skonfigurować podstawowy routing
- Jak używać predykatów i filtrów
- Jak implementować load balancing
- Jak dodać monitoring i logowanie
- Jak zabezpieczyć API Gateway
Spring Cloud Gateway vs Netflix Zuul
Spring Cloud Gateway to następca Netflix Zuul w ekosystemie Spring Cloud. Podczas gdy Zuul 1.x jest oparty na blocking I/O, Gateway wykorzystuje reactive programming model z Spring WebFlux.
Aspekt | Netflix Zuul 1.x | Spring Cloud Gateway |
---|---|---|
Model programowania | Blocking (Servlet API) | Reactive (WebFlux) |
Wydajność | Ograniczona przez thread pool | Wyższa – non-blocking I/O |
Konfiguracja | Java Config + Properties | Fluent API + YAML |
Ekosystem | Netflix OSS | Spring Cloud native |
Przyszłość | Maintenance mode | Aktywny rozwój |
Konfiguracja projektu
Aby rozpocząć pracę ze Spring Cloud Gateway, dodaj odpowiednie zależności do pom.xml:
<dependencies> <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> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Finchley.RC1</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
Podstawowa konfiguracja routingu
Routing w Spring Cloud Gateway konfiguruje się przez application.yml. Każda reguła routingu składa się z trzech elementów: predicate, filter i URI docelowego.
spring: cloud: gateway: routes: - id: user-service uri: http://localhost:8081 predicates: - Path=/api/users/** filters: - StripPrefix=2 - id: order-service uri: http://localhost:8082 predicates: - Path=/api/orders/** - Method=GET,POST filters: - AddRequestHeader=X-Request-Source, gateway - id: payment-service uri: lb://payment-service predicates: - Path=/api/payments/** filters: - CircuitBreaker=paymentCircuitBreaker
Predykaty (Predicates)
Spring Cloud Gateway oferuje bogaty zestaw wbudowanych predykatów do dopasowywania żądań:
spring: cloud: gateway: routes: - id: advanced-routing uri: http://localhost:8083 predicates: # Ścieżka URL - Path=/api/v1/** # Metoda HTTP - Method=GET,POST # Nagłówek HTTP - Header=X-Request-Id, \d+ # Query parameter - Query=version, v1 # Czas - żądania między 9:00 a 17:00 - Between=9:00,17:00 # Host header - Host=api.example.com # Remote address - RemoteAddr=192.168.1.0/24
Filtry (Filters)
Filtry pozwalają na modyfikację żądań i odpowiedzi. Spring Cloud Gateway dostarcza wiele wbudowanych filtrów:
spring: cloud: gateway: routes: - id: filter-example uri: http://localhost:8084 predicates: - Path=/api/** filters: # Usuń prefiksy ze ścieżki - StripPrefix=1 # Dodaj nagłówek do żądania - AddRequestHeader=X-Gateway-Name, spring-cloud-gateway # Dodaj nagłówek do odpowiedzi - AddResponseHeader=X-Response-Time, ${T(java.time.Instant).now()} # Przepisz ścieżkę - RewritePath=/api/(?.*), /${segment} # Rate limiting - RequestRateLimiter=10,1,#{@userKeyResolver} # Retry mechanizm - Retry=3
Load Balancing z Service Discovery
Spring Cloud Gateway integruje się z Eureka Service Discovery, umożliwiając automatyczne load balancing:
spring: application: name: api-gateway cloud: gateway: discovery: locator: enabled: true lower-case-service-id: true routes: - id: user-service-lb uri: lb://user-service predicates: - Path=/users/** eureka: client: service-url: defaultZone: http://localhost:8761/eureka/ fetch-registry: true register-with-eureka: true
Własne filtry
Możesz tworzyć własne filtry implementując GatewayFilter lub GlobalFilter:
@Component public class LoggingGlobalFilter implements GlobalFilter, Ordered { private static final Logger logger = LoggerFactory.getLogger(LoggingGlobalFilter.class); @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { ServerHttpRequest request = exchange.getRequest(); logger.info("Request: {} {} from {}", request.getMethod(), request.getURI().getPath(), request.getRemoteAddress()); return chain.filter(exchange).then(Mono.fromRunnable(() -> { ServerHttpResponse response = exchange.getResponse(); logger.info("Response: {} for {}", response.getStatusCode(), request.getURI().getPath()); })); } @Override public int getOrder() { return -1; // Wykonuj jako pierwszy } }
Monitoring i Health Checks
Spring Cloud Gateway dostarcza actuator endpoints do monitorowania:
management: endpoints: web: exposure: include: health,info,metrics,gateway endpoint: gateway: enabled: true health: show-details: always spring: cloud: gateway: actuator: verbose: enabled: true
Dostępne endpoints:
- /actuator/gateway/routes – lista wszystkich routes
- /actuator/gateway/filters – dostępne filtry
- /actuator/gateway/refresh – odświeżenie konfiguracji routes
- /actuator/metrics – metryki wydajności
Circuit Breaker Pattern
Spring Cloud Gateway integruje się z Hystrix dla implementacji Circuit Breaker pattern:
spring: cloud: gateway: routes: - id: circuit-breaker-route uri: lb://unreliable-service predicates: - Path=/api/unreliable/** filters: - name: CircuitBreaker args: name: unreliableServiceCB fallbackUri: forward:/fallback/unreliable hystrix: command: unreliableServiceCB: execution: isolation: thread: timeoutInMilliseconds: 3000 circuitBreaker: requestVolumeThreshold: 10 errorThresholdPercentage: 50
@RestController public class FallbackController { @RequestMapping("/fallback/unreliable") public Mono<ResponseEntity<String>> fallback() { return Mono.just(ResponseEntity.ok() .body("{\"message\": \"Service temporarily unavailable\"}")); } }
Zabezpieczenia
Spring Cloud Gateway można zabezpieczyć używając Spring Security:
@EnableWebFluxSecurity @Configuration public class SecurityConfig { @Bean public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) { return http .authorizeExchange(exchanges -> exchanges .pathMatchers("/actuator/**").hasRole("ADMIN") .pathMatchers("/api/public/**").permitAll() .anyExchange().authenticated() ) .oauth2ResourceServer(oauth2 -> oauth2 .jwt(jwt -> jwt.jwtDecoder(jwtDecoder())) ) .csrf().disable() .build(); } @Bean public ReactiveJwtDecoder jwtDecoder() { return ReactiveJwtDecoders.fromIssuerLocation("https://your-auth-server.com"); } }
Performance i Best Practices
Kluczowe parametry konfiguracyjne dla wydajności:
spring: cloud: gateway: httpclient: connect-timeout: 1000 response-timeout: 5s pool: type: elastic max-connections: 1000 max-idle-time: 15s default-filters: - name: Retry args: retries: 3 statuses: BAD_GATEWAY,SERVICE_UNAVAILABLE backoff: firstBackoff: 10ms maxBackoff: 50ms
Tak, Spring Cloud Gateway to oficjalny następca Netflix Zuul w ekosystemie Spring Cloud. Oferuje lepszą wydajność dzięki reactive programming model i jest aktywnie rozwijany.
Nie, Spring Cloud Gateway jest oparty wyłącznie na reactive stack (WebFlux) i nie jest kompatybilny z tradycyjnym Spring MVC. Musisz używać reactive programming.
Włącz debug logi: logging.level.org.springframework.cloud.gateway=DEBUG i użyj actuator endpoint /actuator/gateway/routes do sprawdzenia aktywnych reguł.
Spring Cloud Gateway oferuje znacznie lepszą wydajność dzięki non-blocking I/O. W testach benchmarkowych obsługuje 2-3x więcej żądań na sekundę niż Zuul 1.x.
Tak, Spring Cloud Gateway natywnie obsługuje WebSocket proxying. Skonfiguruj route z predykatem – Path=/websocket/** i Gateway automatycznie obsłuży upgrade connection.
Użyj wbudowanego filtru: – DedupeResponseHeader=Access-Control-Allow-Origin lub skonfiguruj globalnie w spring.cloud.gateway.globalcors.
Tak, możesz programowo dodawać/usuwać routes używając RouteDefinitionRepository lub odświeżyć konfigurację przez actuator endpoint /refresh.
Przydatne zasoby:
- Spring Cloud Gateway Reference Documentation
- Spring Cloud Gateway GitHub Repository
- Spring Guide – Building a Gateway
- Netflix Tech Blog – Zuul 2 Architecture
🚀 Zadanie dla Ciebie
Stwórz API Gateway który routuje żądania do trzech mikrousług: user-service, order-service i notification-service. Dodaj rate limiting, basic authentication, circuit breaker dla notification-service oraz custom filter logujący wszystkie żądania. Przetestuj load balancing z wieloma instancjami jednego serwisu.
Czy planujesz migrację z Netflix Zuul na Spring Cloud Gateway? Jakie są twoje główne obawy dotyczące reactive programming w kontekście API Gateway? Podziel się swoimi doświadczeniami w komentarzach!