Reliable Services 수명 주기 개요

Azure Service Fabric Reliable Services의 수명 주기를 고려할 경우 수명 주기에 대한 기본 사항이 가장 중요합니다. 일반적으로 수명 주기는 다음과 같습니다.

  • 시작 중:
    • 서비스가 생성됩니다.
    • 서비스는 0개 이상의 수신기를 생성하고 반환할 수 있습니다.
    • 반환된 모든 수신기가 열리면 서비스와의 통신이 가능합니다.
    • 서비스의 RunAsync 메서드를 호출하면 서비스가 장기 실행 중인 작업 또는 백그라운드 작업을 수행할 수 있습니다.
  • 종료 중:
    • RunAsync에 전달된 취소 토큰이 취소되고 수신기 닫힙니다.
    • 수신기가 닫히면 서비스 개체 자체는 소멸됩니다.

이러한 이벤트의 정확한 순서에 대한 세부 정보가 있습니다. 이벤트의 순서는 Reliable Service가 상태 비저장인지 또는 상태 저장인지에 따라 약간 변경될 수 있습니다. 또한 상태 저장 서비스의 경우 주 복제본 교환 시나리오를 처리해야 합니다. 이 과정 중에 서비스를 종료하지 않고 주 복제본의 역할을 다른 복제본으로 전송하거나 복구합니다. 마지막으로 오류 또는 실패 조건에 대해 고려해야 합니다.

상태 비저장 서비스 시작

상태 비저장 서비스의 수명 주기는 간단합니다. 이벤트의 순서는 다음과 같습니다.

  1. 서비스가 생성됩니다.
  2. StatelessService.CreateServiceInstanceListeners()가 호출되고 반환된 모든 수신기가 열립니다. ICommunicationListener.OpenAsync()가 각 수신기에서 호출됩니다.
  3. 그런 후 다음 두 가지 작업이 동시에 수행됩니다.
    • 서비스의 StatelessService.RunAsync() 메서드가 호출됩니다.
    • 있는 경우 서비스의 StatelessService.OnOpenAsync() 메서드가 호출됩니다. 이 호출은 일반적이지 않은 재정의이지만 사용 가능합니다. 이때 확장된 서비스 초기화 작업을 시작할 수 있습니다.

상태 비저장 서비스 종료

상태 비저장 서비스를 종료할 경우 동일한 패턴이 역방향으로 다음과 같이 따라옵니다.

  1. 열려 있는 수신기가 모두 닫힙니다. ICommunicationListener.CloseAsync()가 각 수신기에서 호출됩니다.
  2. RunAsync()에 전달된 취소 토큰이 취소됩니다. 취소 토큰의 IsCancellationRequested 속성을 확인하면 true를 반환하고, 호출되는 경우 토큰의 ThrowIfCancellationRequested 메서드에서 OperationCanceledException이 발생됩니다. Service Fabric은 RunAsync()가 완료되기를 기다립니다.
  3. RunAsync()가 완료된 후 서비스의 StatelessService.OnCloseAsync() 메서드가 호출됩니다(제공된 경우). 상태 비저장 서비스 인스턴스가 정상적으로 종료되려고 할 때 OnCloseAsync가 호출됩니다. 이는 서비스의 코드를 업그레이드할 때, 로드 균형 조정으로 인해 서비스 인스턴스가 이동할 때 또는 일시적인 오류가 감지되었을 때 발생할 수 있습니다. StatelessService.OnCloseAsync() 재정의는 일반적이지 않지만 리소스를 안전하게 닫거나 백그라운드 프로세스를 중지하거나 외부 상태 저장을 완료하거나 기존 연결을 종료하는 데 사용할 수 있습니다.
  4. StatelessService.OnCloseAsync()이 완료되면 서비스 개체는 소멸됩니다.

상태 저장 서비스 시작

