본문 바로가기
Back-end/Spring Cloud (MSA)

Spring Cloud (MSA) - Resilience4j @Retry @CircuitBreaker(서킷브레이커)

by javapp 자바앱 2022. 12. 6.
728x90

Resilience4j

 

앞의 서비스가 다운되거나 느릴 때

전체 chain에 영향을 끼친다.

 

-> 만약 그럴때 fallback 반환

-> 부하 감소를 위한 CIrcuit Breaker pattern을 구현

-> 다시 요청

-> 속도 제한

Resilience4j

 

 

 


 

 

currency-exchange-service 프로젝트

 

의존성 추가

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
   <groupId>io.github.resilience4j</groupId>
   <artifactId>resilience4j-spring-boot2</artifactId>
</dependency>

 

package com.javapp.microservices.currencyexchangeservice.controller;


import io.github.resilience4j.retry.annotation.Retry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
public class CircuitBreakerController {
    private Logger logger = LoggerFactory.getLogger(CircuitBreakerController.class);

    @GetMapping("/resilience")
    @Retry(name = "resilience", fallbackMethod = "hardcodedResponse")
    public String resilience(){
        logger.info("resilience call received");
        ResponseEntity<String> forEntity = new RestTemplate().getForEntity("http://localhost:8080/call-error",String.class);
        return forEntity.getBody();
    }

    public String hardcodedResponse(){
        return "fallback-response";
    }
}

 

리소스 요청 에러시 재시도 @Retry

import io.github.resilience4j.retry.annotation.Retry;

 

 

Caused by: java.lang.NoSuchMethodException: class java.lang.String class com.javapp.microservices.currencyexchangeservice.controller.CircuitBreakerController.hardcodedResponse(,class java.lang.Throwable)

함수에 Throwable 객체가 필요

public String hardcodedResponse(Exception exception){
    return "fallback-response";
}

파라미터 추가

 

요청 : localhost:8000/resilience

기본적으로 3번 Retry

 

 

 

application.properties

# 최대 재요청 횟수
resilience4j.retry.instances.resilience.maxAttempts=5
# 재요청 시간 간격
resilience4j.retry.instances.resilience.waitDuration=1s
# 재요청 시간 간격 점차 증가
resilience4j.retry.instances.resilience.enableExponentialBackoff=true

5번 재요청 후에 결과 반환

 

 


 

서킷 브레이커

 

@GetMapping("/resilience")
//@Retry(name = "resilience", fallbackMethod = "hardcodedResponse")
@CircuitBreaker(name = "default", fallbackMethod = "hardcodedResponse")
public String resilience(){
    logger.info("resilience call received");
    ResponseEntity<String> forEntity = new RestTemplate().getForEntity("http://localhost:8080/call-error",String.class);
    return forEntity.getBody();
}

 

오류가 없을 때는 CLOSED

서킷이 OPEN 일 때 빠른 실패 로직을 수행

시간이 지나면 HALF OPEN 상태로 전환되어 새로운 호출 허용

 

 

resilience4j.circuitbreaker.instances.default.failureRateThreshold=90

 

 

CircuitBreaker (readme.io)

 

CircuitBreaker

Getting started with resilience4j-circuitbreaker

resilience4j.readme.io

 

Resilience4j를 이용한 서킷 브레이커 기초 - Yun Blog | 기술 블로그 (cheese10yun.github.io)

 

Resilience4j를 이용한 서킷 브레이커 기초 - Yun Blog | 기술 블로그

Resilience4j를 이용한 서킷 브레이커 기초 - Yun Blog | 기술 블로그

cheese10yun.github.io

 

 


RateLimiter

단위 시간동안 얼마만큼의 실행을 허용할 것인지 제한

#ratelimiter
resilience4j.ratelimiter.instances.default.limitForPeriod=2
resilience4j.ratelimiter.instances.default.limit-refresh-period=10s
@RateLimiter(name = "default")

 

 


 

BulkHead

동시에 호출되는 수를 제한해 장애 방지

# bulkhead
resilience4j.bulkhead.instances.resilience.maxConcurrentCalls=10

 

@Bulkhead(name = "resilience")

 

 

 

 

댓글