회로 차단기 패턴 - AWS 규범적 지침

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

회로 차단기 패턴

의도

회로 차단기 패턴을 사용하면 이전에 반복적으로 시간 초과나 장애가 발생한 경우 발신자 서비스가 다른 서비스 (수신자) 로 통화를 재시도하는 것을 방지할 수 있습니다. 또한 이 패턴은 수신자 서비스가 언제 다시 작동하는지를 감지하는 데에도 사용됩니다.

목적

여러 마이크로서비스가 협업하여 요청을 처리하면 하나 이상의 서비스를 사용할 수 없게 되거나 지연 시간이 길어질 수 있습니다. 복잡한 애플리케이션이 마이크로서비스를 사용하는 경우 한 마이크로서비스가 중단되면 애플리케이션 장애가 발생할 수 있습니다. 마이크로서비스는 원격 프로시저 호출을 통해 통신하므로 네트워크 연결에서 일시적인 오류가 발생하여 장애가 발생할 수 있습니다. (일시적 오류는 백오프 패턴을 사용한 재시도를 사용하여 처리할 수 있습니다.) 동기 실행 중에 연속적인 시간 초과나 실패로 인해 사용자 경험이 저하될 수 있습니다.

그러나 일부 상황에서는 장애를 해결하는 데 시간이 더 오래 걸릴 수 있습니다. 예를 들어 수신자 서비스가 중단되거나 데이터베이스 경합으로 인해 시간 초과가 발생하는 경우 등이 있습니다. 이러한 경우 호출 서비스가 호출을 반복적으로 재시도하면 이러한 재시도로 인해 네트워크 경합이 발생하고 데이터베이스 스레드 풀이 소비될 수 있습니다. 또한 여러 사용자가 응용 프로그램을 반복해서 다시 시도하면 문제가 악화되고 전체 응용 프로그램의 성능이 저하될 수 있습니다.

회로 차단기 패턴은 마이클 니가르드가 그의 저서 Release It (Nygard 2018) 에서 널리 퍼뜨린 것입니다. 이 디자인 패턴은 발신자 서비스가 이전에 반복적으로 시간 초과나 실패를 일으킨 서비스 호출을 재시도하는 것을 방지할 수 있습니다. 또한 수신자 서비스가 언제 다시 작동하는지 감지할 수 있습니다.

회로 차단기 개체는 회로에 이상이 있을 때 자동으로 전류를 차단하는 전기 회로 차단기처럼 작동합니다. 전기 회로 차단기는 고장 발생 시 전류 흐름을 차단하거나 끊어냅니다. 마찬가지로 회로 차단기 오브젝트는 발신자와 수신자 서비스 사이에 위치하며 수신자를 사용할 수 없는 경우 트립됩니다.

분산 컴퓨팅의 오류는 피터 도이치 (Peter Deutsch) 와 Sun Microsystems의 다른 직원들이 주장한 일련의 주장입니다. 분산 응용 프로그램을 처음 접하는 프로그래머는 항상 잘못된 가정을 한다고 합니다. 네트워크 안정성, 제로 레이턴시 기대, 대역폭 제한으로 인해 소프트웨어 애플리케이션은 네트워크 오류에 대한 최소한의 오류 처리로 작성됩니다.

네트워크가 중단되는 동안 애플리케이션은 응답을 무기한으로 기다려 애플리케이션 리소스를 지속적으로 소비할 수 있습니다. 네트워크를 사용할 수 있게 되었을 때 작업을 재시도하지 않으면 응용 프로그램 성능이 저하될 수도 있습니다. 네트워크 문제로 인해 데이터베이스 또는 외부 서비스에 대한 API 호출 제한 시간이 초과되면 회로 차단기 없이 반복적으로 호출하면 비용과 성능에 영향을 미칠 수 있습니다.

적용 가능성

다음과 같은 경우에 이 패턴을 사용하십시오.

  • 발신자 서비스가 전화를 걸지만 실패할 가능성이 높습니다.

  • 수신자 서비스의 지연 시간이 길면 (예: 데이터베이스 연결 속도가 느린 경우) 수신자 서비스에 대한 제한 시간이 초과됩니다.

  • 발신자 서비스가 동기적으로 전화를 걸지만 수신자 서비스를 사용할 수 없거나 대기 시간이 깁니다.

문제 및 고려 사항

  • 서비스에 구애받지 않는 구현: 코드 팽창을 방지하려면 마이크로서비스에 구애받지 않고 마이크로서비스에 구애받지 않는 방식으로 회로 차단기 개체를 구현하는 것이 좋습니다. API

  • 수신자별 회로 폐쇄: 피호출자가 성능 문제 또는 장애에서 복구되면 회로 상태를 로 업데이트할 수 있습니다. CLOSED 이는 회로 차단기 패턴의 확장으로, 복구 시간 목표 () RTO 에서 요구하는 경우 구현할 수 있습니다.

  • 멀티스레드 통화: 만료 제한 시간 값은 서비스 가용성을 확인하기 위해 통화가 다시 라우팅되기 전까지 회로가 트립된 상태로 유지되는 기간으로 정의됩니다. 피호출자 서비스가 여러 스레드에서 호출되는 경우, 실패한 첫 번째 호출이 만료 타임아웃 값을 정의합니다. 구현시 후속 호출로 인해 만료 제한 시간이 끝없이 바뀌지 않도록 해야 합니다.

  • 회로 강제 개설 또는 폐쇄: 시스템 관리자는 회로를 열거나 닫을 수 있어야 합니다. 데이터베이스 테이블의 만료 제한 시간 값을 업데이트하여 이 작업을 수행할 수 있습니다.

  • 관찰 가능성: 회로 차단기가 열려 있을 때 실패하는 호출을 식별할 수 있도록 응용 프로그램에 로깅을 설정해야 합니다.

