코딩공작소

MSA(7) - Resilience4j를 사용한 회복성 패턴 본문

어플리케이션개발/MSA

MSA(7) - Resilience4j를 사용한 회복성 패턴

안잡아모찌 2024. 7. 14. 20:59
서비스가 망가지면 쉽게 감지할 수 있으며 애플리케이션은 이를 우회할 수 있다.
그러나,
서비스가 느려진다면 성능 저하를 감지하고 우회하는 일은 어렵다.
그 이유로는,
1. 성능 저하는 간헐적으로 시작되어 확산될 수 있다.
2. 호출은 대게 동기식이며 장기간 수행되는 호출을 중단하지 않는다.
3. 부분적인 저하가 아닌 완전한 실패를 처리하도록 애플리케이션을 설계한다.

 

해당 포스팅에서는 4가지의 클라이언트 회복성 패턴을 소개한다.

 

1. 클라이언트 측 로드 밸런싱

물리척 위치를 캐싱하는 작업을 말한다. 클라이언트 측 로드 밸런서가 문제를 탐지하면 가용 서비스 풀에서 문제된 서비스 인스턴스를 제거하여 해당 서비스 인스턴스로 더이상 호출되지 않게 한다.

 

2. 회로차단기

회로 차단기 패턴은 원격 자원에 대한 모든 호출을 모니터링 하고, 호출이 충분히 실패하면 회로 차단기 구현체가 열리면서 빠르게 실패하고 고장난 원격 자원에 대한 추가 호출을 방지한다.

 

3. 폴백 처리

서비스 호출이 실패할 때 예외(Exception)을 생성하지 않고 서비스 소비자가 대체 코드 경로를 실행하여 다른 수단을 통해 작업을 수행할 수 있다.
폴백은 모든 사용자의 구매 정보를 기반으로 더욱 일반화된 기로 목록을 검색할 수 있다. 그리고 이 데이터는 완전히 다른 서비스와 데이터 소스에서 추출될 수 있다.

 

4. 벌크헤드

스레드 풀별로 서비스를 할당하면 다른 서비스는 포화되지 않기 때문에 이러한 병목 현상을 우회하는 데 유용하다.

 

 

Resilience4j는 내결함성 라이브러리로 아래와 같은 결함 내성을 높이기 위한 패턴을 제공한다

  • 회로 차단기 : 요청받은 서비스가 실패할 때 요청을 중단
  • 재시도 : 서비스가 일시적으로 실패할 때 재시도
  • 벌크헤드 : 과부하를 피하고자 동시 호출하는 서비스 요청 수를 제한
  • 속도 제한 : 서비스가 한 번에 수신하는 호출 수를 제한
  • 폴백 : 실패하는 요청에 대해 대체 경로를 설정

 

Resilience4j를 사용하려면 pom.xml 파일에 필요한 의존성을 포함해야 한다.

		<dependency>
		    <groupId>io.github.resilience4j</groupId>
		    <artifactId>resilience4j-circuitbreaker</artifactId>
		    <version>${resilience4j.version}</version>
		</dependency>
		<dependency>
		    <groupId>io.github.resilience4j</groupId>
		    <artifactId>resilience4j-timelimiter</artifactId>
		    <version>${resilience4j.version}</version>
		</dependency>
		 <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

resilience4j-circuitbreaker 와 resilience4j-timelimiter 산출물에는 회로 차단기 및 속도 제한기를 구현한 로직이 포함된다.
spring-boot-starter-aop는 스프링 AOP 관점을 실행하는 데 필요하다. AOP는 코드를 수정하지 않고 새로운 동작을 기존 코드에 추가한다.

 

 

회로 차단기 구현

차단기 패턴에서는 빠른 실패를 구현하고 서비스에 추가로 요청하는 것을 방지해야 한다.

Resilience4j는 모든 원격 자원 호출 사이에 위차하여 클라이언트를 보호하고, 원격 자원이 데이터베이스나 REST 기반 서비스를 호출하지는지는 중요하지 않다.

 

 

각각의 회복 패턴을 사용하기 위해서는 application.yml, bootstrap.yml에 파라미터를 추가하여 사용한다.

 

 

 

회로 차단기 적용

@CircuitBreaker(name = "licenseService")
public List<License> getLicensesByOrganization(String organizationId) {
	return licenseRepository.findByOrganizationid(organizationId);
}

해당 애너테이션을 통해 함수가 호출 될 때마다 해당 호출은 Resilience4j 회로 차단기로 래핑된다.

 

 

폴백 처리

@CircuitBreaker(name = "licenseService",
	fallbackMethod = "buildFallbackLicenseList") --> 서비스 호출이 실패할 때 호출되는 함수 정의
public List<License> get...(){
...
}

private List<License> buildFallbackLicenseList(String a, Throwable t){
... --> 이 폴백 메서드에서는 하드코딩된 값을 반환한다.
}

해당 패턴에서는 매개변수를 받도록 동일한 서식을 가져야 한다.

 

벌크헤드 패턴 구현

  • 세마포어 벌크헤드 : 동시 요청수를 제한
  • 스레드 풀 벌크헤더 : 폴과 큐가 다 찬 경우만 요청을 거부

@CircuitBreaker(...)
@Bulkhead(name = "bulkheadLicenseService",
	fallbackMethod = "buildFallbackLicenseList") --> 벌크헤드 패턴을 위해 인스턴스 이름과 
    폴백 메서드를 설정한다
public List<License> getLicense...{
...
}

 

 

재시도 패턴 구현

서비스 인스턴스에 대한 재시도 횟수와 재시도 사이에 전달하려는 간격을 지정

@CircuitBreaker...
@Retry(name = "retryLicenseService"),
	fallbackMethod = "buildFallbackLicenseList") --> 재시도 패턴을 위해 인스턴스 이름과 
    폴백 메서드를 설정한다.
@BulkHead...
public List<License> get... {
...
}

 

 

 

  • MSA 설계할 때는 클라이언트 회복성을 고려 해야 한다.
  • 서비스 전면 장애를 쉽게 탐지하고 처리할 수 있다
  • 성능이 낮은 서비스 하나가 연쇄작용을 하도록 하는 것을 방지 할 수 있다.
  • 회로 차단기 패턴, 폴백 패턴, 벌크헤드 패턴이 핵심 패턴이다.
  • 회로 차단기 패턴은 저하된 시스템 호출을 제거해 자원 소진을 막는다
  • 폴백 패턴은 원격 서비스 호출이 실패하거나 회로 차단기가 실패할 경우 대체 코드 경로를 정의할 수 있다
  • 벌크헤드 패턴은 한 종류의 서비스 호출이 실패하면 모든 컨테이너의 자원이 소진되지 않도록 한다
  • 재시도 패턴은 서비스가 일시적으로 실패했을 때 시도하는 역할을 한다