지속성 함수의 버전 관리(Azure Functions)

애플리케이션의 수명 동안 함수를 추가, 제거 및 변경하는 것은 불가피합니다. Durable Functions를 사용하면 이전에는 불가능했던 방식으로 함수를 함께 연결할 수 있으며, 이 체인은 버전 관리 방법을 처리하는 방법에 영향을 줍니다.

호환성이 손상되는 변경 내용을 처리하는 방법

알아야 할 주요 변경 내용의 몇 가지 예가 있습니다. 이 문서에서는 가장 일반적인 항목에 대해 설명합니다. 기본 테마는 새 함수 오케스트레이션과 기존 함수 오케스트레이션 모두 함수 코드 변경의 영향을 받습니다.

활동 또는 엔터티 함수 서명 변경

시그니처 변경은 함수의 이름, 입력 또는 출력의 변경을 나타냅니다. 이러한 종류의 변경이 활동 또는 엔터티 함수에 적용된 경우 해당 함수에 의존하는 오케스트레이터 함수가 중단됩니다. 이러한 현상은 형식이 안전한 언어의 경우에 특히 두드러집니다. 이 변경을 수용하도록 오케스트레이터 함수를 업데이트하는 경우 기존 진행 중인 인스턴스를 중단시킬 수 있습니다.

예를 들어 다음과 같은 오케스트레이터 함수가 있다고 가정합니다.

[FunctionName("FooBar")]
public static Task Run([OrchestrationTrigger] IDurableOrchestrationContext context)
{
    bool result = await context.CallActivityAsync<bool>("Foo");
    await context.CallActivityAsync("Bar", result);
}

이 간단한 함수는 Foo결과를 가져와 Bar전달합니다. 더 다양한 결과 값을 지원하기 위해 Foo의 반환 값을 부울에서 문자열로 변경할 필요가 있다고 가정해 보겠습니다. 결과는 다음과 같습니다.

[FunctionName("FooBar")]
public static Task Run([OrchestrationTrigger] IDurableOrchestrationContext context)
{
    string result = await context.CallActivityAsync<string>("Foo");
    await context.CallActivityAsync("Bar", result);
}

이 변경 내용은 오케스트레이터 함수의 모든 새 인스턴스에 대해 잘 작동하지만 진행 중인 인스턴스가 중단되었을 수 있습니다. 예를 들어 오케스트레이션 인스턴스가 명명Foo된 함수를 호출하고 부울 값을 다시 가져오고 검사 경우를 고려합니다. 이 시점에서 시그니처 변경이 배포되면 검사점이 설정된 인스턴스는 다시 시작되고 Foo에 대한 호출을 재생할 때 즉시 실패합니다. 이 오류는 기록 테이블의 결과가 부울 값이지만 새 코드가 문자열 값으로 역직렬화하려고 시도하여 형식이 안전한 언어에 대해 예기치 않은 동작 또는 런타임 예외가 발생하므로 발생합니다.

이 예제는 함수 서명 변경으로 기존 인스턴스가 중단되는 여러 가지 방법 중 하나일 뿐입니다. 일반적으로 오케스트레이터가 함수를 호출하는 방식을 변경해야 하는 경우 변경에 문제가 있을 수 있습니다.

오케스트레이터 논리 변경

다른 버전 관리 문제 클래스는 진행 중인 인스턴스의 실행 경로를 변경하는 방식으로 오케스트레이터 함수 코드를 변경하여 발생합니다.

다음 오케스트레이터 함수를 살펴보세요.

[FunctionName("FooBar")]
public static Task Run([OrchestrationTrigger] IDurableOrchestrationContext context)
{
    bool result = await context.CallActivityAsync<bool>("Foo");
    await context.CallActivityAsync("Bar", result);
}

이제 두 기존 함수 호출 사이에 새 함수 호출을 추가하도록 변경하려는 경우를 가정해 보겠습니다.

[FunctionName("FooBar")]
public static Task Run([OrchestrationTrigger] IDurableOrchestrationContext context)
{
    bool result = await context.CallActivityAsync<bool>("Foo");
    if (result)
    {
        await context.CallActivityAsync("SendNotification");
    }

    await context.CallActivityAsync("Bar", result);
}

이 변경으로 Foo와 Bar 간에 SendNotification대한 새 함수 호출이 추가됩니다. 서명 변경은 없습니다. 기존 인스턴스가 Bar 호출에서 다시 시작될 때 문제가 발생합니다. 재생 중에 Foo에 대한 원래 호출이 반환true된 경우 오케스트레이터 재생은 실행 기록에 없는 SendNotification호출합니다. 런타임은 이 불일치를 감지하고 Bar에 대한 호출을 예상했을 때 SendNotification에 대한 호출을 발견했기 때문에 비결정 오케스트레이션을 발생시킵니다. 지속성 타이머 만들기, 외부 이벤트 대기, 하위 오케스트레이션 호출 등과 같은 다른 지속성 작업에 API 호출을 추가할 때 동일한 유형의 문제가 발생할 수 있습니다.

