API Gateway
API Gateway avec Spring Cloud Gateway
10-15 min
API Gateway avec Spring Cloud Gateway
L’API Gateway est un composant essentiel dans l’architecture microservices. Il sert de point d’entrée unique pour tous les clients et gère des aspects importants comme le routage, la sécurité, et la limitation de débit.
1. Configuration de l’API Gateway
1.1 Création du Projet Gateway
curl https://start.spring.io/starter.tgz \
-d dependencies=cloud-gateway,cloud-eureka-client \
-d groupId=com.example \
-d artifactId=api-gateway \
-d name=api-gateway \
-d description=API%20Gateway%20for%20Microservices \
-d packageName=com.example.gateway \
-d packaging=jar \
-d javaVersion=17 \
-d type=maven-project \
| tar -xzvf -
1.2 Configuration de Base
# application.yml
server:
port: 8080
spring:
application:
name: api-gateway
cloud:
gateway:
discovery:
locator:
enabled: true
lower-case-service-id: true
routes:
- id: product-service
uri: lb://product-service
predicates:
- Path=/api/products/**
filters:
- StripPrefix=1
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 10
redis-rate-limiter.burstCapacity: 20
key-resolver: "#{@ipKeyResolver}"
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
2. Routage et Filtres
2.1 Configuration des Routes
@Configuration
public class RouteConfig {
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
.route("order-service", r -> r
.path("/api/orders/**")
.filters(f -> f
.stripPrefix(1)
.addResponseHeader("X-Response-Time", String.valueOf(System.currentTimeMillis())))
.uri("lb://order-service"))
.route("payment-service", r -> r
.path("/api/payments/**")
.filters(f -> f
.stripPrefix(1)
.addResponseHeader("X-Response-Time", String.valueOf(System.currentTimeMillis())))
.uri("lb://payment-service"))
.build();
}
}
2.2 Filtres Personnalisés
@Component
public class LoggingFilter implements GlobalFilter, Ordered {
private static final Logger logger = LoggerFactory.getLogger(LoggingFilter.class);
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
logger.info("Path requested: {}", request.getURI().getPath());
return chain.filter(exchange)
.then(Mono.fromRunnable(() -> {
ServerHttpResponse response = exchange.getResponse();
logger.info("Response status: {}", response.getStatusCode());
}));
}
@Override
public int getOrder() {
return -1;
}
}
3. Sécurité
3.1 Configuration JWT
spring:
security:
oauth2:
resourceserver:
jwt:
issuer-uri: http://localhost:9000
jwk-set-uri: http://localhost:9000/.well-known/jwks.json
3.2 Filtre d’Authentification
@Component
public class JwtAuthenticationFilter implements GlobalFilter {
private final JwtDecoder jwtDecoder;
public JwtAuthenticationFilter(JwtDecoder jwtDecoder) {
this.jwtDecoder = jwtDecoder;
}
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
String token = extractToken(request);
if (token != null) {
try {
Jwt jwt = jwtDecoder.decode(token);
ServerHttpRequest modifiedRequest = request.mutate()
.header("X-User-Id", jwt.getSubject())
.build();
return chain.filter(exchange.mutate().request(modifiedRequest).build());
} catch (JwtException e) {
return unauthorized(exchange);
}
}
return chain.filter(exchange);
}
private String extractToken(ServerHttpRequest request) {
String bearerToken = request.getHeaders().getFirst(HttpHeaders.AUTHORIZATION);
if (bearerToken != null && bearerToken.startsWith("Bearer ")) {
return bearerToken.substring(7);
}
return null;
}
private Mono<Void> unauthorized(ServerWebExchange exchange) {
ServerHttpResponse response = exchange.getResponse();
response.setStatusCode(HttpStatus.UNAUTHORIZED);
return response.setComplete();
}
}
4. Limitation de Débit
4.1 Configuration Redis
spring:
redis:
host: localhost
port: 6379
4.2 Configuration du Rate Limiter
@Configuration
public class RateLimiterConfig {
@Bean
KeyResolver ipKeyResolver() {
return exchange -> Mono.just(
exchange.getRequest().getRemoteAddress().getHostName()
);
}
}
5. Monitoring et Métriques
5.1 Configuration Actuator
management:
endpoints:
web:
exposure:
include: health,info,metrics,prometheus
endpoint:
health:
show-details: always
5.2 Métriques Personnalisées
@Component
public class GatewayMetrics {
private final MeterRegistry registry;
private final Counter requestCounter;
private final Timer requestLatency;
public GatewayMetrics(MeterRegistry registry) {
this.registry = registry;
this.requestCounter = Counter.builder("gateway.requests")
.description("Total number of requests")
.tag("type", "all")
.register(registry);
this.requestLatency = Timer.builder("gateway.latency")
.description("Request latency")
.register(registry);
}
public void recordRequest() {
requestCounter.increment();
}
public void recordLatency(long milliseconds) {
requestLatency.record(milliseconds, TimeUnit.MILLISECONDS);
}
}
Conclusion
L’API Gateway avec Spring Cloud Gateway offre plusieurs avantages :
- Routage intelligent vers les microservices
- Sécurité centralisée avec JWT
- Limitation de débit pour protéger les services
- Monitoring et métriques
- Filtres personnalisables pour la transformation des requêtes
Dans le prochain tutoriel, nous verrons comment implémenter le pattern Circuit Breaker avec Resilience4J pour gérer la résilience de nos microservices.
Commentaires
Les commentaires sont alimentés par GitHub Discussions
Connectez-vous avec GitHub pour participer à la discussion