이번 강의에서는 Spring Cloud Gateway
를 사용하여 Rate Limiter
패턴을 구현하는 방법을 단계별로 설명합니다. 이를 통해 각 사용자에 대해 초당 요청 수를 제한하고, 너무 많은 요청이 발생할 경우 HTTP 429
상태 코드를 반환하는 기능을 구현합니다.
먼저, Redis를 사용하기 위해 spring-boot-starter-data-redis-reactive
의존성을 pom.xml
파일에 추가합니다.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
Maven 로드를 통해 의존성을 프로젝트에 반영합니다.
이제 GatewayserverApplication
클래스에서 KeyResolver
와 RedisRateLimiter
를 설정합니다.
KeyResolver는 요청이 속한 사용자를 식별하는 데 사용됩니다. 이 예제에서는 user
라는 HTTP 헤더를 기준으로 Rate Limiter를 설정합니다.
@Bean
public KeyResolver userKeyResolver() {
return exchange -> Mono.just(
exchange.getRequest().getHeaders().getFirst("user") != null ?
exchange.getRequest().getHeaders().getFirst("user") : "anonymous"
);
}
user
헤더를 읽어 키를 생성합니다. 헤더가 없으면 기본값인 anonymous
를 사용합니다.이제 RedisRateLimiter를 설정합니다. 이는 Redis를 사용하여 Rate Limiter를 관리합니다.
@Bean
public RedisRateLimiter redisRateLimiter() {
return new RedisRateLimiter(1, 1);
}
replenishRate
와 burstCapacity
를 각각 1
로 설정합니다. 이는 매초 하나의 요청을 허용하며, 한 번에 하나의 요청만 처리할 수 있음을 의미합니다.이제 카드 서비스에 대해 Rate Limiter를 설정합니다.
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder,
RedisRateLimiter redisRateLimiter) {
return builder.routes()
.route("cards-service", r -> r.path("/cards/**")
.filters(f -> f
.addResponseHeader("X-Response-Time", LocalDateTime.now().toString())
.requestRateLimiter(c -> c
.setRateLimiter(redisRateLimiter)
.setKeyResolver(userKeyResolver())))
.uri("lb://cards-service"))
.build();
}
requestRateLimiter
필터: 이 필터는 설정된 RedisRateLimiter와 KeyResolver를 사용하여 Rate Limiter를 적용합니다.이제 Redis 서버를 Docker 컨테이너로 시작합니다.
docker run -p 6379:6379 --name eazyredis -d redis
6379
에서 실행합니다.application.yml
파일에 Redis 연결 정보를 추가합니다.
spring:
data:
redis:
host: localhost
port: 6379
timeout: 60000ms
이제 모든 설정이 완료되었으므로 애플리케이션을 시작합니다. Config Server
, Eureka Server
, Cards Service
, 그리고 Gateway Server
를 순서대로 실행합니다.
이제 Apache Benchmark 도구를 사용하여 Rate Limiter를 테스트합니다.
Apache Benchmark는 간단한 부하 테스트 도구입니다. Mac에서는 brew
명령어로 쉽게 설치할 수 있습니다.
brew install httpd
다음 명령어를 사용하여 부하 테스트를 실행합니다:
ab -n 10 -c 2 -v 3 http://localhost:8080/cards/contact-info
-n 10
: 10개의 요청을 보냅니다.-c 2
: 동시에 2개의 요청을 보냅니다.-v 3
: 자세한 출력 정보를 표시합니다.http://localhost:8080/cards/contact-info
는 테스트할 엔드포인트입니다.결과는 다음과 같이 표시됩니다:
Document Path: /cards/contact-info
Document Length: 117 bytes
Concurrency Level: 2
Time taken for tests: 0.050 seconds
Complete requests: 10
Failed requests: 9
(Connect: 0, Receive: 0, Length: 9, Exceptions: 0)
Non-2xx responses: 9
Total transferred: 1720 bytes
HTML transferred: 1170 bytes
Requests per second: 199.13 [#/sec] (mean)
Time per request: 10.053 [ms] (mean)
Time per request: 5.027 [ms] (mean, across all concurrent requests)
Transfer rate: 33.53 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 1 1 0.2 1 1
Processing: 3 5 2.7 5 10
Waiting: 3 5 2.7 5 10
Total: 4 6 2.8 6 11
Percentage of the requests served within a certain time (ms)
50% 6
66% 7
75% 8
80% 9
90% 11
95% 11
98% 11
99% 11
100% 11 (longest request)
HTTP 429
상태 코드가 반환되었습니다.이번 강의에서는 Spring Cloud Gateway
와 Redis를 사용하여 Rate Limiter
패턴을 구현하는 방법을 학습했습니다. 이를 통해 각 사용자에 대한 요청 수를 제한하고, 시스템의 안정성을 유지할 수 있음을 확인했습니다. Rate Limiter 설정을 통해 악성 또는 과도한 요청을 효과적으로 방지할 수 있습니다.