‡๐Ÿ‘ฉ‍๐Ÿ’ป ‡/ºSpring

[MSA] Resilience4j | ์„œํ‚ท ๋ธŒ๋ ˆ์ด์ปค ๊ฐœ๋… ๋ฐ ์ ์šฉ

Trudy | ์†ก์—ฐ 2024. 1. 12. 16:14

๐Ÿ“MSA ๊ตฌ์กฐ์—์„œ ์„œํ‚ท ๋ธŒ๋ ˆ์ด์ปค์˜ ์—ญํ• 

 

์„œํ‚ท ๋ธŒ๋ ˆ์ด์ปค(Circuit Breaker)๋Š” ๋ถ„์‚ฐ ์‹œ์Šคํ…œ์—์„œ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ์žฅ์• ์— ๋Œ€์‘ํ•˜๊ธฐ ์œ„ํ•œ ๋””์ž์ธ ํŒจํ„ด ์ค‘ ํ•˜๋‚˜๋กœ, ํŠนํžˆ MSA(Microservices Architecture) ๊ตฌ์กฐ์—์„œ ์ค‘์š”ํ•œ ์—ญํ• ์„ ํ•œ๋‹ค. ์„œํ‚ท ๋ธŒ๋ ˆ์ด์ปค๋Š” ๋„คํŠธ์›Œํฌ๋‚˜ ์„œ๋น„์Šค ๊ฐ„์˜ ํ†ต์‹ ์—์„œ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ์žฅ์• ๋‚˜ ์ง€์—ฐ์œผ๋กœ ์ธํ•œ ์ „์ฒด ์‹œ์Šคํ…œ์˜ ์„ฑ๋Šฅ ์ €ํ•˜๋ฅผ ๋ฐฉ์ง€ํ•˜๊ณ  ์•ˆ์ •์„ฑ์„ ์œ ์ง€ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋œ๋‹ค.

 

์„œํ‚ท๋ธŒ๋ ˆ์ด์ปค์˜ ์ฃผ์š” ๊ธฐ๋Šฅ์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค. 

  1. ์žฅ์•  ํšŒํ”ผ (Fault Tolerance): ์„œํ‚ท ๋ธŒ๋ ˆ์ด์ปค๋Š” ํŠน์ • ์„œ๋น„์Šค๋‚˜ ๋„คํŠธ์›Œํฌ ํ˜ธ์ถœ์— ์žฅ์• ๊ฐ€ ๋ฐœ์ƒํ•  ๊ฒฝ์šฐ, ํ•ด๋‹น ํ˜ธ์ถœ์„ ํšŒํ”ผํ•˜๊ณ  ์ฆ‰์‹œ ์‘๋‹ตํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋œ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์žฅ์• ๊ฐ€ ์ „์ฒด ์‹œ์Šคํ…œ์— ์ „ํŒŒ๋˜๋Š” ๊ฒƒ์„ ๋ง‰์•„ ์•ˆ์ •์„ฑ์„ ํ™•๋ณดํ•œ๋‹ค.
  2. Timeout ์„ค์ •: ์„œํ‚ท ๋ธŒ๋ ˆ์ด์ปค๋Š” ํ˜ธ์ถœ๋œ ์„œ๋น„์Šค์˜ ์‘๋‹ต ์‹œ๊ฐ„์„ ๋ชจ๋‹ˆํ„ฐ๋งํ•˜๊ณ , ์ง€์ •๋œ ์‹œ๊ฐ„ ๋‚ด์— ์‘๋‹ต์ด ์—†์œผ๋ฉด ํšŒ๋กœ๋ฅผ ์—ด์–ด ๋‹ค์Œ ์š”์ฒญ์„ ์ฐจ๋‹จํ•œ๋‹ค.
  3. Fallback ๊ธฐ๋Šฅ: ์„œํ‚ท ๋ธŒ๋ ˆ์ด์ปค๊ฐ€ ํšŒ๋กœ๋ฅผ ์—ด์–ด ์š”์ฒญ์„ ์ฐจ๋‹จํ•  ๊ฒฝ์šฐ, ๋Œ€์ฒด ๋กœ์ง ๋˜๋Š” ๊ธฐ๋ณธ๊ฐ’์„ ์ œ๊ณตํ•˜์—ฌ ์ „์ฒด ์‹œ์Šคํ…œ์˜ ๊ธฐ๋Šฅ์„ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์ด๋‚˜ ์‹œ์Šคํ…œ ์„ฑ๋Šฅ์„ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค.
  4. ์‹ค์‹œ๊ฐ„ ๋ชจ๋‹ˆํ„ฐ๋ง ๋ฐ ๊ฒฝ๊ณ : ์„œํ‚ท ๋ธŒ๋ ˆ์ด์ปค๋Š” ํ˜ธ์ถœ๋œ ์„œ๋น„์Šค์˜ ์ƒํƒœ๋ฅผ ๋ชจ๋‹ˆํ„ฐ๋งํ•˜๊ณ , ์„ฑ๋Šฅ์ด๋‚˜ ์žฅ์• ๊ฐ€ ๋ฐœ์ƒํ•  ๊ฒฝ์šฐ ๊ด€๋ฆฌ์ž์—๊ฒŒ ๊ฒฝ๊ณ ๋ฅผ ๋ณด๋‚ด๊ฑฐ๋‚˜ ๋ชจ๋‹ˆํ„ฐ๋ง ๋Œ€์‹œ๋ณด๋“œ๋ฅผ ํ†ตํ•ด ์‹ค์‹œ๊ฐ„์œผ๋กœ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•œ๋‹ค.

 

 