상태 저장 서비스는 몇 가지를 변경한 상태 비저장 서비스 패턴과 비슷합니다. 상태 저장 서비스를 시작하면 이벤트의 순서는 다음과 같습니다.

  1. 서비스가 생성됩니다.

  2. StatefulServiceBase.OnOpenAsync()을 호출합니다. 이 호출은 서비스에서 드물게 재정의됩니다.

  3. StatefulServiceBase.CreateServiceReplicaListeners()가 호출됩니다.

    • 서비스가 주 서비스인 경우 반환된 모든 수신기가 열립니다. ICommunicationListener.OpenAsync()가 각 수신기에서 호출됩니다.
    • 서비스가 보조 서비스인 경우 ListenOnSecondary = true로 표시된 수신기만 열립니다. 보조 복제본에서 수신기가 열려 있는 경우는 일반적이지 않습니다.
  4. 그런 다음, 병렬로:

    • 서비스가 현재 주 서비스인 경우 서비스의 StatefulServiceBase.RunAsync() 메서드가 호출됩니다.
    • StatefulServiceBase.OnChangeRoleAsync()을 호출합니다. 이 호출은 서비스에서 드물게 재정의됩니다.

    참고 항목

    새 보조 복제본의 경우 StatefulServiceBase.OnChangeRoleAsync()가 두 번 호출됩니다. 2단계 이후 한 번, 유휴 보조가 되면 4단계에서 다시 활성 보조가 됩니다. 복제본 및 인스턴스 수명 주기에 대한 자세한 내용은 복제본 및 인스턴스 수명 주기를 참조하세요.

상태 저장 서비스 종료

상태 비저장 서비스와 마찬가지로 종료 중 수명 주기 이벤트는 시작 시와 동일하지만 역방향으로 이뤄집니다. 상태 저장 서비스가 종료되면 다음과 같은 이벤트가 발생합니다.

  1. 열려 있는 수신기가 모두 닫힙니다. ICommunicationListener.CloseAsync()가 각 수신기에서 호출됩니다.

  2. StatefulServiceBase.OnCloseAsync() 메서드가 호출됩니다. 이 호출은 일반적이지 않은 재정의이지만 사용 가능합니다.

  3. RunAsync()에 전달된 취소 토큰이 취소됩니다. 취소 토큰의 IsCancellationRequested 속성을 확인하면 true를 반환하고, 호출되는 경우 토큰의 ThrowIfCancellationRequested 메서드에서 OperationCanceledException이 발생됩니다. Service Fabric은 RunAsync()가 완료되기를 기다립니다.

    참고 항목

    RunAsync가 완료될 때까지 기다려야 하는 경우는 이 복제본이 주 복제본인 경우 뿐입니다.

  4. StatefulServiceBase.RunAsync()이 완료되면 서비스 개체는 소멸됩니다.

상태 저장 서비스 주 교환

상태 저장 서비스가 실행되는 동안 해당 상태 저장 서비스의 주 복제본은 해당 통신 수신기를 열고 해당 RunAsync 메서드를 호출합니다. 보조 복제본을 생성하지만 더 이상 호출하지 않습니다. 장애 또는 클러스터 균형 조정 최적화의 결과로 상태 저장 서비스가 실행되는 동안 현재 주 복제본인 복제본을 변경할 수 있습니다. 복제본이 확인할 수 있는 수명 주기 이벤트의 측면에서 무슨 의미인가요? 상태 저장 복제본이 확인하는 동작은 강등되는 복제본인지 승격되는 복제본인지에 따라 달라 집니다.

강등되는 주 복제본의 경우

