이번 강의에서는 Spring Cloud Gateway
를 활용하여 Rate Limiter
패턴을 구현하는 방법을 배웁니다. Rate Limiter
패턴은 시스템에 대한 요청이 일정한 속도를 초과할 때, 해당 요청을 제한하고 HTTP 429
상태 코드를 반환하여 "Too Many Requests" 오류를 발생시킵니다.
Rate Limiter
패턴을 구현하려면 몇 가지 중요한 구성 요소를 이해해야 합니다:
KeyResolver
는 Rate Limiter
가 요청을 제한할 기준을 정의하는 인터페이스입니다. 이 기준은 사용자, 세션, IP 주소 또는 서버 등 다양한 요소에 기반할 수 있습니다.
PrincipalNameKeyResolver
를 사용하여 로그인한 사용자 이름을 기준으로 Rate Limiter를 설정할 수 있습니다.Spring Cloud Gateway
에서는 Redis를 사용한 Rate Limiter
구현을 지원합니다. Redis는 캐시 기반의 저장 시스템으로, Rate Limiter의 구현에 적합합니다. 이 구현은 Stripe 팀의 작업을 기반으로 하고 있으며, 기본적으로 토큰 버킷(Token Bucket) 알고리즘을 사용합니다.
replenishRate
가 100으로 설정되면, 매 초마다 100개의 토큰이 버킷에 추가됩니다.burstCapacity
가 200으로 설정되면, 버킷에는 최대 200개의 토큰이 저장됩니다.이제 Rate Limiter
패턴을 Spring Cloud Gateway에 구현해보겠습니다.
먼저, Redis 기반의 Rate Limiter
를 사용하기 위해 Maven pom.xml
에 필요한 종속성을 추가합니다.
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
이제 Rate Limiter
를 설정하기 위해 Java 코드와 Yaml 설정 파일을 사용합니다.
RouteLocator
를 설정할 때 Rate Limiter
를 추가합니다. 이 예제에서는 사용자의 IP 주소를 기준으로 Rate Limiter를 설정합니다.
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder, RedisRateLimiter redisRateLimiter) {
return builder.routes()
.route("loans-service", r -> r.path("/loans/**")
.filters(f -> f
.requestRateLimiter(c -> c
.setRateLimiter(redisRateLimiter)
.setKeyResolver(ipKeyResolver())))
.uri("lb://loans-service"))
.build();
}
@Bean
public KeyResolver ipKeyResolver() {
return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getAddress().getHostAddress());
}
ipKeyResolver()
: 요청자의 IP 주소를 기준으로 Rate Limiter를 설정합니다.RedisRateLimiter
: RedisRateLimiter
를 사용하여 토큰 버킷 알고리즘을 통해 요청을 제한합니다.application.yml
파일에서 Rate Limiter
의 속성을 정의합니다.
spring:
cloud:
gateway:
routes:
- id: loans-service
uri: lb://loans-service
filters:
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 10
redis-rate-limiter.burstCapacity: 20
redis-rate-limiter.requestedTokens: 1
replenishRate
: 초당 10개의 요청을 허용하도록 설정합니다.burstCapacity
: 최대 20개의 요청을 허용하도록 설정합니다.requestedTokens
: 각 요청에 1개의 토큰을 소모하도록 설정합니다.이제 Spring Cloud Gateway를 실행하고, Postman 등을 사용하여 설정한 Rate Limiter
가 올바르게 동작하는지 테스트합니다.
Postman에서 설정한 엔드포인트로 여러 개의 요청을 보냅니다. Rate Limiter
가 동작하면 초과된 요청에 대해 HTTP 429 Too Many Requests
응답을 반환합니다.
GET /loans/contact-info
Status: 429 Too Many Requests
Redis를 모니터링하여 토큰이 어떻게 관리되고 있는지 확인할 수 있습니다. Redis CLI를 사용하여 관련 키와 값을 확인할 수 있습니다.
redis-cli
> KEYS *
> GET <your_key>
이번 강의에서는 Spring Cloud Gateway를 사용하여 Rate Limiter
패턴을 구현하는 방법을 배웠습니다. Redis를 활용하여 Rate Limiter를 설정하고, KeyResolver를 통해 사용자 정의 제한 조건을 설정했습니다. 이 구현을 통해 트래픽을 효과적으로 관리하고 시스템의 안정성을 유지할 수 있습니다.
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder, RedisRateLimiter redisRateLimiter) {
return builder.routes()
.route("loans-service", r -> r.path("/loans/**")
.filters(f -> f
.requestRateLimiter(c -> c
.setRateLimiter(redisRateLimiter)
.setKeyResolver(ipKeyResolver())))
.uri("lb://loans-service"))
.build();
}
@Bean
public KeyResolver ipKeyResolver() {
return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getAddress().getHostAddress());
}
spring:
cloud:
gateway:
routes:
- id: loans-service
uri: lb://loans-service
filters:
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 10
redis-rate-limiter.burstCapacity: 20
redis-rate-limiter.requestedTokens: 1
이제 Spring Cloud Gateway를 사용하여 시스템의 트래픽을 효율적으로 제한하고 관리할 수 있게 되었습니다. 이 설정을 통해 서버 리소스를 보호하고, 악성 또는 과도한 요청으로 인한 장애를 방지할 수 있습니다.