API Gateway in Microservices¶
Overview¶
This guide covers the API Gateway pattern in microservices architecture, including implementation approaches, best practices, and common patterns.
Prerequisites¶
- Basic understanding of microservices architecture
- Knowledge of Spring Cloud Gateway
- Familiarity with routing concepts
- Understanding of authentication and authorization
Learning Objectives¶
- Understand API Gateway pattern
- Learn different gateway implementations
- Master routing and filtering
- Implement security at gateway level
- Handle cross-cutting concerns
Table of Contents¶
API Gateway Pattern¶
Core Functions¶
- Routing
- Authentication
- SSL Termination
- Load Balancing
- Monitoring
- Rate Limiting
- Circuit Breaking
Implementation with Spring Cloud Gateway¶
Basic Configuration¶
spring:
cloud:
gateway:
routes:
- id: user_service
uri: lb://user-service
predicates:
- Path=/api/users/**
filters:
- StripPrefix=1
Java Configuration¶
@Configuration
public class GatewayConfig {
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
.route("user_service", r -> r
.path("/api/users/**")
.filters(f -> f.stripPrefix(1))
.uri("lb://user-service"))
.build();
}
}
Implementation Approaches¶
1. Spring Cloud Gateway¶
@SpringBootApplication
@EnableDiscoveryClient
public class ApiGatewayApplication {
public static void main(String[] args) {
SpringApplication.run(ApiGatewayApplication.class, args);
}
}
2. Custom Filters¶
@Component
public class CustomGatewayFilter implements GatewayFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
exchange.getRequest().mutate()
.header("X-Custom-Header", "custom-value");
return chain.filter(exchange);
}
}
3. Global Filters¶
@Component
public class LoggingGlobalFilter implements GlobalFilter {
private static final Logger log = LoggerFactory.getLogger(LoggingGlobalFilter.class);
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.info("Path requested: {}", exchange.getRequest().getPath());
return chain.filter(exchange);
}
}
Security¶
JWT Authentication¶
@Component
public class JwtAuthenticationFilter implements GatewayFilter {
private final JwtTokenProvider tokenProvider;
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String token = extractToken(exchange.getRequest());
if (tokenProvider.validateToken(token)) {
return chain.filter(exchange);
}
return Mono.error(new UnauthorizedException("Invalid token"));
}
}
Rate Limiting¶
@Configuration
public class RateLimitConfig {
@Bean
public KeyResolver userKeyResolver() {
return exchange -> Mono.just(
exchange.getRequest().getHeaders().getFirst("X-User-Id"));
}
}
CORS Configuration¶
@Configuration
public class CorsConfig {
@Bean
public CorsWebFilter corsWebFilter() {
CorsConfiguration config = new CorsConfiguration();
config.setAllowedOrigins(Arrays.asList("*"));
config.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE"));
config.setAllowedHeaders(Arrays.asList("*"));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return new CorsWebFilter(source);
}
}
Cross-Cutting Concerns¶
Circuit Breaker¶
spring:
cloud:
gateway:
routes:
- id: user_service
uri: lb://user-service
predicates:
- Path=/api/users/**
filters:
- name: CircuitBreaker
args:
name: userServiceBreaker
fallbackUri: forward:/fallback
Request/Response Transformation¶
@Component
public class TransformationFilter implements GatewayFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
return chain.filter(exchange.mutate()
.request(exchange.getRequest().mutate()
.header("X-Transformed", "true")
.build())
.build());
}
}
Logging and Monitoring¶
@Component
public class MetricsFilter implements GlobalFilter {
private final MeterRegistry meterRegistry;
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
long startTime = System.currentTimeMillis();
return chain.filter(exchange)
.doFinally(signalType -> {
long duration = System.currentTimeMillis() - startTime;
meterRegistry.timer("gateway.request.duration")
.record(duration, TimeUnit.MILLISECONDS);
});
}
}
Best Practices¶
- Implement proper security measures
- Use circuit breakers for downstream services
- Implement rate limiting
- Monitor gateway performance
- Handle errors gracefully
- Implement proper logging
- Use appropriate caching strategies
Common Pitfalls¶
- Insufficient security measures
- Poor error handling
- Missing rate limiting
- Inadequate monitoring
- Poor performance
- Improper routing configuration
Implementation Examples¶
Complete Gateway Configuration¶
spring:
cloud:
gateway:
routes:
- id: user_service
uri: lb://user-service
predicates:
- Path=/api/users/**
filters:
- StripPrefix=1
- name: CircuitBreaker
args:
name: userServiceBreaker
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 10
redis-rate-limiter.burstCapacity: 20
- id: order_service
uri: lb://order-service
predicates:
- Path=/api/orders/**
filters:
- StripPrefix=1
- name: Retry
args:
retries: 3
statuses: BAD_GATEWAY
Error Handling¶
@Component
public class GlobalErrorHandler implements ErrorWebExceptionHandler {
@Override
public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) {
exchange.getResponse().setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR);
return exchange.getResponse().writeWith(Mono.just(
exchange.getResponse().bufferFactory().wrap(
ex.getMessage().getBytes())));
}
}
Resources for Further Learning¶
- Spring Cloud Gateway Documentation
- Netflix Zuul Wiki
- Kong Gateway Documentation
- Azure API Management
Practice Exercises¶
- Set up Spring Cloud Gateway with service discovery
- Implement custom filters
- Configure rate limiting
- Set up circuit breakers
- Implement JWT authentication