지속성 함수의 작업 허브(Azure Functions)

Durable Functions작업 허브는 보류 중인 모든 작업을 포함하여 스토리지에 있는 애플리케이션의 현재 상태를 나타냅니다. 함수 앱이 실행되는 동안 오케스트레이션, 작업 및 엔터티 함수의 진행 상황은 작업 허브에 계속 저장됩니다. 이렇게 하면 애플리케이션이 어떤 이유로 인해 일시적으로 중지되거나 중단된 후 다시 시작해야 하는 경우 중단된 위치에서 처리를 다시 시작할 수 있습니다. 또한 함수 앱이 컴퓨팅 작업자를 동적으로 크기 조정할 수 있습니다.

Diagram showing concept of function app and task hub concept.

개념적으로 작업 허브는 다음 정보를 저장합니다.

  • 모든 오케스트레이션 및 항목 인스턴스의 인스턴스 상태.
  • 처리할 메시지는 다음과 같습니다.
    • 실행 대기 중인 작업을 나타내는 모든 작업 메시지.
    • 인스턴스에 전달되기를 기다리는 모든 인스턴스 메시지.

작업 메시지와 인스턴스 메시지의 차이점은 작업 메시지는 상태 비저장이므로 어디에서나 처리할 수 있는 반면 인스턴스 메시지는 해당 인스턴스 ID로 식별되는 특정 상태 저장 인스턴스(오케스트레이션 또는 엔터티)로 전달되어야 한다는 것입니다.

내부적으로 각 스토리지 공급자는 다른 조직을 사용하여 인스턴스 상태 및 메시지를 나타낼 수 있습니다. 예를 들어 메시지는 Azure Storage 공급자에 의해 Azure Storage 큐에 저장되지만 MSSQL 공급자에 의해 관계형 테이블에 저장됩니다. 이러한 차이점은 애플리케이션 디자인에 관한 한 중요하지 않지만 일부는 성능 특성에 영향을 줄 수 있습니다. 아래의 스토리지의 표현 섹션에서 이에 대해 설명합니다.

작업 항목

작업 허브의 작업 메시지 및 인스턴스 메시지는 함수 앱이 처리해야 하는 작업을 나타냅니다. 함수 앱이 실행되는 동안 작업 허브에서 지속적으로 작업 항목을 가져옵니다. 각 작업 항목은 하나 이상의 메시지를 처리하고 있습니다. 두 가지 형식의 작업 항목을 구분합니다.

  • 활동 작업 항목: 활동 함수를 실행하여 작업 메시지를 처리합니다.
  • 조정자 작업 항목: 조정자 또는 엔터티 함수를 실행하여 하나 이상의 인스턴스 메시지를 처리합니다.

작업자는 구성된 작업자당 동시성 제한에 따라 여러 작업 항목을 동시에 처리할 수 있습니다.

작업자가 작업 항목을 완료하면 작업 허브에 효과를 다시 커밋합니다. 이러한 효과는 실행된 함수 형식에 따라 다릅니다.

  • 완료된 작업 함수는 부모 오케스트레이터 인스턴스로 주소가 지정된 결과를 포함하는 인스턴스 메시지를 만듭니다.
  • 완료된 오케스트레이터 함수는 오케스트레이션 상태 및 기록을 업데이트하고 새 메시지를 만들 수 있습니다.
  • 완료된 엔터티 함수는 엔터티 상태를 업데이트하고 새 인스턴스 메시지를 만들 수도 있습니다.

오케스트레이션의 경우 각 작업 항목은 해당 오케스트레이션 실행의 하나의 에피소드를 나타냅니다. 오케스트레이터가 처리할 새 메시지가 있을 때 에피소드가 시작됩니다. 이러한 메시지는 오케스트레이션을 시작해야 함을 나타낼 수 있습니다. 또는 작업, 엔터티 호출, 타이머 또는 하위 오케스트레이션이 완료되었음을 나타낼 수 있습니다. 또는 외부 이벤트를 나타낼 수 있습니다. 메시지는 조정자가 결과를 처리하고 다음 에피소드를 계속할 수 있도록 하는 작업 항목을 트리거합니다. 해당 에피소드는 오케스트레이터가 완료되거나 새 메시지를 기다려야 하는 지점에 도달하면 끝납니다.

실행 예

두 가지 작업을 병렬로 시작하고 두 작업이 모두 완료될 때까지 기다리는 팬아웃/팬인 오케스트레이션을 고려합니다.

[FunctionName("Example")]
public static async Task Run([OrchestrationTrigger] IDurableOrchestrationContext context)
{
    Task t1 = context.CallActivityAsync<int>("MyActivity", 1);
    Task t2 = context.CallActivityAsync<int>("MyActivity", 2);
    await Task.WhenAll(t1, t2);
}

