함수는 애플리케이션의 수명 동안 필연적으로 추가, 제거 및 변경되므로 Durable 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);
}
이 변경은 SendNotification와 Foo 사이에 새 함수 호출을 추가합니다.Bar 서명 변경 내용이 없습니다. 기존 인스턴스가 Bar 호출 이후 다시 시작될 때 문제가 발생합니다. 원래 호출 Foo이 true을 반환한 경우, 재생 중 오케스트레이터는 실행 기록에 없는 SendNotification을 호출합니다. 런타임은 이러한 불일치를 감지하고, 에 대한 호출이 예상되는 상황에서 SendNotification에 대한 호출을 발견했기 때문에 Bar 오류를 발생시킵니다. 지속성 타이머 만들기, 외부 이벤트 대기 또는 하위 오케스트레이션 호출과 같은 다른 지속성 작업에 API 호출을 추가할 때 동일한 유형의 문제가 발생할 수 있습니다.
완화 전략
Warning
완화 전략 없이 호환성을 손상시키는 변경을 배포하면("아무 조치도 하지 않는" 접근 방식) 비결정적 오케스트레이션 오류로 인해 오케스트레이션이 실패하거나, 상태가 Running 상태에서 무기한 정지되거나, 저수준의 런타임 오류로 인해 성능이 저하될 수 있습니다. 호환성이 손상되는 변경 내용을 배포할 때는 항상 다음 전략 중 하나를 사용합니다.
오케스트레이션 버전 관리(권장)
이 섹션의 다른 전략과 달리 오케스트레이션 버전 관리는 자동 버전 격리를 제공하는 기본 제공 런타임 기능 입니다. 별도의 배포, 작업 허브 또는 스토리지 계정을 관리할 필요가 없습니다. 대신 런타임 자체는 버전 정보를 추적하고 호환되는 작업자가 오케스트레이션 인스턴스를 처리하도록 합니다.
오케스트레이션 버전 관리:
- 각 오케스트레이션 인스턴스는 생성될 때 영구적으로 설정된 버전을 갖게 됩니다.
- 오케스트레이터 함수는 버전 및 분기 실행을 적절하게 검사하여 이전 및 새 코드 경로를 동일한 코드베이스에 유지할 수 있습니다.
- 최신 오케스트레이터 함수 버전을 실행하는 작업자는 이전 버전에서 만든 오케스트레이션 인스턴스를 계속 실행할 수 있습니다.
- 런타임을 사용하면 이전 오케스트레이터 함수 버전을 실행하는 작업자가 최신 버전의 오케스트레이션을 실행할 수 없습니다.
이 방법은 최소한의 구성(버전 문자열 및 선택적 일치 전략)이 필요하며 모든 스토리지 공급자와 호환됩니다. 이는 무중단 배포를 유지하면서 변경 사항을 지원해야 하는 애플리케이션에 권장되는 전략입니다.
자세한 구성 및 구현 지침은 오케스트레이션 버전 관리를 참조하세요.
모든 기내 인스턴스 중지
또 다른 옵션은 모든 기내 인스턴스를 중지하는 것입니다. 기본 Azure Storage 공급자를 Durable Functions 사용하는 경우 내부 control-queue 및 workitem-queue 큐의 내용을 지워 모든 인스턴스를 중지합니다. 또는 함수 앱을 중지하고, 이러한 큐를 삭제하고, 앱을 다시 시작합니다. 앱이 다시 시작되면 큐가 자동으로 다시 만들어집니다. 이전 오케스트레이션 인스턴스는 "실행 중" 상태로 무기한 남아 있을 수 있지만 실패 메시지로 로그를 복잡하게 하거나 앱에 해를 끼치지 않습니다. 이 방법은 로컬 개발을 비롯한 신속한 프로토타입 개발에 적합합니다.
Warning
이 방법을 사용하려면 기본 스토리지 리소스에 직접 액세스해야 하며 Durable Functions 지원하는 모든 스토리지 공급자에는 적합하지 않습니다.
독립적 배치
호환성이 손상되는 변경 내용이 안전하게 배포되도록 하는 가장 실패 방지 방법은 이전 버전과 함께 배포하는 것입니다. 다음 기술 중 하나를 사용할 수 있습니다.
- 다른 스토리지 계정: 모든 업데이트를 다른 스토리지 계정을 사용하여 새 함수 앱으로 배포합니다. 이렇게 하면 새 버전의 상태가 이전 버전과 완전히 격리됩니다.
- 다른 작업 허브: 동일한 스토리지 계정을 사용하지만 업데이트된 작업 허브 이름을 사용하여 함수 앱의 새 복사본을 배포합니다. 이 방법은 이전 버전이 기존 아티팩트 사용을 계속하는 동안 새 버전에 대한 새 스토리지 아티팩트가 만들어집니다.
Azure에서 동시 배포를 수행할 때 배포 슬롯을 사용하여 두 버전을 동시에 실행하고, 한 슬롯만 활성 프로덕션 슬롯으로 지정할 수 있습니다. 새 오케스트레이션 논리를 노출할 준비가 되면 새 버전을 프로덕션 슬롯으로 교환합니다.
메모
이 지침에서는 Azure Storage 특정 용어를 사용하지만 일반적으로 지원되는 모든 Durable Functions 스토리지 공급자 적용됩니다.
메모
배포 슬롯 교환은 HTTP 및 웹후크 트리거에서 가장 적합합니다. 큐 또는 Event Hubs와 같은 비 HTTP 트리거의 경우 트리거 정의는 교환 작업의 일부로 업데이트되는 앱 설정에서 파생 되어야 합니다.