์„œํ‚ท ๋ธŒ๋ ˆ์ด์ปค์˜ 3๊ฐ€์ง€ ์ƒํƒœ

 

Open/Closed/ํ•˜ํ–ฅ๋œ ์ƒํƒœ (Open/Closed/ Half-Open States)

  • Open(์—ด๋ฆผ) ์ƒํƒœ: ์ผ์ • ์‹œ๊ฐ„ ๋™์•ˆ ์ง€์†์ ์œผ๋กœ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ํšŒ๋กœ๋ฅผ ์—ด์–ด์„œ ํ–ฅํ›„ ์š”์ฒญ์„ ์ฐจ๋‹จํ•œ๋‹ค.
  • Closed(๋‹ซํž˜) ์ƒํƒœ: ์„œ๋น„์Šค ํ˜ธ์ถœ์ด ์ •์ƒ์ ์œผ๋กœ ์ด๋ฃจ์–ด์ง€๋ฉด ํšŒ๋กœ๋ฅผ ๋‹ซ์•„์„œ ์š”์ฒญ์„ ํ—ˆ์šฉํ•œ๋‹ค.
  • Half-Open(ํ•˜ํ–ฅ๋œ) ์ƒํƒœ: ์ฃผ๊ธฐ์ ์œผ๋กœ ์ผ๋ถ€ ์š”์ฒญ์„ ์‹œ๋„ํ•˜์—ฌ ์„œ๋น„์Šค์˜ ์ƒํƒœ๋ฅผ ํ™•์ธํ•˜๊ณ , ๋ฌธ์ œ๊ฐ€ ์—†๋‹ค๋ฉด ๋‹ค์‹œ Closed ์ƒํƒœ๋กœ ์ „ํ™˜๋œ๋‹ค.

 


๊ทธ๋ ‡๋‹ค๋ฉด ํ”„๋กœ์ ํŠธ์— ์„œํ‚ท๋ธŒ๋ ˆ์ด์ปค๋ฅผ ์ ์šฉํ•  ๋ถ€๋ถ„์€ ์–ด๋””์ผ๊นŒ?

 

  1. ์™ธ๋ถ€ ์„œ๋น„์Šค(๋งˆ์ดํฌ๋กœ ์„œ๋น„์Šค๋‚˜ API) ํ˜ธ์ถœ
    • ์™ธ๋ถ€ ์„œ๋น„์Šค๊ฐ€ ์‘๋‹ตํ•˜์ง€ ์•Š๊ฑฐ๋‚˜ ์‘๋‹ต ์‹œ๊ฐ„์ด ์ง€์—ฐ๋˜๋Š” ๊ฒฝ์šฐ, ์„œํ‚ท ๋ธŒ๋ ˆ์ด์ปค๋Š” ํ•ด๋‹น ์„œ๋น„์Šค ํ˜ธ์ถœ์„ ์ค‘๋‹จํ•˜๊ณ  ๋น ๋ฅด๊ฒŒ ์‹คํŒจ ์‘๋‹ต์„ ๋ฐ˜ํ™˜ํ•˜์—ฌ ์ „์ฒด ์‹œ์Šคํ…œ์˜ ์•ˆ์ •์„ฑ์„ ์œ ์ง€ํ•œ๋‹ค. 
  2. ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ˜ธ์ถœ
    • ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์„œ๋ฒ„์— ๋Œ€ํ•œ ์—ฐ๊ฒฐ์ด ์‹คํŒจํ•˜๊ฑฐ๋‚˜ ์‘๋‹ต์ด ์ง€์—ฐ๋  ๋•Œ ์„œํ‚ท ๋ธŒ๋ ˆ์ด์ปค๊ฐ€ ํ•ด๋‹น ์—ฐ๊ฒฐ์„ ๋Š๊ณ  ๋Œ€์ฒด ๋กœ์ง์ด๋‚˜ ๊ธฐ๋ณธ๊ฐ’์„ ์‚ฌ์šฉํ•˜์—ฌ ์‹œ์Šคํ…œ์˜ ์ผ๊ด€์„ฑ์„ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค.
  3. ์™ธ๋ถ€ ๋ฆฌ์†Œ์Šค ์‚ฌ์šฉ (ํŒŒ์ผ ์‹œ์Šคํ…œ, ๋ฉ”์‹œ์ง€ ํ, ์™ธ๋ถ€ ์ €์žฅ์†Œ ๋“ฑ)

 