완화 전략

버전 관리 문제를 처리하기 위한 몇 가지 전략은 다음과 같습니다.

  • 아무 작업도 수행하지 않음(권장하지 않음)
  • 진행 중인 모든 인스턴스 중지
  • 병렬 배포

아무 작업도 수행하지 않음

버전 관리의 순진한 접근 방식은 아무 것도 하지 않고 진행 중인 오케스트레이션 인스턴스가 실패하도록 하는 것입니다. 변경 유형에 따라 다음과 같은 유형의 오류가 발생할 수 있습니다.

  • 오케스트레이션이 비결정 오케스트레이션 오류와 함께 실패할 수 있습니다.
  • 오케스트레이션이 무기한 중단되어 Running 상태를 보고할 수 있습니다.
  • 함수가 제거되면 호출을 시도하는 모든 함수에서 오류가 발생하여 실패할 수 있습니다.
  • 함수가 실행되도록 예약된 후 제거되면 앱에서 지속성 작업 프레임워크 엔진에서 낮은 수준의 런타임 오류가 발생하여 성능이 저하될 수 있습니다.

이러한 잠재적인 실패로 인해 "아무것도 하지 않음" 전략은 권장되지 않습니다.

진행 중인 모든 인스턴스 중지

또 다른 옵션은 모든 기내 인스턴스를 중지하는 것입니다. Durable Functions에 대한 기본 Azure Storage 공급자를 사용하는 경우 내부 control-queue 및 workitem-queue 큐의 내용을 지우면 모든 인스턴스를 중지할 수 있습니다. 또는 함수 앱을 중지하고, 이러한 큐를 삭제하고, 앱을 다시 시작할 수 있습니다. 앱이 다시 시작되면 큐가 자동으로 다시 생성됩니다. 이전 오케스트레이션 인스턴스는 "실행 중" 상태로 무기한 기본 수 있지만 오류 메시지로 로그를 어지럽히거나 앱에 해를 끼치지 않습니다. 이 접근 방식은 로컬 개발을 포함하여 신속한 프로토타입 개발에 이상적입니다.

참고 항목

이 방법을 사용하려면 기본 스토리지 리소스에 직접 액세스해야 하며 Durable Functions에서 지원하는 모든 스토리지 공급자에는 적합하지 않습니다.

병렬 배포

주요 변경 내용을 안전하게 배포하는 가장 확실한 방법은 이전 버전과 함께 나란히 배포하는 것입니다. 이렇게 하려면 다음 방법 중 하나를 사용하면 됩니다.

  • 모든 업데이트를 완전히 새로운 함수로 배포하여 기존 함수를 그대로 둡니다. 이는 새 함수 버전의 호출자를 재귀적으로 업데이트하는 것과 관련된 복잡성 때문에 일반적으로 권장되지 않습니다.
  • 모든 업데이트를 다른 스토리지 계정으로 새 함수 앱으로 배포합니다.
  • 동일한 스토리지 계정을 사용하지만 업데이트 된 작업 허브 이름을 사용하여 함수 앱의 새 복사본을 배포합니다. 그러면 새 버전의 앱에서 사용할 수 있는 새 스토리지 아티팩트가 만들어집니다. 이전 버전의 앱은 이전 스토리지 아티팩트 집합을 사용하여 계속 실행됩니다.

병렬 배포는 새 버전의 함수 앱을 배포하는 데 권장되는 기술입니다.

참고 항목

병렬 배포 전략에 대한 이 지침은 Azure Storage 관련 용어를 사용하지만 일반적으로 지원되는 모든 Durable Functions 스토리지 공급자에 적용됩니다.

배포 슬롯

Azure Functions 또는 Azure App Service에서 병렬 배포를 수행하는 경우 새 버전의 함수 앱을 새 배포 슬롯에 배포하는 것이 좋습니다. 배포 슬롯을 사용하면 슬롯 중 하나만 활성 프로덕션 슬롯으로 사용하여 함수 앱의 여러 복사본을 병렬로 실행할 수 있습니다. 새 오케스트레이션 논리를 기존 인프라에 노출할 준비가 되면 새 버전을 프로덕션 슬롯으로 교환하는 것만큼 간단할 수 있습니다.

참고 항목

이 전략은 오케스트레이터 함수에 HTTP 및 웹후크 트리거를 사용하는 경우에 가장 적합합니다. 큐 또는 Event Hubs와 같은 비 HTTP 트리거의 경우 트리거 정의는 교환 작업의 일부로 업데이트되는 앱 설정에서 파생되어야 합니다.

다음 단계