이 오케스트레이션이 클라이언트에 의해 시작된 후에는 함수 앱에서 일련의 작업 항목으로 처리됩니다. 완료된 각 작업 항목은 커밋될 때 작업 허브 상태를 업데이트합니다. 수행하는 단계는 다음과 같습니다.

  1. 클라이언트가 instance-id "123"으로 새 오케스트레이션을 시작하도록 요청합니다. 클라이언트가 이 요청을 완료한 후 작업 허브에는 오케스트레이션 상태에 대한 자리 표시자와 인스턴스 메시지가 포함됩니다.

    workitems-illustration-step-1

    ExecutionStarted 레이블은 오케스트레이션 기록에 참여하는 다양한 형식의 메시지 및 이벤트를 식별하는 많은 기록 이벤트 유형 중 하나입니다.

  2. 작업자는 오케스트레이터 작업 항목을 실행하여 ExecutionStarted 메시지를 처리합니다. 오케스트레이션 코드 실행을 시작하는 오케스트레이터 함수를 호출합니다. 이 코드는 두 가지 작업을 예약한 다음 결과를 기다릴 때 실행을 중지합니다. 작업자가 이 작업 항목을 커밋한 후 작업 허브에 포함

    workitems-illustration-step-2

    런타임 상태는 이제 Running이고 2개의 새로운 TaskScheduled 메시지가 추가되었으며 기록에는 이제 5개의 이벤트 OrchestratorStarted, ExecutionStarted, TaskScheduled, TaskScheduled, OrchestratorCompleted가 포함됩니다. 이러한 이벤트는 이 오케스트레이션 실행의 첫 번째 에피소드를 나타냅니다.

  3. 작업자는 작업 항목을 실행하여 TaskScheduled 메시지 중 하나를 처리합니다. 입력 "2"로 작업 함수를 호출합니다. 작업 함수가 완료되면 결과가 포함된 TaskCompleted 메시지가 만들어집니다. 작업자가 이 작업 항목을 커밋한 후 작업 허브에 포함

    workitems-illustration-step-3

  4. 작업자는 오케스트레이터 작업 항목을 실행하여 TaskCompleted 메시지를 처리합니다. 오케스트레이션이 여전히 메모리에 캐시되어 있으면 실행을 다시 시작할 수 있습니다. 그렇지 않으면 작업자가 먼저 기록을 재생하여 오케스트레이션의 현재 상태를 복구합니다. 그런 다음 오케스트레이션을 계속하여 작업 결과를 전달합니다. 이 결과를 수신한 후 오케스트레이션은 여전히 다른 작업의 결과를 기다리고 있으므로 다시 한 번 실행을 중지합니다. 작업자가 이 작업 항목을 커밋한 후 작업 허브에 포함

    workitems-illustration-step-4

    이제 오케스트레이션 기록에 OrchestratorStarted, TaskCompleted, OrchestratorCompleted 이벤트가 3개 더 포함됩니다. 이러한 이벤트는 이 오케스트레이션 실행의 두 번째 에피소드를 나타냅니다.

  5. 작업자는 작업 항목을 실행하여 나머지 TaskScheduled 메시지를 처리합니다. 입력 "1"로 작업 함수를 호출합니다. 작업자가 이 작업 항목을 커밋한 후 작업 허브에 포함

    workitems-illustration-step-5

  6. 작업자는 다른 오케스트레이터 작업 항목을 실행하여 TaskCompleted 메시지를 처리합니다. 이 두 번째 결과를 받은 후 오케스트레이션이 완료됩니다. 작업자가 이 작업 항목을 커밋한 후 작업 허브에 포함

    workitems-illustration-step-6

    이제 런타임 상태가 Completed이고 오케스트레이션 기록에 OrchestratorStarted, TaskCompleted, ExecutionCompleted, OrchestratorCompleted 이벤트가 4개 더 포함됩니다. 이러한 이벤트는 이 오케스트레이션 실행의 세 번째이자 마지막 에피소드를 나타냅니다.

이 오케스트레이션 실행의 최종 기록에는 12개의 이벤트 OrchestratorStarted, ExecutionStarted, TaskScheduled, TaskScheduled, OrchestratorCompleted, OrchestratorStarted, TaskCompleted, OrchestratorCompleted, OrchestratorStarted, TaskCompleted, ExecutionCompleted, OrchestratorCompleted가 포함됩니다.

참고 항목

