스프링 클라우드 써킷 브레이커와 장애 격리 패턴

스프링 클라우드 써킷 브레이커란?

스프링 클라우드 써킷 브레이커는 분산 시스템에서 발생하는 장애에 대한 대응 방안으로 개발된 오픈소스 프레임워크입니다. 써킷 브레이커는 일종의 보호막으로, 각 서비스간의 호출을 모니터링하다가 호출 대상의 지연, 실패 등이 발생할 경우 해당 서비스 호출을 차단하고 대신 미리 정의된 행위(예를 들어 기본값 반환 등)를 수행합니다. 이를 통해 호출 대상 서비스의 장애로 인한 전체 시스템의 장애를 막을 수 있습니다.

써킷 브레이커는 스프링 클라우드 기반 서비스에서 사용 가능하며, 다양한 기능을 제공합니다. 가장 대표적으로는 써킷 브레이커를 통해 서비스 호출 실패 시 대응하는 Fallback 기능, 특정 호출에 대해 써킷 브레이커를 적용할지 말지를 결정하는 Route 기능 등이 있습니다.

장애 격리 패턴을 위한 스프링 클라우드 써킷 브레이커 구현 방법

스프링 클라우드 써킷 브레이커를 사용하기 위해서는 먼저 의존성을 추가해야 합니다. 스프링 부트 기반 프로젝트라면 다음과 같이 의존성을 추가할 수 있습니다.


  org.springframework.cloud
  spring-cloud-starter-circuitbreaker-resilience4j

써킷 브레이커를 사용하려면 우선 써킷 브레이커 객체를 생성해야 합니다. 스프링 클라우드에서는 써킷 브레이커 객체를 생성하기 위한 @CircuitBreaker 어노테이션을 제공합니다. 이 어노테이션을 메서드에 붙이면 해당 메서드가 써킷 브레이커로 래핑되어 호출됩니다.

@Service
public class MyService {
    @CircuitBreaker(name = "myCircuitBreaker")
    public String foo(String arg) {
        // ...
    }
}

@CircuitBreaker 어노테이션의 name 속성은 써킷 브레이커 객체의 이름을 지정합니다. 이름을 지정하지 않으면 메서드 이름이 써킷 브레이커 객체의 이름으로 사용됩니다.

써킷 브레이커 객체를 생성했다면 이제 써킷 브레이커가 적용될 호출 대상 메서드를 정의해야 합니다. 호출 대상 메서드는 실패할 가능성이 있는 코드 블록을 포함하고 있어야 합니다. 다음은 호출 대상 메서드의 예시입니다.

public String slowMethod(String arg) {
    try {
        Thread.sleep(5000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return "slow result";
}

이제 써킷 브레이커를 적용할 호출 대상 메서드를 @CircuitBreaker 어노테이션으로 감싸줍니다.

@Service
public class MyService {
    @CircuitBreaker(name = "myCircuitBreaker")
    public String slowMethod(String arg) {
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "slow result";
    }
}

이제 slowMethod 메서드를 호출할 때 써킷 브레이커가 적용됩니다. 써킷 브레이커가 호출 대상 메서드를 모니터링하다가 지정된 실패 횟수 이상의 호출 실패가 발생하면 써킷 브레이커가 차단됩니다.

스프링 클라우드 써킷 브레이커를 활용한 높은 가용성 구현

써킷 브레이커를 사용하면 분산 시스템에서 발생하는 장애에 대응할 수 있습니다. 이를 통해 시스템의 가용성을 높일 수 있습니다. 스프링 클라우드에서는 써킷 브레이커를 활용하여 높은 가용성을 구현할 수 있습니다.

예를 들어, 다음과 같은 상황을 가정해보겠습니다. 서비스 A가 서비스 B를 호출하는데, 서비스 B에 장애가 발생하여 호출이 실패하는 경우가 발생합니다. 이때, 서비스 A는 더 이상 서비스 B를 호출하지 않고 Fallback 메서드를 호출하도록 설정할 수 있습니다. 이를 통해 서비스 A는 서비스 B의 장애로 인한 영향을 최소화할 수 있습니다.

@Service
public class ServiceA {
    @Autowired
    private ServiceB serviceB;

    @CircuitBreaker(name = "serviceB", fallbackMethod = "fallback")
    public String callServiceB(String input) {
        return serviceB.doSomething(input);
    }

    public String fallback(String input, Throwable throwable) {
        // ...
    }
}

@Service
public class ServiceB {
    public String doSomething(String input) {
        // ...
    }
}

위 예제에서 ServiceAServiceB를 호출하는 callServiceB 메서드를 가지고 있습니다. callServiceB 메서드에 @CircuitBreaker 어노테이션을 사용하여 ServiceB에 써킷 브레이커를 적용하고, 호출 실패 시 fallback 메서드를 호출하도록 설정합니다.

ServiceB에서는 doSomething 메서드를 정의하여 실제로 수행할 작업을 구현합니다.

스프링 클라우드 써킷 브레이커의 장단점과 사용 사례

스프링 클라우드 써킷 브레이커를 사용하면 분산 시스템에서 발생하는 장애에 대응할 수 있습니다. 써킷 브레이커는 호출 대상 서비스의 장애로 인한 전체 시스템의 장애를 막을 수 있으며, Fallback 기능과 Route 기능을 통해 높은 가용성을 구현할 수 있습니다.

하지만 써킷 브레이커를 사용하면서 고려해야 할 몇 가지 단점도 있습니다. 먼저, 써킷 브레이커가 호출 대상 서비스를 차단할 때, 호출 대상 서비스의 부하가 더욱 증가할 수 있습니다. 이로 인해 호출 대상 서비스가 더욱 느려질 수 있습니다. 또한, 써킷 브레이커가 적용되는 서비스의 성능에도 영향을 미칠 수 있습니다.

스프링 클라우드 써킷 브레이커는 다양한 사용 사례가 있습니다. 예를 들어, 대기업에서는 수천 대의 서비스를 운영하고 있습니다. 이때, 각 서비스 간의 호출이 잦아지면서 호출 대상 서비스의 장애가 전체 시스템에 영향을 미치는 경우가 많습니다. 이런 경우에는 써킷 브레이커를 활용하여 전체 시스템의 가용성을 높일 수 있습니다.

또한, 써킷 브레이커는 마이크로서비스 아키텍처에서도 유용하게 사용될 수 있습니다. 마이크로서비스 아키텍처에서는 각 서비스가 독립적으로 운영되기 때문에 호출 대상 서비스의 장애가 다른 모든 서비스에 영향을 미치는 경우가 적습니다. 그러나 여러 서비스를 호출하면서 호출 대상 서비스의 장애로 인해 전체 시스템에 영향이 미치는 경우도 있습니다. 이런 경우에도 써킷 브레이커를 사용하여 가용성을 높일 수 있습니다.

결론

스프링 클라우드 써킷 브레이커는 분산 시스템에서 발생하는 장애에 대응하여 전체 시스템의 가용성을 높일 수 있는 오픈소스 프레임워크입니다. 써킷 브레이커를 사용하면 Fallback 기능과 Route 기능을 통해 높은 가용성을 구현할 수 있으며, 마이크로서비스 아키텍처에서도 유용하게 사용될 수 있습니다. 단, 써킷 브레이커를 사용하면서 고려해야 할 단점도 있으므로, 사용 시 주의가 필요합니다.