2021. 8. 7. 23:31ㆍSpringBoot Monitoring/SpringBoot Resilience4j
resilience4j-retry 예제를 작성하기 전에 한 가지 시나리오를 생각해 보자.
사용자가 주문을 할때 가장 중요한 부분은 결제 일 것이다. 그런데 시스템 운영 중 중요한 오류가 있어서 서버에 소스를 반영하고 재기동해야 한다고 하면 그 시간 동안 회사는 많은 손해가 발생할 것입니다.
만약 소스를 반영하고 서버 재기동 까지 1분 안에 가능하다고 한다면 사용자가 주문이 잠시 느려지더라도 결제까지 정상적으로 실행할 수 있을 것이다.
이렇게 되면 서비스 제공자 입장에서는 정상적으로 서비스를 제공하면서 큰 문제를 막을 수 있을 것이다.
극단적인 시나리오 일수 있겠지만 실제로 서비스를 운영하다 보면 저러한 문제들이 있을 것입니다.
Retry는 이러한 문제를 해결 하기에 적합하다는 생각이 듭니다.
소스는 아래 사이트에서 받으실 수 있습니다.
https://github.com/roopy1210/spring-boot-resilience4j
[application.yml]
spring:
application.name: order-service
output.ansi.enabled: always
server:
port: 7070
management.endpoints.web.exposure.include: '*'
management.endpoint.health.show-details: always
# Spring actuator 에 circuitbreaker 정보를 표시하기 위한 설정
management.health.circuitbreakers.enabled: true
#-------------------------------------------------------------
# Retry Configuration
#-------------------------------------------------------------
# 설정의 의미는 총 30초 동안 10초 간격으로 서비스 호출을 3번
# 한다는 의미이다.
#-------------------------------------------------------------
retry:
instances:
orderService:
maxRetryAttempts: 3
waitDuration: 10s
주석에도 설명 되어 있지만 위의 설정은 30초 동안 10초 간격으로 서비스 호출을 3번 한다는 의미이다.
[RetrySericeImpl]
package com.roopy.service.impl;
import com.roopy.service.OrderService;
import io.github.resilience4j.retry.annotation.Retry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
@Service
@Qualifier("retryService")
public class RetryServiceImpl implements OrderService {
Logger logger = LoggerFactory.getLogger(OrderService.class);
@Autowired
private RestTemplate restTemplate;
private int attempts = 1;
@Override
@Retry(name = "orderService", fallbackMethod = "retryFallback")
public String makeOrder() {
logger.info("결제서비스 호출 횟수 : " + attempts++);
return restTemplate.getForObject("http://localhost:7071/pay", String.class);
}
public String retryFallback(Throwable t) {
attempts = 1;
logger.error("Retry fallback, cause - {}", t.toString());
return "[Retry] 결제서비스 호출 중 오류가 발생 하였습니다.";
}
}
주문 서비스에서는 결제 서비스를 Rest방식으로 호출하는데 이때 application.yml 에 설정된 총 30초 동안 10초에 한 번씩 결제 서비스를 호출하고 3번 호출되기 전에 결제 서비스가 실행되면 정상적으로 주문처리가 될 것이다.
[테스트 결과]
첫 번째로 payment-service 서버는 실행하지 않은 상태에서 수행 결과 실패
두 번째로 payment-service 서버 실행 후 재 수행 결과 성공
콘솔 로그
로그 결과를 보면 1번 결과는 payment-service 서버가 실행되지 않은 상태에서 설정 파일에서 설정한 maxRetryAttempts: 3 횟수 만큼 실행 후 오류를 발생하는 것을 확인할 수 있습습니다. 2번 결과는 payment-service 실행 후 다시 주문 서비스를 호출하게 되면 정상적으로 수행된 것을 확인할 수 있습니다.
Grafana 로그
'SpringBoot Monitoring > SpringBoot Resilience4j' 카테고리의 다른 글
RateLimiter 예제 (0) | 2021.08.22 |
---|---|
Bulkhead 예제 (0) | 2021.08.15 |
CircuitBreaker 예제 (0) | 2021.07.31 |
CircuitBreaker 개념 (0) | 2021.07.31 |