표시된 일정이 유일한 것이 아닙니다. 가능한 일정이 약간씩 다릅니다. 예를 들어 두 번째 작업이 더 일찍 완료되면 두 TaskCompleted 인스턴스 메시지가 단일 작업 항목에서 처리될 수 있습니다. 이 경우 2개의 에피소드만 있고 다음 10개 이벤트 OrchestratorStarted, ExecutionStarted, TaskScheduled, TaskScheduled, OrchestratorCompleted, OrchestratorStarted, TaskCompleted, TaskCompleted, ExecutionCompleted, OrchestratorCompleted가 포함되어 있기 때문에 실행 이력이 조금 더 짧습니다.

작업 허브 관리

다음으로 작업 허브를 만들거나 삭제하는 방법, 여러 함수 앱을 실행할 때 작업 허브를 올바르게 사용하는 방법, 작업 허브의 콘텐츠를 검사하는 방법에 대해 자세히 살펴보겠습니다.

만들기 및 삭제

함수 앱이 처음 시작될 때 필요한 모든 리소스가 있는 빈 작업 허브가 스토리지에 자동으로 만들어집니다.

기본 Azure Storage 공급자를 사용하는 경우 추가 구성이 필요하지 않습니다. 그렇지 않으면 스토리지 공급자 구성 지침에 따라 스토리지 공급자가 작업 허브에 필요한 스토리지 리소스를 적절하게 프로비저닝하고 액세스할 수 있는지 확인합니다.

참고 항목

작업 허브는 함수 앱을 중지하거나 삭제할 때 자동으로 삭제되지 않습니다. 해당 데이터를 더 이상 유지하지 않으려면 작업 허브, 해당 콘텐츠 또는 포함하는 스토리지 계정을 수동으로 삭제해야 합니다.

개발 시나리오에서는 자주 정리된 상태에서 다시 시작해야 할 수 있습니다. 이렇게 신속히 수행하려면 구성된 작업 허브 이름을 변경하면 됩니다. 이렇게 하면 애플리케이션을 다시 시작할 때 비어 있는 새 작업 허브가 강제로 만들어집니다. 이 경우 이전 데이터는 삭제되지 않습니다.

여러 함수 앱

여러 함수 앱이 한 스토리지 계정을 공유하는 경우 반드시 함수 앱마다 별도의 작업 허브 이름으로 구성해야 합니다. 이 요구 사항은 스테이징 슬롯에도 적용됩니다. 각 스테이징 슬롯은 고유한 작업 허브 이름으로 구성해야 합니다. 단일 스토리지 계정에 여러 작업 허브가 포함될 수 있습니다. 이 제한은 일반적으로 다른 스토리지 공급자에도 적용됩니다.

다음 다이어그램에서는 공유 및 전용 Azure Storage 계정의 함수 앱당 단일 작업 허브를 보여 줍니다.

Diagram showing shared and dedicated storage accounts.

참고 항목

작업 허브 공유 규칙의 예외는 지역 재해 복구를 위해 앱을 구성하는 경우입니다. 자세한 내용은 재해 복구 및 지리적 분포 문서를 참조하세요.

콘텐츠 검사

작업 허브의 내용을 검사하는 몇 가지 일반적인 방법이 있습니다.

  1. 함수 앱 내에서 클라이언트 개체는 인스턴스 저장소를 쿼리하는 메서드를 제공합니다. 지원되는 쿼리 형식에 대한 자세한 내용은 인스턴스 관리 문서를 참조하세요.
  2. 마찬가지로 HTTP API는 오케스트레이션 및 항목의 상태를 쿼리하기 위한 REST 요청을 제공합니다. 자세한 내용은 HTTP API 참조를 참조하세요.
  3. Durable Functions Monitor 도구는 작업 허브를 검사하고 시각적 표시를 위한 다양한 옵션을 제공합니다.

일부 스토리지 공급자의 경우 기본 스토리지로 직접 이동하여 작업 허브를 검사할 수도 있습니다.

  • Azure Storage 공급자를 사용하는 경우 인스턴스 상태는 Azure Storage Explorer와 같은 도구를 사용하여 검사할 수 있는 인스턴스 테이블기록 테이블에 저장됩니다.
  • MSSQL 스토리지 공급자를 사용하는 경우 SQL 쿼리 및 도구를 통해 데이터베이스 내부의 작업 허브 내용을 검사할 수 있습니다.

스토리지의 표현

