2025. 3. 16. 17:48ㆍSpring Microservice
🚦 Resilience4j로 Rate Limiter 패턴 완벽히 구현하기 (with Spring Cloud)
마이크로서비스 환경에서 서비스의 안정성과 가용성을 유지하는 핵심 전략 중 하나가 바로 속도 제한(Rate Limiting)입니다. 속도 제한은 일정 시간 내 처리 가능한 요청의 수를 제한해, 서비스가 과부하되는 것을 막습니다.
오늘은 Resilience4j 라이브러리를 이용한 Rate Limiter 패턴의 구현 방법을 소개합니다. 🔍🚀
✅ 1. Rate Limiter 패턴이란?
Rate Limiter 패턴은 지정된 시간 동안 서비스에 들어오는 요청 수를 제한하여, 과부하를 방지하는 설계 기법입니다.
📌 AtomicRateLimiter (디폴트)
- 별도의 백그라운드 스레드를 추가하지 않고, 해당 요청을 처리하는 스레드가 직접 이 요청을 실행할 수 있는지 여부를 결정한다
- 전체 시간을 나노초 단위로 분할하여 관리
- 매우 효율적이며 성능이 뛰어남
📌 SemaphoreBasedRateLimiter
java.util.concurrent.Semaphore
를 이용한 구현- 간단하지만 추가 스레드 관리가 필요
✅ 2. RateLimiter 설정 방법
아래는 bootstrap.yml
을 통해 Resilience4j의 RateLimiter를 설정하는 예제입니다.
📋 bootstrap.yml 설정 예시
resilience4j.ratelimiter:
instances:
licenseService:
timeoutDuration: 1000ms # 권한을 기다리는 최대 시간 (디폴트값: 5초)
limitRefreshPeriod: 5000 # 호출 권한 갱신 주기 (디폴트값: 500ns)
limitForPeriod: 5 # 주기당 허용 가능한 최대 호출 수 (디폴트값: 50)
📚 주요 설정 파라미터 완벽 정리
- timeoutDuration: 권한 대기 최대 시간 (
디폴트값: 5초
) - limitRefreshPeriod: 호출 권한 리셋 주기 (
디폴트값: 500ns
) - limitForPeriod: 주기당 최대 호출 수 (
디폴트값: 50
)
추가 설정 가능한 옵션:
intervalFunction
: 호출 간격 동적 조정 함수retryOnResultPredicate
: 결과에 따른 재시도 판단 조건retryOnExceptionPredicate
: 예외 발생 시 재시도 조건ignoreExceptions
: 무시할 예외 목록 (디폴트값: Empty 목록)
✅ 3. 실제 서비스 코드에서 RateLimiter 패턴 구현 예시
다음은 서비스 메서드에 Resilience4j의 다양한 패턴을 함께 적용한 코드 예제입니다.
📋 서비스 메서드 RateLimiter 적용 코드
@CircuitBreaker(name = "licenseService",
fallbackMethod = "buildFallbackLicenseList")
@RateLimiter(name = "licenseService",
fallbackMethod = "buildFallbackLicenseList")
@Retry(name = "retryLicenseService",
fallbackMethod = "buildFallbackLicenseList")
@Bulkhead(name = "bulkheadLicenseService",
fallbackMethod = "buildFallbackLicenseList")
public List<License> getLicensesByOrganization(String organizationId)
throws TimeoutException {
logger.debug("getLicensesByOrganization Correlation id: {}",
UserContextHolder.getContext().getCorrelationId());
randomlyRunLong(); // 장애 상황 시뮬레이션
return licenseRepository.findByOrganizationId(organizationId);
}
- 하나의 메서드에 여러 Resilience4j 패턴(CircuitBreaker, Retry, Bulkhead, RateLimiter)을 동시에 적용 가능함
- 각각의 fallback 메서드 지정 가능
✅ 4. RateLimiter와 Bulkhead의 명확한 차이점
패턴 | 역할 | 예시 |
---|---|---|
Bulkhead | 동시 호출 횟수 제한 (Concurrency) | 동시에 10개의 호출까지만 허용 |
RateLimiter | 시간당 전체 호출 횟수 제한 | 초당 100개의 호출까지만 허용 |
중요: 두 패턴을 동시에 적용하는 것도 가능하며, 요구사항에 따라 적절히 선택합니다.
✅ 5. ThreadLocal과 Resilience4j 활용 - Correlation ID 전파하기
서비스 간 요청을 추적하는 데는 Correlation ID가 필수적입니다.
아래는 Spring Filter를 통해 HTTP 헤더로부터 Correlation ID를 추출하고 ThreadLocal
에 저장하는 예제입니다.
📋 UserContextFilter 클래스
@Component
public class UserContextFilter implements Filter {
private static final Logger logger =
LoggerFactory.getLogger(UserContextFilter.class);
@Override
public void doFilter(ServletRequest servletRequest,
ServletResponse servletResponse,
FilterChain filterChain)
throws IOException, ServletException {
HttpServletRequest httpServletRequest =
(HttpServletRequest) servletRequest;
UserContextHolder.getContext().setCorrelationId(
httpServletRequest.getHeader(UserContext.CORRELATION_ID));
// 추가 헤더 저장(UserId, AuthToken 등)
filterChain.doFilter(httpServletRequest, servletResponse);
}
}
📋 UserContextHolder
public class UserContextHolder {
private static final ThreadLocal<UserContext> userContext =
new ThreadLocal<UserContext>();
public static final UserContext getContext() {
UserContext context = userContext.get();
if (context == null) {
context = createEmptyContext();
userContext.set(context);
}
return userContext.get();
}
// setContext(), createEmptyContext() 메서드 포함됨
}
📋 UserContext 클래스
@Component
public class UserContext {
public static final String CORRELATION_ID = "tmx-correlation-id";
public static final String AUTH_TOKEN = "tmx-auth-token";
public static final String USER_ID = "tmx-user-id";
public static final String ORGANIZATION_ID = "tmx-organization-id";
private String correlationId = new String();
private String authToken = new String();
private String userId = new String();
private String organizationId = new String();
// 모든 getter, setter 메서드 완벽 포함
}
✅ 6. 요청 시 Correlation ID 적용 예시 (Postman)
아래는 HTTP 요청 시 헤더에 Correlation ID를 설정하는 예시입니다:
- 헤더 키:
tmx-correlation-id
- 값:
TEST-CORRELATION-ID
✅ 7. 로깅 설정 추가 (application.yml 완벽 포함)
logging:
level:
org.springframework.web: WARN
com.optimagrowth: DEBUG
📌 주의: ThreadLocal 사용 시 잘못된 처리는 메모리 누수(memory leak)를 유발할 수 있으므로 주의하여 사용합니다.
다음 시간에는 Spring Cloud Gateway를 살펴보겠습니다. 감사합니다!
'Spring Microservice' 카테고리의 다른 글
Implementing the rate limiter pattern (0) | 2025.03.16 |
---|---|
Implementing the retry pattern (0) | 2025.03.16 |
99 퍼센타일(percentile) (0) | 2025.03.16 |
Implementing the bulkhead pattern (1) | 2025.03.16 |
Fallback processing (0) | 2025.03.16 |