영구 오케스트레이션 은 API를 사용하여 continue-as-new 자신의 기록을 주기적으로 다시 설정하여 무기한 실행되는 오케스트레이터 함수입니다. 집계, 주기적 백그라운드 작업 및 무제한 기록 증가 없이 무한 루프가 필요한 모든 Durable Functions 시나리오에 유용합니다.
continue-as-new이 없으면, 무한히 반복하는 오케스트레이터는 예약된 모든 작업으로 오케스트레이션 기록을 누적하여 결국 성능 문제를 일으키고 메모리를 과도하게 사용하게 됩니다. 영구 오케스트레이션 패턴은 각 반복에서 기록을 다시 설정하여 이를 해결합니다.
메모
영구 오케스트레이션 코드 샘플은 C#, JavaScript, Python 및 Java 사용할 수 있습니다. PowerShell은 continue-as-new을 지원하지 않습니다.
문서 내용:
- Continue-as-new 기능의 작동 방식 - 재설정 메커니즘
- 고려 사항 - 예외 동작, 불완전한 작업 및 외부 이벤트
- 주기적 작업 예제 - 타이머 겹침을 방지하는 정리 루프
- 영구 오케스트레이션 시작 - 시작 및 싱글톤 패턴
- 영원한 오케스트레이션에서의 탈출 - 우아한 중단과 종료
영구 오케스트레이션 은 API를 사용하여 continue-as-new 자신의 기록을 주기적으로 다시 설정하여 무기한 실행되는 오케스트레이션입니다. 집계, 주기적 백그라운드 작업 및 무제한 기록 증가 없이 무한 루프가 필요한 시나리오에 유용합니다.
continue-as-new가 없으면, 영원히 반복되는 오케스트레이션은 모든 예약된 작업마다 기록이 누적되며, 결국 성능 문제와 과도한 메모리 사용을 유발하게 됩니다. 영구 오케스트레이션 패턴은 각 반복에서 기록을 다시 설정하여 이를 해결합니다.
중요합니다
현재 PowerShell 지속성 작업 SDK는 사용할 수 없습니다.
문서 내용:
- 새로 계속하기 작동 방식 - 재설정 메커니즘
- 고려 사항 - 예외 동작, 불완전한 작업 및 외부 이벤트
- 주기적 작업 예제 - 타이머 겹침을 방지하는 정리 루프
- 영구 오케스트레이션 시작 - 시작 및 싱글톤 패턴
- 영구 오케스트레이션 종료 - 정상적인 중지 및 종료
계속-새로하기 기능의 작동 원리
오케스트레이터 함수는 무한 루프를 사용하는 대신 continue-as-new의 메서드를 호출하여 상태를 다시 설정합니다. 이 메서드는 다음 오케스트레이터 함수 생성을 위한 새 입력이 되는 JSON 직렬화 가능 매개 변수를 사용합니다.
호출 continue-as-new하면 오케스트레이션 인스턴스가 새 입력 값으로 다시 시작됩니다. 동일한 인스턴스 ID가 유지되지만 오케스트레이터 함수의 기록이 다시 설정됩니다.
오케스트레이션은 무한 루프를 사용하는 대신 오케스트레이션 컨텍스트에서 메서드를 continue-as-new 호출하여 상태를 다시 설정합니다. 이 메서드는 다음 오케스트레이션 생성을 위한 새 입력이 되는 JSON 직렬화 가능 매개 변수를 사용합니다.
호출 continue-as-new하면 오케스트레이션 인스턴스가 새 입력 값으로 다시 시작됩니다. 동일한 인스턴스 ID가 유지되지만 오케스트레이션의 기록이 다시 설정됩니다.
영구 오케스트레이션 고려 사항
오케스트레이션에서 메서드를 continue-as-new 사용할 때는 다음 사항을 고려해야 합니다.
오케스트레이터 함수가 메서드를 사용하여
continue-as-new다시 설정되면 Durable Task Framework는 동일한 인스턴스 ID를 유지하지만 내부적으로는 앞으로 새 실행 ID 를 만들고 사용합니다. 이 실행 ID는 외부에서 노출되지 않지만 오케스트레이션 실행을 디버깅할 때 유용합니다.실행 중에 처리되지 않은 예외가 발생하면 오케스트레이션이 실패한 상태로 전환되고 실행이 종료됩니다. 블록
finally에서continue-as-new에 대한 호출은 처리되지 않은 예외 발생 후에 오케스트레이션을 다시 시작하지 않습니다.불완전한 작업의 결과는 오케스트레이션이 호출
continue-as-new될 때 삭제됩니다. 예를 들어 타이머가 예약된 다음continue-as-new타이머가 실행되기 전에 호출되면 타이머 이벤트가 삭제됩니다.필요에 따라 다시 시작할 때
continue-as-new처리되지 않은 외부 이벤트를 유지할 수 있습니다. C#ContinueAsNew에서는 기본적으로 처리되지 않은 이벤트를 유지합니다. JavacontinueAsNew기본적으로 이벤트를 유지합니다. Python에서는continue_as_newsave_events=True하지 않는 한 이벤트를 유지하지 않습니다. JavaScript에서는continueAsNew가saveEvents매개 변수를 사용하여 이 동작을 제어합니다. 매개 변수는true또는false중 하나여야 합니다.
오케스트레이션에서 메서드를 continue-as-new 사용할 때는 다음 사항을 고려해야 합니다.
메서드를 사용하여
continue-as-new오케스트레이션을 다시 설정하는 경우 지속성 작업 SDK는 동일한 인스턴스 ID를 유지하지만 내부적으로는 앞으로 새 실행 ID 를 만들고 사용합니다. 이 실행 ID는 외부에서 노출되지 않지만 오케스트레이션 실행을 디버깅할 때 유용할 수 있습니다.실행 중에 처리되지 않은 예외가 발생하면 오케스트레이션이 실패한 상태로 전환되고 실행이 종료됩니다. 블록
finally에서continue-as-new로의 호출은 catch되지 않은 예외 후에도 오케스트레이션을 다시 시작하지 않습니다.불완전한 작업의 결과는 오케스트레이션이 호출
continue-as-new될 때 삭제됩니다. 예를 들어 타이머가 예약된 다음continue-as-new타이머가 실행되기 전에 호출되면 타이머 이벤트가 삭제됩니다.필요에 따라 다시 시작할 때
continue-as-new처리되지 않은 외부 이벤트를 유지할 수 있습니다. .NET 및 Javacontinue-as-new기본적으로 처리되지 않은 이벤트를 유지합니다. Python에서는continue_as_newsave_events=True하지 않는 한 이벤트를 유지하지 않습니다. JavaScript에서는continueAsNew가saveEvents매개 변수를 사용하여 이 동작을 제어합니다. 매개 변수는true또는false중 하나여야 합니다. 모든 경우에 처리되지 않은 이벤트는 오케스트레이션이waitForExternalEvent또는wait_for_external_event을 다음에 호출할 때 전달됩니다.
주기적 작업 예제
영구 오케스트레이션의 일반적인 사용 사례 중 하나는 정리 작업과 같은 주기적인 백그라운드 작업입니다.
타이머 트리거를 사용하지 않는 이유는 무엇인가요? CRON 기반 타이머 트리거는 이전 실행이 완료되었는지 여부에 관계없이 고정된 시간에 실행됩니다. 영구 오케스트레이션은 다음 반복을 예약하기 전에 작업이 완료될 때까지 기다리므로 실행이 겹치지 않습니다.
| Approach | 일정(1시간 간격, 30분 작업) | 겹치는 위험 |
|---|---|---|
| 타이머 트리거(CRON) | 1:00, 2:00, 3:00 | 예 - 작업이 간격을 초과하는 경우 |
| 영구 오케스트레이션 | 1:00, 2:30, 4:00 | 아니요 - 다음 실행이 완료될 때까지 대기합니다. |
[FunctionName("Periodic_Cleanup_Loop")]
public static async Task Run(
[OrchestrationTrigger] IDurableOrchestrationContext context)
{
await context.CallActivityAsync("DoCleanup", null);
// sleep for one hour between cleanups
DateTime nextCleanup = context.CurrentUtcDateTime.AddHours(1);
await context.CreateTimer(nextCleanup, CancellationToken.None);
context.ContinueAsNew(null);
}
public class PeriodicCleanupLoop : TaskOrchestrator<object?, object?>
{
public override async Task<object?> RunAsync(TaskOrchestrationContext context, object? input)
{
await context.CallActivityAsync("DoCleanup");
// sleep for one hour between cleanups
await context.CreateTimer(TimeSpan.FromHours(1), CancellationToken.None);
context.ContinueAsNew(null);
return null;
}
}
영구 오케스트레이션 시작
다른 오케스트레이션 함수와 마찬가지로 start-new 또는 schedule-new 지속성 클라이언트 메서드를 사용하여 영구 오케스트레이션을 시작합니다. 한 번에 하나의 인스턴스만 실행되도록 하려면 고정 인스턴스 ID를 사용합니다. 자세한 내용은 Singleton 오케스트레이션을 참조하세요.
[FunctionName("Trigger_Eternal_Orchestration")]
public static async Task<HttpResponseMessage> OrchestrationTrigger(
[HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequestMessage request,
[DurableClient] IDurableOrchestrationClient client)
{
string instanceId = "StaticId";
await client.StartNewAsync("Periodic_Cleanup_Loop", instanceId);
return client.CreateCheckStatusResponse(request, instanceId);
}
일정-새 클라이언트 메서드를 사용하여 다른 오케스트레이션과 마찬가지로 영구 오케스트레이션을 시작합니다. 한 번에 하나의 인스턴스만 실행되도록 하려면 고정 인스턴스 ID를 사용합니다. 자세한 내용은 Singleton 오케스트레이션을 참조하세요.
string instanceId = "StaticId";
await client.ScheduleNewOrchestrationInstanceAsync(
"PeriodicCleanupLoop",
null,
new StartOrchestrationOptions { InstanceId = instanceId });
영원한 오케스트레이션에서 벗어나다
오케스트레이터 함수가 최종적으로 완료되어야 하는 경우 호출 continue-as-new 하지 말고 함수를 종료합니다.
오케스트레이터 함수가 무한 루프에 있고 중지해야 하는 경우 오케스트레이션 클라이언트 바인딩의 종료 API를 사용하여 중지합니다.
await client.TerminateAsync(instanceId, "Cleanup no longer needed");
자세한 내용은 인스턴스 관리를 참조하세요.
오케스트레이션을 완료해야 하는 경우, continue-as-new 을 호출하지 말고 자연스럽게 종료되도록 해야 합니다.
오케스트레이션이 무한 루프에 있고 중지해야 하는 경우 지속성 작업 클라이언트에서 종료 API를 사용하여 중지합니다.
await client.TerminateInstanceAsync(instanceId, "Cleanup no longer needed");