각 스토리지 공급자는 다른 내부 조직을 사용하여 스토리지의 작업 허브를 나타냅니다. 이 조직을 이해해야 하는 것은 아니지만 함수 앱의 문제를 해결하거나 성능, 확장성 또는 비용 대상을 보장하려고 할 때 도움이 될 수 있습니다. 따라서 각 스토리지 공급자에 대해 스토리지에서 데이터가 구성되는 방식을 간략하게 설명합니다. 다양한 스토리지 공급자 옵션 및 비교 방법에 대한 자세한 내용은 Durable Functions 스토리지 공급자를 참조하세요.

Azure Storage 공급자

Azure Storage 공급자는 다음 구성 요소를 사용하여 스토리지의 작업 허브를 나타냅니다.

  • 두 개의 Azure 테이블은 인스턴스 상태를 저장합니다.
  • 하나의 Azure 큐는 작업 메시지를 저장합니다.
  • 하나 이상의 Azure 큐가 인스턴스 메시지를 저장합니다. 이러한 각 제어 큐은 인스턴스 ID의 해시를 기반으로 모든 인스턴스 메시지의 하위 집합이 할당된 파티션을 나타냅니다.
  • 임대 Blob 및/또는 대용량 메시지에 사용되는 몇 가지 추가 Blob 컨테이너입니다.

예를 들어 PartitionCount = 4가 있는 xyz라는 작업 허브에는 다음 큐와 테이블이 포함되어 있습니다.

Diagram showing Azure Storage provider storage storage organization for 4 control queues.

다음으로 이러한 구성 요소와 해당 구성 요소가 수행하는 역할에 대해 자세히 설명합니다.

작업 허브가 Azure Storage 공급자로 표시되는 방식에 대한 자세한 내용은 Azure Storage 공급자 설명서를 참조하세요.

Netherite 스토리지 공급자

Netherite는 모든 작업 허브 상태를 지정된 수의 파티션으로 분할합니다. 스토리지에서는 다음 리소스가 사용됩니다.

  • 파티션별로 그룹화된 모든 Blob이 포함된 하나의 Azure Storage Blob 컨테이너입니다.
  • 파티션에 대해 게시된 메트릭이 포함된 하나의 Azure 테이블입니다.
  • 파티션 간에 메시지를 전달하기 위한 Azure Event Hubs 네임스페이스입니다.

예를 들어 이름이 mytaskhub이고 PartitionCount = 32인 작업 허브는 스토리지에 다음과 같이 표시됩니다.

Diagram showing Netherite storage organization for 32 partitions.

참고 항목

모든 작업 허브 상태는 x-storage Blob 컨테이너 내부에 저장됩니다. DurableTaskPartitions 테이블 및 EventHubs 네임스페이스에는 중복 데이터가 포함되어 있습니다. 해당 내용이 손실된 경우 자동으로 복구할 수 있습니다. 따라서 기본 만료 시간이 지난 후에도 메시지를 유지하도록 Azure Event Hubs 네임스페이스를 구성할 필요가 없습니다.

Netherite는 로그 및 검사점을 기반으로 하는 이벤트 소싱 메커니즘을 사용하여 파티션의 현재 상태를 나타냅니다. 블록 Blob과 페이지 Blob이 모두 사용됩니다. 이 형식은 스토리지에서 직접 읽을 수 없으므로 인스턴스 저장소를 쿼리할 때 함수 앱을 실행해야 합니다.

Netherite 스토리지 공급자의 작업 허브에 대한 자세한 내용은 Netherite 스토리지 공급자의 작업 허브 정보를 참조하세요.

MSSQL 스토리지 공급자

모든 작업 허브 데이터는 여러 테이블을 사용하여 단일 관계형 데이터베이스에 저장됩니다.

  • dt.Instancesdt.History 테이블은 인스턴스 상태를 저장합니다.
  • dt.NewEvents 테이블은 인스턴스 메시지를 저장합니다.
  • dt.NewTasks 테이블은 작업 메시지를 저장합니다.

Diagram showing MSSQL storage organization.

여러 작업 허브가 동일한 데이터베이스에서 독립적으로 공존할 수 있도록 각 테이블에는 기본 키의 일부로 TaskHub 열이 포함됩니다. 다른 두 공급자와 달리 MSSQL 공급자에는 파티션 개념이 없습니다.

MSSQL 스토리지 공급자의 작업 허브에 대한 자세한 내용은 MSSQL(Microsoft SQL) 스토리지 공급자를 위한 작업 허브 정보를 참조하세요.

작업 허브 이름

작업 허브는 다음 규칙을 따라야 하는 이름으로 식별됩니다.

  • 영숫자만 포함
  • 문자로 시작
  • 최소 길이는 3자, 최대 길이는 45자

작업 허브 이름은 다음 예제와 같이 host.json에 선언됩니다.

host.json(Functions 2.0)