구현

전반적인 아키텍처

다음 예제에서 발신자는 주문 서비스이고 수신자는 결제 서비스입니다.

장애가 없는 경우 주문 서비스는 다음 다이어그램과 같이 회로 차단기를 통해 모든 통화를 결제 서비스로 라우팅합니다.

장애가 없는 회로 차단기 패턴.

결제 서비스 제한 시간이 초과되면 회로 차단기가 시간 초과를 감지하고 장애를 추적할 수 있습니다.

결제 서비스 실패로 인한 회로 차단기.

제한 시간이 지정된 임계값을 초과하면 응용 프로그램이 회로를 엽니다. 회로가 열려 있는 경우 회로 차단기 객체는 통화를 결제 서비스로 라우팅하지 않습니다. 주문 서비스가 결제 서비스에 전화를 걸면 즉시 실패를 반환합니다.

서킷 브레이커는 결제 서비스로의 라우팅을 중단합니다.

서킷 브레이커 객체는 주기적으로 결제 서비스에 대한 호출이 성공했는지 확인하려고 합니다.

서킷 브레이커는 주기적으로 결제 서비스를 재시도합니다.

결제 서비스 호출이 성공하면 회로가 닫히고 이후의 모든 통화는 결제 서비스로 다시 라우팅됩니다.

결제 서비스가 작동하는 서킷 브레이커.

서비스를 이용한 AWS 구현

샘플 솔루션은 고속 워크플로를 사용하여 회로 차단기 패턴을 구현합니다. AWS Step Functions Step Functions 상태 머신을 사용하면 패턴 구현에 필요한 재시도 기능 및 의사 결정 기반 제어 흐름을 구성할 수 있습니다.

또한 이 솔루션은 Amazon DynamoDB 테이블을 데이터 스토어로 사용하여 회로 상태를 추적합니다. 성능 향상을 위해 Amazon ElastiCache (RedisOSS) 과 같은 인메모리 데이터스토어로 대체할 수 있습니다.

서비스가 다른 서비스를 호출하려는 경우 수신자 서비스의 이름으로 워크플로를 시작합니다. 워크플로는 현재 성능이 저하된 서비스를 저장하는 CircuitStatus DynamoDB 테이블에서 회로 차단기 상태를 가져옵니다. 피호출자에 대한 만료되지 않은 레코드가 CircuitStatus 포함된 경우 회로는 열려 있습니다. Step Functions 워크플로는 즉각적인 실패를 반환하고 FAIL 상태와 함께 종료됩니다.

CircuitStatus테이블에 피호출자에 대한 레코드가 없거나 만료된 레코드가 포함되어 있는 경우 서비스는 작동 가능합니다. 상태 머신 정의의 ExecuteLambda 단계는 파라미터 값을 통해 전송된 Lambda 함수를 호출합니다. 호출이 성공하면 Step Functions 워크플로가 상태와 함께 종료됩니다. SUCCESS

AWS Step Functions 및 DynamoDB를 사용한 회로 차단기 구현

서비스 호출이 실패하거나 타임아웃이 발생하는 경우 애플리케이션은 정의된 횟수만큼 지수 백오프를 사용하여 재시도합니다. 재시도 후 서비스 호출이 실패하면 워크플로는 an이 있는 서비스의 CircuitStatus 테이블에 레코드를 삽입하고 워크플로우는 상태와 함께 ExpiryTimeStamp 종료됩니다. FAIL 이후에 동일한 서비스를 호출하면 회로 차단기가 열려 있는 한 즉시 오류가 발생합니다. 스테이트 머신 정의의 Get Circuit Status 단계에서는 ExpiryTimeStamp 값을 기반으로 서비스 가용성을 확인합니다. 만료된 항목은 DynamoDB timeto live () 기능을 사용하여 CircuitStatus 테이블에서 삭제됩니다. TTL

샘플 코드

다음 코드는 GetCircuitStatus Lambda 함수를 사용하여 회로 차단기 상태를 확인합니다.

var serviceDetails = _dbContext.QueryAsync<CircuitBreaker>(serviceName, QueryOperator.GreaterThan, new List<object> {currentTimeStamp}).GetRemainingAsync(); if (serviceDetails.Result.Count > 0) { functionData.CircuitStatus = serviceDetails.Result[0].CircuitStatus; } else { functionData.CircuitStatus = ""; }

다음 코드는 Step Functions 워크플로의 Amazon States 언어 명령문을 보여줍니다.

"Is Circuit Closed": { "Type": "Choice", "Choices": [ { "Variable": "$.CircuitStatus", "StringEquals": "OPEN", "Next": "Circuit Open" }, { "Variable": "$.CircuitStatus", "StringEquals": "", "Next": "Execute Lambda" } ] }, "Circuit Open": { "Type": "Fail" }

GitHub 리포지토리

이 패턴의 샘플 아키텍처를 완전히 구현하려면 의 GitHub 저장소를 참조하십시오 https://github.com/aws-samples/circuit-breaker-netcore-blog.

블로그 참조

관련 콘텐츠