์„œํ‚ท๋ธŒ๋ ˆ์ด์ปค๋Š” ํ•ต์‚ฌ๊ณ ๋„ ์•„ํ‚คํ…์ฒ˜ ์ค‘ ์–ด๋””์— ์ ์šฉ์‹œ์ผœ์•ผํ• ๊นŒ?

 

Adapter/Application ์–ด๋””์—๋„ ์ ์šฉ๋˜์–ด๋„ ๊ดœ์ฐฎ์ง€๋งŒ ์ผ๋ฐ˜์ ์œผ๋กœ๋Š” ์™ธ๋ถ€ ์„œ๋น„์Šค ํ˜ธ์ถœ์ด๋‚˜ ๋ฐ์ดํ„ฐ ์†Œ์Šค์™€์˜ ํ†ตํ•ฉ ์ง€์ ์—์„œ ์„œํ‚ท ๋ธŒ๋ ˆ์ด์ปค๋ฅผ ์ ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ผ๋ฐ˜์ ์ด๋‹ค. 


๐Ÿ“Resilience4j - ์„œํ‚ท ๋ธŒ๋ ˆ์ด์ปค ์ ์šฉ

 

   spring cloud hystrix์—์„œ resilience4j ๋ฅผ ๋” ๋งŽ์ด ์“ฐ๊ธฐ ์‹œ์ž‘ํ–ˆ๋‹ค. ๋‹ค์Œ ๊ณผ์ •์€ Resilience4j๋ฅผ ํ”„๋กœ์ ํŠธ์— ์ ์šฉํ•ด๋ณด๋Š” ์ฝ”๋“œ์ด๋‹ค.

 

1. pom.xml์— ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ถ”๊ฐ€

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-circuitbreaker-resilience4j</artifactId>
            <version>2.1.7</version>
        </dependency>

 

 

2. ์˜์กด์„ฑ ์ฃผ์ž…

private final CircuitBreaker

 

 

3. ์„œํ‚ท ๋ธŒ๋ ˆ์ด์ปค๋ฅผ ์‚ฌ์šฉํ•  ์ฝ”๋“œ์— ๊ฐ์‹ธ์ค€๋‹ค. 

 

์„œํ‚ท ๋ธŒ๋ ˆ์ด์ปค ์ ์šฉ ์ „

@WebAdapter
@RequiredArgsConstructor
public class GetProductImageServiceAdapter implements GetProductImagePort {

    private final OpenFeignGetProductImages openFeignGetProductImages;
    
    @Override
    public List<ProductImage> getProductImagePort(Long id) {
		List<ProductImage> productImages = openFeignGetProductImages.call(id);
        return productImages;
    }
}

 

์„œํ‚ท ๋ธŒ๋ ˆ์ด์ปค ์ ์šฉ ํ›„

@WebAdapter
@RequiredArgsConstructor
public class GetProductImageServiceAdapter implements GetProductImagePort {

    private final OpenFeignGetProductImages openFeignGetProductImages;
    private final CircuitBreakerFactory circuitBreakerFactory;

    @Override
    public List<ProductImage> getProductImagePort(Long id) {
        CircuitBreaker circuitBreaker = circuitBreakerFactory.create("getProductImage");

        List<ProductImage> productImages = circuitBreaker.run(() ->
                openFeignGetProductImages.call(id)
                , throwable -> null
        );



        return productImages;
    }
}

 

๊ฐ์‹ผ ์ฝ”๋“œ๊ฐ€ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ์„œํ‚ท๋ธŒ๋ ˆ์ด์ปค๋ฅผ ์‹คํ–‰ํ•ด์„œ ๋ง‰๋„๋ก ์ž‘๋™ํ•œ๋‹ค.