{
  "version": "2.0",
  "extensions": {
    "durableTask": {
      "hubName": "MyTaskHub"
    }
  }
}

host.json(Functions 1.x)

{
  "durableTask": {
    "hubName": "MyTaskHub"
  }
}

다음 host.json 예제 파일과 같이 앱 설정을 사용하여 작업 허브를 구성할 수도 있습니다.

host.json(Functions 1.0)

{
  "durableTask": {
    "hubName": "%MyTaskHub%"
  }
}

host.json(Functions 2.0)

{
  "version": "2.0",
  "extensions": {
    "durableTask": {
      "hubName": "%MyTaskHub%"
    }
  }
}

작업 허브 이름은 MyTaskHub 앱 설정의 값으로 설정됩니다. 다음 local.settings.jsonMyTaskHub 설정을 samplehubname으로 정의하는 방법을 보여 줍니다.

{
  "IsEncrypted": false,
  "Values": {
    "MyTaskHub" : "samplehubname"
  }
}

참고 항목

배포 슬롯을 사용하는 경우 앱 설정을 사용하여 작업 허브 이름을 구성하는 것이 가장 좋습니다. 특정 슬롯이 항상 특정 작업 허브를 사용하도록 하려면 "slot-sticky" 앱 설정을 사용합니다.

host.json 외에도 오케스트레이션 클라이언트 바인딩메타 데이터에서 작업 허브 이름을 구성할 수 있습니다. 별도의 함수 앱에 상주하는 오케스트레이션 또는 엔터티에 액세스해야 하는 경우에 유용합니다. 다음 코드에서는 오케스트레이션 클라이언트 바인딩을을 사용하여 앱 설정으로 구성된 작업 허브로 작업하는 함수를 작성하는 방법을 보여줍니다.

[FunctionName("HttpStart")]
public static async Task<HttpResponseMessage> Run(
    [HttpTrigger(AuthorizationLevel.Function, methods: "post", Route = "orchestrators/{functionName}")] HttpRequestMessage req,
    [DurableClient(TaskHub = "%MyTaskHub%")] IDurableOrchestrationClient starter,
    string functionName,
    ILogger log)
{
    // Function input comes from the request content.
    object eventData = await req.Content.ReadAsAsync<object>();
    string instanceId = await starter.StartNewAsync(functionName, eventData);

    log.LogInformation($"Started orchestration with ID = '{instanceId}'.");

    return starter.CreateCheckStatusResponse(req, instanceId);
}

참고 항목

이전 예제는 Durable Functions 2.x용입니다. Durable Functions 1.x의 경우 IDurableOrchestrationContext 대신 DurableOrchestrationContext를 사용해야 합니다. 버전 간 차이점에 관한 자세한 내용은 Durable Functions 버전 문서를 참조하세요.

참고 항목

클라이언트 바인딩 메타데이터에서 작업 허브 이름을 구성하는 작업은 하나의 함수 앱을 사용하여 다른 함수 앱의 오케스트레이션 및 엔터티에 액세스할 때만 필요합니다. 클라이언트 함수가 오케스트레이션 및 엔터티와 동일한 함수 앱에 정의된 경우 바인딩 메타데이터에서 작업 허브 이름을 지정하지 않아야 합니다. 기본적으로 모든 클라이언트 바인딩은 host.json 설정에서 작업 허브 메타데이터를 가져옵니다.

작업 허브 이름은 문자로 시작하고 문자와 숫자로만 구성되어야 합니다. 지정하지 않으면 다음 표와 같이 기본 작업 허브 이름이 사용됩니다.

지속성 확장 버전 기본 작업 허브 이름
2.x Azure에 배포된 경우 작업 허브 이름은 함수 앱의 이름에서 파생됩니다. Azure 외부에서 실행하는 경우 기본 작업 허브 이름은 TestHubName입니다.
1.x 모든 환경의 기본 작업 허브 이름은 DurableFunctionsHub입니다.

확장 버전 간 차이점에 대한 자세한 내용은 Durable Functions 버전 문서를 참조하세요.

참고 항목

이 이름은 공유 스토리지 계정에 여러 작업 허브가 있을 때 작업 허브를 다른 작업 허브에서 구분해줍니다. 여러 함수 앱이 한 공유 스토리지 계정을 공유하는 경우 host.json 파일의 각 작업 허브에 서로 다른 이름을 명시적으로 구성해야 합니다. 그러지 않으면 여러 함수 앱이 메시지를 위해 서로 경쟁하게 되며, 이로 인해 오케스트레이션이 예기치 않게 Pending 또는 Running 상태로 "중단"되는 것과 같은 정의되지 않은 동작이 발생할 수 있습니다.

다음 단계