강등되는 주 복제본의 경우 Service Fabric은 이 복제본에서 메시지 처리를 중지하고 수행 중인 모든 백그라운드 작업을 종료하도록 합니다. 결과적으로 이 단계는 서비스가 종료될 경우와 유사합니다. 한 가지 차이점은 서비스가 보조 복제본으로 그대로 남아 있으므로 소멸되거나 종료되지 않는다는 점입니다. 다음 API가 호출됩니다.

  1. 열려 있는 수신기가 모두 닫힙니다. ICommunicationListener.CloseAsync()가 각 수신기에서 호출됩니다.
  2. RunAsync()에 전달된 취소 토큰이 취소됩니다. 취소 토큰의 IsCancellationRequested 속성을 확인하면 true를 반환하고, 호출되는 경우 토큰의 ThrowIfCancellationRequested 메서드에서 OperationCanceledException이 발생됩니다. Service Fabric은 RunAsync()가 완료되기를 기다립니다.
  3. ListenOnSecondary = true로 표시된 수신기가 열립니다.
  4. 서비스의 StatefulServiceBase.OnChangeRoleAsync()가 호출됩니다. 이 호출은 서비스에서 드물게 재정의됩니다.

승격되는 보조 복제본의 경우

마찬가지로 Service Fabric에서 통신 중에 메시지에 대한 수신 대기를 시작하고, 관심 있는 모든 백그라운드 작업을 시작하기 위해 승격되는 보조 복제본이 필요합니다. 결과적으로 이 프로세스는 복제본 자체가 이미 존재한다는 점을 제외하면 서비스를 만들 때와 유사합니다. 다음 API가 호출됩니다.

  1. ICommunicationListener.CloseAsync()는 열려 있는 모든 수신기에 대해 호출됩니다(ListenOnSecondary = true로 표시됨).
  2. 모든 통신 수신기가 열립니다. ICommunicationListener.OpenAsync()가 각 수신기에서 호출됩니다.
  3. 그런 다음, 동시에 다음이 수행됩니다.
    • 서비스의 StatefulServiceBase.RunAsync() 메서드가 호출됩니다.
    • StatefulServiceBase.OnChangeRoleAsync()을 호출합니다. 이 호출은 서비스에서 드물게 재정의됩니다.

참고 항목

CreateServiceReplicaListeners는 한 번만 호출되며 복제본 승격 또는 강등 프로세스 중에 다시 호출되지 않습니다. 동일한 ServiceReplicaListener 인스턴스가 사용되지만 이전 인스턴스가 닫힌 후 ServiceReplicaListener.CreateCommunicationListener 메서드를 호출하여 새 ICommunicationListener 인스턴스가 만들어집니다.

상태 저장 서비스 종료 및 기본 수준 내리기 동안의 일반적인 문제

Service Fabric에서는 다양한 이유로 상태 저장 서비스에 대한 주 복제본을 변경합니다. 가장 일반적인 것은 클러스터 재분산애플리케이션 업그레이드입니다. 이러한 작업 동안(서비스가 삭제되었는지 확인하는 경우처럼 정상적인 서비스 종료 동안에도) 서비스에서 CancellationToken을 준수하는 것이 중요합니다.

취소를 완전히 처리하지 않는 서비스에는 몇 가지 문제가 발생합니다. Service Fabric에서 서비스가 정상적으로 중지되기를 기다리기 때문에 이러한 작업이 느려질 수 있습니다. 이로 인해 궁극적으로 시간이 초과되고 롤백하게 되는 실패한 업그레이드로 이어질 수 있습니다. 취소 토큰을 사용하지 않으면 클러스터가 분산되지 않을 수도 있습니다. 클러스터가 핫 노드가 되어 분산되지 않게 되지만 다른 곳으로 이동하는 데 시간이 너무 오래 걸리므로 서비스를 다시 분산할 수 없습니다.

서비스가 상태 저장 서비스이므로 신뢰할 수 있는 컬렉션을 사용하고 있을 가능성이 큽니다. Service Fabric에서 주 복제본이 강등될 때 가장 먼저 발생하는 상황 중 하나는 기본 상태에 대한 쓰기 액세스가 철회된다는 것입니다. 이로 인해 서비스 수명 주기에 영향을 줄 수 있는 두 번째 문제 집합이 발생합니다. 컬렉션에서는 타이밍 및 복제본이 이동되거나 종료되는지 여부에 따라 예외를 반환합니다. 이러한 예외는 올바르게 처리되어야 합니다. Service Fabric에서 발생한(throw) 예외는 영구(FabricException) 및 일시적(FabricTransientException) 범주로 분류됩니다. 영구 예외는 기록되고 발생되어야 하지만, 일시적 예외는 몇 가지 다시 시도 논리에 따라 다시 시도될 수 있습니다.

