이 Google Cloud 아키텍처 프레임워크 문서에서는 고객 요구에 따라 오류를 허용하고 확장할 수 있도록 서비스를 설계하는 설계 원칙을 제공합니다. 안정적인 서비스에서는 서비스 수요가 많거나 유지보수 이벤트가 있을 때에도 고객 요청에 응답합니다. 다음과 같은 안정성 설계 원칙과 권장사항을 시스템 아키텍처 및 배포 계획에 포함해야 합니다.
가용성 증대를 위한 중복성 만들기
안정성이 높은 시스템에는 단일 장애점이 없어야 하며 리소스는 여러 장애 도메인에 걸쳐 복제되어야 합니다. 장애 도메인은 VM 인스턴스, 영역 또는 리전과 같이 독립적으로 실패할 수 있는 리소스 풀입니다. 장애 도메인 간 복제 시 개별 인스턴스보다 높은 집계 수준의 가용성을 얻을 수 있습니다. 자세한 내용은 리전 및 영역을 참조하세요.
시스템 아키텍처의 일부일 수 있는 중복성의 구체적인 예시로 DNS 등록 실패를 개별 영역으로 격리하려면 동일한 네트워크의 인스턴스들이 상호 액세스할 수 있도록 영역 DNS 이름을 사용합니다.
고가용성을 위한 장애 조치가 포함된 멀티 영역 아키텍처 설계
데이터 복제, 부하 분산, 영역 간 자동 장애 조치 기능을 통해 애플리케이션이 여러 영역에 분산된 리소스 풀을 사용하도록 설계하여 영역 장애에 대한 복원력이 우수하도록 합니다. 애플리케이션 스택의 모든 레이어에 대한 영역 복제본을 실행하고 아키텍처의 모든 영역 간 종속 항목을 삭제합니다.
재해 복구를 위해 리전 간 데이터 복제
리전 서비스 중단 또는 데이터 손실 시 재해 복구가 가능하도록 원격 리전에 데이터를 복제하거나 보관처리합니다. 복제 지연으로 인해 소량의 데이터가 손실될 수 있는 경우를 제외한다면 복제 사용 시 원격 리전의 스토리지 시스템에 이미 최신 데이터가 있으므로 복구 속도가 더 빠릅니다. 지속적 복제 대신 주기적인 보관처리를 사용하는 경우 재해 복구에 새 리전의 백업 또는 보관 파일에서 데이터를 복원하는 작업이 포함됩니다. 이 절차는 일반적으로 계속 업데이트되는 데이터베이스 복제본을 활성화할 때보다 서비스 다운타임이 길고, 연속된 백업 작업 사이의 시간 간격으로 인해 더 많은 데이터 손실이 발생할 수 있습니다. 어떤 접근 방식을 사용하든 전체 애플리케이션 스택을 다시 배포하여 새 리전에서 시작해야 하며 그동안에는 서비스를 사용할 수 없습니다.
재해 복구 개념 및 기법에 대한 자세한 내용은 클라우드 인프라 서비스 중단의 재해 복구 설계를 참조하세요.
리전 서비스 중단에 대한 복원력이 우수한 멀티 리전 아키텍처 설계
드물지만 전체 리전에 장애가 발생하더라도 서비스를 계속 실행해야 하는 경우 서비스가 여러 리전에 분산된 컴퓨팅 리소스 풀을 사용하도록 설계하세요. 애플리케이션 스택의 모든 레이어에 대한 리전 복제본을 실행합니다.
리전이 작동 중지될 때 리전 간 데이터 복제 및 자동 장애 조치를 사용합니다. 일부 Google Cloud 서비스에는 Spanner와 같은 멀티 리전 변형이 있습니다. 리전 장애로부터 복원력을 늘리기 위해서는 가능한 경우 디자인에 멀티 리전 서비스를 사용합니다. 리전 및 서비스 가용성에 대한 자세한 내용은 Google Cloud 위치를 참고하세요.
리전 수준 장애가 미치는 영향의 범위가 해당 리전으로 제한되도록 리전 간 종속 항목이 없는지 확인합니다.
연결할 수 없을 때 전역 서비스 중단을 초래할 수 있는 단일 리전 기본 데이터베이스와 같은 리전 단일 장애점을 제거합니다. 멀티 리전 아키텍처는 비용이 많이 드는 경우가 많으므로 이 접근 방식을 채택하기 전에 비용과 비즈니스 요구를 비교하여 고려하세요.
장애 도메인 간 중복성 구현에 대한 자세한 지침은 클라우드 애플리케이션을 위한 배포 Archetype(PDF) 문서를 참조하세요.
확장성 병목 현상 제거
단일 VM 또는 단일 영역의 리소스 한도를 초과해서는 안 되는 시스템 구성요소를 식별합니다. 부하 증가를 처리하기 위해 단일 VM 인스턴스에 CPU 코어, 메모리 또는 네트워크 대역폭을 추가하여 수직 확장되는 애플리케이션도 있습니다. 이러한 애플리케이션은 확장성이 엄격하게 제한되어 증가를 처리하도록 수동으로 구성해야 하는 경우가 많습니다.
가능한 경우 VM 또는 영역에서 샤딩 또는 파티션 나누기 등을 사용해 수평 확장이 가능하도록 구성요소를 재설계합니다. 샤드를 추가하여 트래픽 또는 사용량 증가를 처리할 수 있습니다. 자동으로 추가되는 표준 VM 유형을 사용하면 샤드당 부하의 증가를 처리할 수 있습니다. 자세한 내용은 확장 가능하고 복원력이 우수한 앱 패턴을 참조하세요.
애플리케이션을 다시 설계할 수 없는 경우 사용자가 관리하는 구성요소를 사용자 작업 없이 수평 확장되도록 설계된 완전 관리형 클라우드 서비스로 바꿀 수 있습니다.
과부하 발생 시 단계적으로 서비스 수준 저하
과부하를 허용하도록 서비스를 설계합니다. 서비스에서 과부하를 감지하고 사용자에게 낮은 품질의 응답을 반환하거나 과부하로 인해 완전히 실패하지 않게 트래픽을 부분적으로 삭제해야 합니다.
예를 들어 서비스에서 정적 웹 페이지를 통해 사용자 요청에 응답하고 처리하는 데 비용이 많이 드는 동적 동작을 일시적으로 사용 중지할 수 있습니다. 또는 읽기 전용 작업을 허용하고 데이터 업데이트를 일시적으로 사용 중지할 수 있습니다
서비스가 저하되면 오류 조건을 수정하라는 알림이 운영자에게 전달되어야 합니다.
트래픽 급증을 방지하고 완화하기
클라이언트 간 요청을 동기화하지 마세요. 동일한 인스턴스에서 트래픽을 보내는 클라이언트가 너무 많으면 트래픽이 급증하여 연쇄적 장애가 발생할 수 있습니다.
서버 측에 제한, 큐에 추가, 부하 차단, 회로 차단, 단계적 성능 저하, 중요 요청 우선순위 지정과 같은 급증 완화 전략을 구현합니다.
클라이언트의 완화 전략에는 클라이언트 측 제한과 지터를 사용한 지수 백오프가 포함됩니다.
입력 내용 삭제 및 유효성 검사
서비스 중단 또는 보안 침해를 야기하는 오류, 무작위 또는 악의적 입력을 방지하려면 API 및 운영 도구에 대한 입력 매개변수를 삭제하고 검사합니다. 예를 들어 Apigee와 Google Cloud Armor가 삽입 공격으로부터 보호하는 데 도움이 될 수 있습니다.
테스트 하네스가 의도적으로 무작위 입력, 비어 있는 입력, 너무 큰 입력으로 API를 호출하는 퍼즈 테스트를 정기적으로 사용합니다. 이러한 테스트는 격리된 테스트 환경에서 수행합니다.
변경사항을 적용하기 전에 운영 도구에서 자동으로 구성 변경사항을 검증하고 검증에 실패하면 변경사항을 거부해야 합니다.
작동이 지속되는 안전 장치
문제로 인해 오류가 발생한 경우 전체 시스템이 계속 작동할 수 있는 방식으로 시스템 구성요소에 장애가 발생해야 합니다. 이러한 문제는 소프트웨어 버그, 잘못된 입력 또는 구성, 계획되지 않은 인스턴스 중단 또는 작업자 오류일 수 있습니다. 서비스가 처리하는 작업은 지나치게 제한적이지 않고 오히려 지나치게 권한이 많거나, 지나치게 단순해야 하는지 여부를 확인하는 데 도움이 됩니다.
다음 예시 시나리오와 실패에 대응하는 방법을 고려하세요.
- 일반적으로 구성이 잘못되거나 비어 있는 방화벽 구성요소의 경우 오류 시 허용을 적용하고 운영자가 오류를 해결하는 동안 승인되지 않은 네트워크 트래픽이 단시간 통과할 수 있도록 하는 것이 좋습니다. 이 동작은 오류 시 종료하고 트래픽을 100% 차단하는 대신 서비스를 계속 사용할 수 있도록 합니다. 서비스에서 모든 트래픽이 통과하는 동안 민감한 영역을 보호하기 위해 애플리케이션 스택의 더 깊은 수준까지 인증 및 승인 확인을 사용해야 합니다.
- 하지만 사용자 데이터에 대한 액세스를 제어하는 권한 서버 구성요소는 오류 시 종료하여 모든 액세스를 차단하는 것이 좋습니다. 이 동작으로 인해 구성이 손상되면 서비스 중단이 발생하지만 오류 시 허용일 때의 기밀 사용자 데이터 유출 위험을 피할 수 있습니다.
두 경우 모두 운영자가 오류 조건을 해결할 수 있도록 장애 시 높은 우선순위의 알림이 발생해야 합니다. 비즈니스에 심각한 위험을 초래하지 않는 한, 서비스 구성요소에 오류 시 허용을 적용해야 합니다.
재시도할 수 있도록 API 호출 및 작업 명령어 설계
API 및 운영 도구에서 최대한 안전하게 호출을 재시도할 수 있어야 합니다. 여러 오류 조건에 대한 자연스러운 접근 방식은 이전 작업을 다시 시도하는 것이지만 첫 시도가 성공했는지 모를 수 있습니다.
시스템 아키텍처는 작업이 멱등성을 갖도록 해야 합니다. 즉, 객체에 대해 동일한 작업을 두 번 이상 연속적으로 실행하면 단일 호출과 동일한 결과가 생성됩니다. 비멱등성 작업에는 시스템 상태의 손상을 방지하기 위해 더 복잡한 코드가 필요합니다.
서비스 종속 항목 식별 및 관리
서비스 설계자와 소유자가 다른 시스템 구성요소의 종속 항목에 관한 전체 목록을 유지해야 합니다. 또한 서비스 설계에는 종속 항목 오류 복구 또는 전체 복구가 불가능한 경우 단계적 성능 저하가 포함되어야 합니다. 모든 시스템 종속 항목의 실패율이 0이 아님을 인식하고, 시스템에서 사용하는 클라우드 서비스 및 타사 서비스 API와 같은 외부 종속 항목을 고려합니다.
안정성 목표를 설정할 때 서비스의 SLO가 모든 중요한 종속 항목의 SLO에 따라 수학적으로 제한된다는 것을 인식합니다. 종속 항목 중 하나의 최저 SLO보다 안정적일 수는 없습니다. 자세한 내용은 서비스 가용성의 미적분을 참조하세요.
시작 종속 항목
서비스는 안정 상태 동작과 달리 시작 시 다르게 작동합니다. 시작 종속 항목은 안정 상태의 런타임 종속 항목과 상당히 다를 수 있습니다.
예를 들어 서비스가 시작할 때 다시 호출할 일이 거의 없는 사용자 메타데이터 서비스에서 사용자 또는 계정 정보를 로드해야 할 수 있습니다. 비정상 종료나 정기 유지보수 후에 다시 시작되는 서비스 복제본이 많으면 특히 캐시가 비어 있어 다시 채워야 하는 경우 복제본으로 인해 시작 종속 항목의 부하가 급증할 수 있습니다.
로드 시 서비스 시작을 테스트하고 그에 맞게 시작 종속 항목을 프로비저닝합니다. 중요 시작 종속 항목에서 검색하는 데이터 복사본을 저장하여 단계적으로 성능 저하가 발생하도록 디자인을 고려합니다. 이 동작은 중요 종속 항목에 중단이 발생할 때 서비스가 시작되지 않는 것이 아니라 잠재적으로 오래된 데이터를 사용해서 서비스가 다시 시작될 수 있도록 합니다. 서비스는 나중에 가능하면 새 데이터를 로드하여 정상 작동 상태로 돌아갈 수 있습니다.
시작 종속 항목은 또한 새 환경에서 서비스를 부트스트랩할 때 중요합니다. 레이어 간 순환 종속 항목 없이 계층형 아키텍처로 애플리케이션 스택을 디자인합니다. 순환 종속 항목은 단일 애플리케이션에 대해 증분적인 변경을 차단하지 않기 때문에 용인되는 것으로 보일 수 있습니다. 하지만 순환 종속 항목은 재해로 인해 전체 서비스 스택이 중단된 이후 다시 시작하는 것을 어렵거나 불가능하게 만들 수 있습니다.
중요한 종속 항목 최소화
서비스에 중요한 종속 항목, 즉 장애가 발생하여 서비스가 중단되는 원인이 되는 다른 구성요소를 최소화합니다. 사용하는 다른 구성요소의 장애 또는 속도 저하에 대한 복원력이 우수한 서비스를 만들려면 다음과 같은 설계 기법 및 원칙을 사용하여 중요한 종속 항목을 중요하지 않은 종속 항목으로 변환합니다.
- 중요한 종속 항목의 중복 수준을 높입니다. 복제본을 더 추가하면 전체 구성요소를 사용할 수 없게 될 가능성이 낮습니다.
- 응답을 차단하는 대신 다른 서비스에 대한 비동기식 요청을 사용하거나 게시/구독 메시지를 사용하여 응답에서 요청을 분리합니다.
- 단기적으로 사용할 수 없게 된 종속 항목을 복구하기 위해 다른 서비스의 응답을 캐시합니다.
서비스 장애 또는 속도 저하를 종속된 다른 구성요소에 피해가 덜 가는 방식으로 렌더링하려면 다음 설계 기법 및 원칙을 고려하세요.
- 우선순위가 지정된 요청 큐를 사용하고 사용자가 응답을 기다리는 요청에 더 높은 우선순위를 부여합니다.
- 캐시에서 응답을 제공하여 지연 시간과 부하를 줄입니다.
- 작동이 지속되는 안전 장치를 마련합니다.
- 트래픽 과부하가 발생하면 성능이 단계적으로 저하되도록 합니다.
모든 변경 사항을 롤백 가능한지 확인
서비스에 대해 특정 유형의 변경사항을 실행 취소할 수 있는 잘 정의된 방법이 없으면 롤백을 지원하도록 서비스 디자인을 변경합니다. 주기적으로 롤백 프로세스를 테스트합니다. 각 구성요소 또는 마이크로서비스의 API 버전을 관리하고, API가 발전하더라도 이전 세대의 클라이언트가 계속 올바르게 작동하도록 하위 호환성을 지원해야 합니다. 이러한 디자인 원칙은 필요에 따라 빠른 롤백을 지원하고 API 변경사항의 점진적 롤아웃을 허용하기 위해 중요합니다.
롤백은 모바일 애플리케이션에 구현하는 데 비용이 많이 들 수 있습니다. Firebase 원격 구성은 기능을 손쉽게 롤백할 수 있는 Google Cloud 서비스입니다.
데이터베이스 스키마 변경사항을 즉시 롤백할 수는 없으므로, 이를 여러 단계에 걸쳐 실행해야 합니다. 애플리케이션의 최신 버전 및 이전 버전에서 안전한 스키마 읽기 및 업데이트 요청을 허용하도록 각 단계를 디자인합니다. 이러한 디자인 방식을 사용하면 최신 버전에 문제가 있을 때 안전하게 롤백할 수 있습니다.
권장사항
아키텍처 프레임워크의 안내 사항을 사용자의 고유 환경에 적용하려면 다음 권장사항을 따르세요.
- 클라이언트 애플리케이션의 오류 재시도 로직에서 무작위 순서 지정으로 지수 백오프를 구현합니다.
- 높은 가용성을 위해 자동 장애 조치가 포함된 멀티 리전 아키텍처를 구현합니다.
- 부하 분산을 사용하여 샤드와 리전 전체에 사용자 요청을 분산합니다.
- 과부하 시 성능이 단계적으로 저하되도록 애플리케이션을 설계합니다. 완전히 실패하는 대신 부분 응답을 제공하거나 제한된 기능을 제공합니다.
- 용량 계획을 위해 데이터 중심의 프로세스를 설정하고 로드 테스트 및 트래픽 예측을 사용해서 리소스 프로비저닝 시기를 결정합니다.
- 재해 복구 절차를 수립하고 주기적으로 테스트합니다.
다음 단계
- 안정적인 운영 프로세스 및 도구 만들기(이 시리즈의 다음 문서)
- 아키텍처 프레임워크의 다른 요소에서 권장사항 살펴보기