Rate Limiter 패턴 구현

날아올라돼지야·2024년 8월 29일
0

1. Rate Limiter 패턴 구현

이번 강의에서는 Spring Cloud Gateway를 사용하여 Rate Limiter 패턴을 구현하는 방법을 단계별로 설명합니다. 이를 통해 각 사용자에 대해 초당 요청 수를 제한하고, 너무 많은 요청이 발생할 경우 HTTP 429 상태 코드를 반환하는 기능을 구현합니다.

2. Redis 의존성 추가

먼저, 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 로드를 통해 의존성을 프로젝트에 반영합니다.

3. KeyResolver 및 RedisRateLimiter 설정

이제 GatewayserverApplication 클래스에서 KeyResolverRedisRateLimiter를 설정합니다.

3.1 KeyResolver 정의

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"
    );
}
  • KeyResolver 설명: user 헤더를 읽어 키를 생성합니다. 헤더가 없으면 기본값인 anonymous를 사용합니다.

3.2 RedisRateLimiter 설정

이제 RedisRateLimiter를 설정합니다. 이는 Redis를 사용하여 Rate Limiter를 관리합니다.

@Bean
public RedisRateLimiter redisRateLimiter() {
    return new RedisRateLimiter(1, 1);
}
  • RedisRateLimiter 설정: replenishRateburstCapacity를 각각 1로 설정합니다. 이는 매초 하나의 요청을 허용하며, 한 번에 하나의 요청만 처리할 수 있음을 의미합니다.

4. Route 설정 및 필터 적용

이제 카드 서비스에 대해 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를 적용합니다.

5. Redis 서버 시작

이제 Redis 서버를 Docker 컨테이너로 시작합니다.

docker run -p 6379:6379 --name eazyredis -d redis
  • Docker 명령어 설명: Redis 서버를 포트 6379에서 실행합니다.

6. Redis 설정 추가

application.yml 파일에 Redis 연결 정보를 추가합니다.

spring:
  data:
    redis:
      host: localhost
      port: 6379
      timeout: 60000ms

7. 애플리케이션 시작

이제 모든 설정이 완료되었으므로 애플리케이션을 시작합니다. Config Server, Eureka Server, Cards Service, 그리고 Gateway Server를 순서대로 실행합니다.

8. Rate Limiter 테스트

이제 Apache Benchmark 도구를 사용하여 Rate Limiter를 테스트합니다.

8.1 Apache Benchmark 설치 및 설정

Apache Benchmark는 간단한 부하 테스트 도구입니다. Mac에서는 brew 명령어로 쉽게 설치할 수 있습니다.

brew install httpd

8.2 부하 테스트 실행

다음 명령어를 사용하여 부하 테스트를 실행합니다:

ab -n 10 -c 2 -v 3 http://localhost:8080/cards/contact-info
  • 명령어 설명:
    • -n 10: 10개의 요청을 보냅니다.
    • -c 2: 동시에 2개의 요청을 보냅니다.
    • -v 3: 자세한 출력 정보를 표시합니다.
    • URL: http://localhost:8080/cards/contact-info는 테스트할 엔드포인트입니다.

8.3 결과 분석

결과는 다음과 같이 표시됩니다:

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)
  • 결과 해석: 10개의 요청 중 9개가 실패했으며, HTTP 429 상태 코드가 반환되었습니다.

9. 결론

이번 강의에서는 Spring Cloud Gateway와 Redis를 사용하여 Rate Limiter 패턴을 구현하는 방법을 학습했습니다. 이를 통해 각 사용자에 대한 요청 수를 제한하고, 시스템의 안정성을 유지할 수 있음을 확인했습니다. Rate Limiter 설정을 통해 악성 또는 과도한 요청을 효과적으로 방지할 수 있습니다.

profile
무슨 생각하며 사니

0개의 댓글