티스토리 뷰
728x90
반응형
Resilience4j
자바 기반의 강력한 회복성 및 내결함성 라이브러리로, 분산 시스템 및 서비스에서 오류와 장애에 대응하는 데 사용
Resilience4j는 멀티 스레딩 환경에서 안전하게 동작하며, 고성능을 제공
- 서킷 브레이커 (Circuit Breaker): 서킷 브레이커 패턴을 구현하여 서비스 호출 중에 장애가 발생할 경우 재시도 및 회복을 관리합니다. 서킷이 열린 상태에서 호출을 차단하고, 특정 시간 동안 호출을 시도하지 않도록 설정할 수 있습니다.
- 한도 지정 (Rate Limiting): 요청을 한도 내에서 제한하고 초과하는 경우 요청을 거부하거나 대기시킬 수 있습니다.
- 반환 값 및 예외 처리 (Response and Exception Handling): 성공과 실패에 대한 반환 값을 처리하고, 실패 시 예외 처리를 사용자 정의할 수 있습니다.
- Retry 메커니즘: 서비스 호출이 실패한 경우 재시도 기능을 제공합니다. 재시도 횟수 및 재시도 간격을 설정할 수 있습니다.
- 메트릭과 모니터링: Resilience4j는 호출된 메소드의 성능 및 실패에 대한 메트릭을 수집하고, 이러한 메트릭을 모니터링 도구로 내보낼 수 있도록 지원합니다.
- 자동 데코레이터 (Auto-Decorators): 자동 데코레이터를 사용하여 Resilience4j 기능을 기존 코드에 쉽게 통합할 수 있습니다.
- 상태 및 구성 관리: Resilience4j는 YAML 또는 프로퍼티 파일을 사용하여 서비스의 동작을 구성할 수 있습니다.
build.gradle
dependencies {
implementation 'org.springframework.cloud:spring-cloud-starter-circuitbreaker-resilience4j'
}
application.yml
spring:
cloud:
openfeign:
circuitbreaker:
enabled: true
alphanumeric-ids: #circuitBreaker 인스턴스를 구분하는 name을 알파벳과 숫자로 설정 여부
enabled: true
resilience4j:
circuitbreaker:
default:
minimumNumberOfCalls: 100
instances:
DemoClientgetDemo:
minimumNumberOfCalls: 69
timelimiter:
instances:
DemoClientgetDemo:
timeoutDuration: 10s
minimumNumberOfCalls Test
@SpringBootTest
@AutoConfigureWireMock(port = 0)
@TestPropertySource(properties = {
"naver.openapi-url=http://localhost:${wiremock.server.port}",
"resilience4j.circuitbreaker.configs.default.minimumNumberOfCalls=10", //설정 변경
})
@ExtendWith(SpringExtension.class)
class FeignClientWireMockTest {
@Autowired
FeignClient feignClient;
@Test
void searchLocalResilience4jTest_whenServerError_thenCallFallbackFactory() {
WireMock.stubFor(WireMock.get(WireMock.urlPathEqualTo("/v1/search/local.json"))
.willReturn(WireMock.aResponse().withStatus(HttpStatus.INTERNAL_SERVER_ERROR_500)));
var search = new SearchLocalReq();
search.setQuery("갈비집");
for (int i=0; i<20; i++) {
var result = feignClient.searchLocal(search); //10번째까지 500서버 에러로 FeignException, 11번째부터는 circuit breaker open 으로 CallNotPermittedException
assertThat(result).isNotNull();
assertThat(result.getTotal()).isEqualTo(0);
}
}
}
slowCallDurationThreshold Test
@SpringBootTest
@AutoConfigureWireMock(port = 0)
@TestPropertySource(properties = {
"naver.openapi-url=http://localhost:${wiremock.server.port}",
"resilience4j.circuitbreaker.configs.default.slowCallDurationThreshold=3s" //설정 변경
})
@ExtendWith(SpringExtension.class)
class FeignClientWireMockTest {
@Autowired
FeignClient feignClient;
@Test
void searchLocalResilience4jTest_whenServerDelay_thenTimeout() {
WireMock.stubFor(WireMock.get(WireMock.urlPathEqualTo("/v1/search/local.json"))
.willReturn(WireMock.aResponse()
.withStatus(HttpStatus.OK_200)
.withFixedDelay(4000) //slowCallDurationThreshold 3초 설정으로 slow 카운팅
.withHeader("Content-Type", "application/json")
.withBody("{\n" +
"\t\"lastBuildDate\":\"Sun, 01 Oct 2023 23:31:58 +0900\",\n" +
"\t\"total\":1,\n" +
"\t\"start\":1,\n" +
"\t\"display\":1,\n" +
"\t\"items\":[\n" +
"\t\t{\n" +
"\t\t\t\"title\":\"몽탄2\",\n" +
"\t\t\t\"link\":\"http:\\/\\/www.mongtan.co.kr\",\n" +
"\t\t\t\"category\":\"한식>육류,고기요리\",\n" +
"\t\t\t\"description\":\"\",\n" +
"\t\t\t\"telephone\":\"\",\n" +
"\t\t\t\"address\":\"서울특별시 용산구 한강로1가 251-1\",\n" +
"\t\t\t\"roadAddress\":\"서울특별시 용산구 백범로99길 50\",\n" +
"\t\t\t\"mapx\":\"1269722500\",\n" +
"\t\t\t\"mapy\":\"375360103\"\n" +
"\t\t}\n" +
"\t]\n" +
"}")));
var search = new SearchLocalReq();
search.setQuery("갈비집");
for (int i=0; i<20; i++) {
var result = feignClient.searchLocal(search);
if (i < 10) { //10번째까지는 circuit breaker closed
assertThat(result).isNotNull();
assertThat(result.getTotal()).isEqualTo(1);
} else { //11번째부터 circuit breaker open
assertThat(result).isNotNull();
assertThat(result.getTotal()).isEqualTo(0);
}
}
}
}
https://resilience4j.readme.io/docs/circuitbreaker
Spring Cloud LoadBalancer
- Spring Cloud Netflix Ribbon의 대체 기술로, Spring Boot 2.4 이상에서 기본 로드 밸런싱 솔루션으로 제공
- 서비스 클라이언트가 여러 인스턴스 중 하나를 선택하여 호출하는 방식.
- Eureka, Consul 등과 쉽게 연동하여 동적으로 서비스 인스턴스를 검색하고 로드 밸런싱 수행.
- 기본적으로 Round Robin 방식이 적용되며, 필요하면 사용자 정의 로드 밸런싱 정책도 구현 가능.
Feign Client와 함께 사용
Feign을 사용할 때도 별도의 설정 없이 Spring Cloud LoadBalancer가 자동으로 적용됨.
@FeignClient(name = "user-service")
public interface UserServiceClient {
@GetMapping("/api/users")
String getUsers();
}
user-service의 여러 인스턴스 중 하나가 자동으로 선택됨.
로드 밸런싱 정책 변경하기
기본 정책은 Round Robin이지만, 필요하면 커스텀 로드 밸런싱 전략을 적용할 수 있음.
@Configuration
public class CustomLoadBalancerConfiguration {
@Bean
public ReactorLoadBalancer<ServiceInstance> randomLoadBalancer(
Environment environment,
LoadBalancerClientFactory factory
) {
String serviceName = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
return new RandomLoadBalancer(
factory.getLazyProvider(serviceName, ServiceInstanceListSupplier.class),
serviceName
);
}
}
@LoadBalancerClient(name = "user-service", configuration = CustomLoadBalancerConfiguration.class)
public class LoadBalancerConfig {
}
728x90
반응형
'Spring' 카테고리의 다른 글
[Spring Boot] 2.7.8 버전 이후 Amazon RDS Aurora MySQL JDBC Driver 변경 (0) | 2023.11.21 |
---|---|
[Spring] Swagger CORS 이슈 (0) | 2023.11.09 |
[Spring Boot] OpenFeign Fallback (0) | 2023.10.03 |
[Spring Boot] WireMock API 테스트 (0) | 2023.10.03 |
[Spring Boot] OpenFeign 로깅 설정 (0) | 2023.10.01 |
반응형
300x250