서비스 수명 주기 이벤트와 함께 ReliableCollections 사용으로 인한 예외 처리는 신뢰할 수 있는 서비스의 테스트 및 유효성 검사에 대한 중요한 부분입니다. 권장 사항은 항상 프로덕션에 배포하기 전에 업그레이드 및 비정상 상황 테스트(chaos testing)를 수행하는 동안 로드 상태에서 서비스를 실행하는 것입니다. 이러한 기본 단계를 통해 서비스가 올바르게 구현되고 수명 주기 이벤트가 올바르게 처리되도록 할 수 있습니다.

서비스 수명 주기에 대한 참고 사항

  • RunAsync() 메서드 및 CreateServiceReplicaListeners/CreateServiceInstanceListeners 호출은 모두 선택 사항입니다. 서비스에는 이러한 항목이 있거나 없을 수도 있습니다. 예를 들어, 서비스가 모든 작업을 사용자 호출에 대한 응답으로 수행할 경우 RunAsync()을(를) 구현할 필요가 없습니다. 통신 수신기 및 해당 관련 코드만이 필요합니다. 마찬가지로 통신 수신기를 만들고 반환하는 작업은 선택적이며 서비스가 백그라운드 작업을 수행해야 하므로 RunAsync()을 구현해야 합니다.
  • 서비스가 RunAsync()을 성공적으로 완료하고 거기에서 반환하는 작업이 유효합니다. 완료는 실패 조건이 아닙니다. RunAsync()를 완료하면 서비스의 백그라운드 작업이 완료되었음을 나타냅니다. 상태 저장 신뢰할 수 있는 서비스의 경우 복제본이 주에서 보조로 강등된 다음 다시 주로 승격되면 RunAsync()가 다시 호출됩니다.
  • 예기치 않은 예외가 발생(throw)되어 서비스가 RunAsync()에서 종료되는 경우 실패로 간주됩니다. 서비스 개체가 종료되고 상태 오류가 보고됩니다.
  • 이러한 메서드에서 반환에는 시간 제한이 없으며 신뢰할 수 있는 컬렉션에 작성할 수 있는 기능이 즉시 손실되고 모든 실제 작업을 완료할 수 없습니다. 취소 요청을 받는 즉시 최대한 신속하게 반환하는 것이 좋습니다. 서비스가 적절한 시간 내에 이러한 API 호출에 응답하지 않으면 Service Fabric은 서비스를 강제로 종료할 수 있습니다. 이러한 상황은 일반적으로 애플리케이션을 업그레이드하거나 서비스를 삭제할 때 발생합니다. 이 시간 제한은 기본적으로 15분입니다.
  • OnCloseAsync() 경로의 오류로 인해 OnAbort()가 호출되고 이것이 서비스에서 요구하는 리소스를 정리하고 릴리스할 수 있는 마지막 방법입니다. 이는 일반적으로 노드에서 영구 오류가 감지되거나, 내부 오류로 인해 서비스 패브릭에서 서비스 인스턴스 수명 주기를 안정적으로 관리할 수 없을 때 호출됩니다.
  • 상태 저장 서비스 복제본이 역할을 변경할 경우(예: 주 또는 보조) OnChangeRoleAsync()가 호출됩니다. 주 복제본에는 쓰기 상태가 지정됩니다(신뢰할 수 있는 컬렉션을 만들고 쓰도록 허용). 보조 복제본에는 읽기 상태가 지정됩니다(신뢰할 수 있는 기존 컬렉션에서 읽기만 가능). 상태 저장 서비스에서 대부분의 작업은 주 복제본에서 수행됩니다. 보조 복제본은 읽기 전용 유효성 검사, 보고서 생성, 데이터 마이닝 또는 다른 읽기 전용 작업을 수행할 수 있습니다.

다음 단계