Durable Functions のパフォーマンスとスケーリング (Azure Functions)Performance and scale in Durable Functions (Azure Functions)

パフォーマンスとスケーラビリティを最適化するには、Durable Functions 固有のスケーリング特性を理解しておくことが重要です。To optimize performance and scalability, it's important to understand the unique scaling characteristics of Durable Functions.

スケーリング動作を理解するには、基になる Azure Storage プロバイダーの詳細を理解しておく必要があります。To understand the scale behavior, you have to understand some of the details of the underlying Azure Storage provider.

履歴テーブルHistory table

履歴テーブルは、タスク ハブ内のすべてのオーケストレーション インスタンスの履歴イベントを含む Azure Storage テーブルです。The History table is an Azure Storage table that contains the history events for all orchestration instances within a task hub. このテーブルの名前は、TaskHubNameHistory の形式になります。The name of this table is in the form TaskHubNameHistory. インスタンスが実行されると、新しい行がこのテーブルに追加されます。As instances run, new rows are added to this table. このテーブルのパーティション キーは、オーケストレーションのインスタンス ID から派生します。The partition key of this table is derived from the instance ID of the orchestration. ほとんどの場合、インスタンス ID はランダムであり、Azure Storage での内部パーティションの最適な分散が確保されます。An instance ID is random in most cases, which ensures optimal distribution of internal partitions in Azure Storage.

オーケストレーション インスタンスを実行する必要があるときには、履歴テーブルの適切な行がメモリに読み込まれます。When an orchestration instance needs to run, the appropriate rows of the History table are loaded into memory. その後、これらの "履歴イベント" がオーケストレーター関数コードに再生され、以前にチェックポイントされた状態に戻されます。These history events are then replayed into the orchestrator function code to get it back into its previously checkpointed state. このように実行履歴を使用した状態の再構築は、イベント ソーシング パターンの影響を受けます。The use of execution history to rebuild state in this way is influenced by the Event Sourcing pattern.

インスタンス テーブルInstances table

インスタンス テーブルは、タスク ハブ内のすべてのオーケストレーション インスタンスの状態を含む別の Azure Storage テーブルです。The Instances table is another Azure Storage table that contains the statuses of all orchestration instances within a task hub. インスタンスが作成されると、このテーブルに新しい行が追加されます。As instances are created, new rows are added to this table. このテーブルのパーティション キーはオーケストレーション インスタンス ID であり、行キーは固定定数です。The partition key of this table is the orchestration instance ID and the row key is a fixed constant. オーケストレーション インスタンスごとに 1 つの行があります。There is one row per orchestration instance.

このテーブルは、GetStatusAsync API と HTTP status query API からのインスタンス クエリ要求を満たすために使用されます。This table is used to satisfy instance query requests from the GetStatusAsync API as well as the status query HTTP API. 最終的には、前述の履歴テーブルの内容との整合性が維持されます。It is kept eventually consistent with the contents of the History table mentioned previously. このように別の Azure Storage テーブルを使用したインスタンス クエリ操作への効率的な対応は、コマンド クエリ責務分離 (CQRS) パターンの影響を受けます。The use of a separate Azure Storage table to efficiently satisfy instance query operations in this way is influenced by the Command and Query Responsibility Segregation (CQRS) pattern.

内部キュー トリガーInternal queue triggers

オーケストレーター関数とアクティビティ関数は、どちらも関数アプリのタスク ハブ内の内部キューによってトリガーされます。Orchestrator functions and activity functions are both triggered by internal queues in the function app's task hub. このようにキューを使用することによって、信頼性のある "少なくとも 1 回" のメッセージ配信保証が実現されます。Using queues in this way provides reliable "at-least-once" message delivery guarantees. Durable Functions には、コントロール キュー作業項目キューという 2 種類のキューがあります。There are two types of queues in Durable Functions: the control queue and the work-item queue.

作業項目キューThe work-item queue

Durable Functions では、タスク ハブあたり 1 つの作業項目のキューがあります。There is one work-item queue per task hub in Durable Functions. これは基本的なキューであり、Azure Functions の他の queueTrigger キューと同様に動作します。It is a basic queue and behaves similarly to any other queueTrigger queue in Azure Functions. このキューは、一度に 1 つのメッセージをデキューして、ステートレスな "アクティビティ関数" をトリガーするために使用されます。This queue is used to trigger stateless activity functions by dequeueing a single message at a time. これらの各メッセージには、アクティビティ関数の入力と追加のメタデータ (実行する関数など) が含まれています。Each of these messages contains activity function inputs and additional metadata, such as which function to execute. Durable Functions アプリケーションが複数の VM にスケールアウトされた場合、作業項目キューの作業を取得するためにすべての VM が競合します。When a Durable Functions application scales out to multiple VMs, these VMs all compete to acquire work from the work-item queue.

コントロール キューControl queue(s)

Durable Functions では、タスク ハブごとに複数の "コントロール キュー" があります。There are multiple control queues per task hub in Durable Functions. "コントロール キュー" は、単純な作業項目キューよりも高度なキューです。A control queue is more sophisticated than the simpler work-item queue. コントロール キューは、ステートフルなオーケストレーター関数をトリガーするために使用されます。Control queues are used to trigger the stateful orchestrator functions. オーケストレーター関数のインスタンスは、ステートフル シングルトンであるため、競合コンシューマー モデルを使用して VM 間に負荷を分散させることはできません。Because the orchestrator function instances are stateful singletons, it's not possible to use a competing consumer model to distribute load across VMs. 代わりに、オーケストレーター メッセージが複数のコントロール キューに負荷分散されます。Instead, orchestrator messages are load-balanced across the control queues. この動作の詳細については、以降のセクションをご覧ください。More details on this behavior can be found in subsequent sections.

コントロール キューには、さまざまな種類のオーケストレーション ライフサイクル メッセージが含まれます。Control queues contain a variety of orchestration lifecycle message types. たとえば、オーケストレーター コントロール メッセージ、アクティビティ関数の "応答" メッセージ、タイマー メッセージがあります。Examples include orchestrator control messages, activity function response messages, and timer messages. 1 回のポーリングで 32 個のメッセージがコントロール キューからデキューされます。As many as 32 messages will be dequeued from a control queue in a single poll. これらのメッセージには、ペイロード データと、対象となるオーケストレーション インスタンスなどのメタデータが含まれています。These messages contain payload data as well as metadata including which orchestration instance it is intended for. デキューされた複数のメッセージが同じオーケストレーション インスタンスを対象としている場合、それらはバッチとして処理されます。If multiple dequeued messages are intended for the same orchestration instance, they will be processed as a batch.

ストレージ アカウントの選択Storage account selection

Durable Functions で使用されるキュー、テーブル、BLOB は、構成済みの Azure ストレージ アカウントによって作成されます。The queues, tables, and blobs used by Durable Functions are created by in a configured Azure Storage account. 使用するアカウントは、host.json ファイルの durableTask/azureStorageConnectionStringName 設定を使用して指定できます。The account to use can be specified using the durableTask/azureStorageConnectionStringName setting in host.json file.

{
  "durableTask": {
    "azureStorageConnectionStringName": "MyStorageAccountAppSetting"
  }
}

アカウントが指定されていない場合、既定の AzureWebJobsStorage ストレージ アカウントが使用されます。If not specified, the default AzureWebJobsStorage storage account is used. ただし、パフォーマンスが重視されるワークロードの場合、既定以外のストレージ アカウントを構成することをお勧めします。For performance-sensitive workloads, however, configuring a non-default storage account is recommended. Durable Functions では Azure Storage を頻繁に使用するので、専用のストレージ アカウントを使用することで、Durable Functions によるストレージの使用を、Azure Functions ホストによる内部的な使用から分離します。Durable Functions uses Azure Storage heavily, and using a dedicated storage account isolates Durable Functions storage usage from the internal usage by the Azure Functions host.

オーケストレーターのスケールアウトOrchestrator scale-out

アクティビティ関数はステートレスであり、VM の追加によって自動的にスケールアウトされます。Activity functions are stateless and scaled out automatically by adding VMs. 一方、オーケストレーター関数は、1 つまたは複数のコントロール キューにパーティション化されます。Orchestrator functions, on the other hand, are partitioned across one or more control queues. コントロール キューの数は、host.json ファイルで定義されています。The number of control queues is defined in the host.json file. 次の host.json スニペットの例では、durableTask/partitionCount プロパティを 3 に設定しています。The following example host.json snippet sets the durableTask/partitionCount property to 3.

{
  "durableTask": {
    "partitionCount": 3
  }
}

タスク ハブは、1 ~ 16 個のパーティションで構成できます。A task hub can be configured with between 1 and 16 partitions. パーティション数が指定されていない場合、既定値は 4 です。If not specified, the default partition count is 4.

複数の関数ホスト インスタンスにスケールアウトする (通常は異なる VM で実行されます) と、各インスタンスは、いずれかのコントロール キューのロックを取得します。When scaling out to multiple function host instances (typically on different VMs), each instance acquires a lock on one of the control queues. これらのロックは、内部的に Blob Storage リースとして実装され、オーケストレーション インスタンスが確実に一度に 1 つのホスト インスタンスでのみ実行されるようにします。These locks are internally implemented as blob storage leases and ensure that an orchestration instance only runs on a single host instance at a time. タスク ハブが 3 つのコントロール キューで構成されている場合、オーケストレーション インスタンスを 3 台の VM に負荷分散できます。If a task hub is configured with three control queues, orchestration instances can be load-balanced across as many as three VMs. VM を追加することで、アクティビティ関数を実行するための容量を増やすことができます。Additional VMs can be added to increase capacity for activity function execution.

次の図は、Azure Functions ホストがスケールアウトされた環境で ストレージ エンティティと対話する方法を示しています。The following diagram illustrates how the Azure Functions host interacts with the storage entities in a scaled out environment.

スケール図

前の図に示すように、作業項目キューのメッセージを取得するためにすべての VM が競合します。As shown in the previous diagram, all VMs compete for messages on the work-item queue. ただし、コントロール キューからメッセージを取得できるのは 3 台の VM のみであり、各 VM が 1 つのコントロール キューをロックします。However, only three VMs can acquire messages from control queues, and each VM locks a single control queue.

オーケストレーション インスタンスは、すべてのコントロール キュー インスタンスに配分されます。The orchestration instances are distributed across all control queue instances. 配分は、オーケストレーションのインスタンス ID をハッシュすることによって実行されます。The distribution is done by hashing the instance ID of the orchestration. インスタンス ID は既定ではランダムな GUID であり、インスタンスはすべてのコントロール キューに均等に配分されます。Instance IDs by default are random GUIDs, ensuring that instances are equally distributed across all control queues.

一般に、オーケストレーター関数は軽量であることを目的としているので、多くの処理能力を必要としません。Generally speaking, orchestrator functions are intended to be lightweight and should not require large amounts of computing power. そのため、スループットを向上させるためにコントロール キューの多数のパーティションを作成する必要はありません。It is therefore not necessary to create a large number of control queue partitions to get great throughput. 高負荷の処理の大半をステートレスなアクティビティ関数で実行することで、無限にスケールアウトできます。Most of the heavy work should be done in stateless activity functions, which can be scaled out infinitely.

自動スケールAuto-scale

従量課金プランで実行されるすべての Azure Functions と同様に、Durable Functions では、Azure Functions のスケール コントローラーによる自動スケールをサポートしています。As with all Azure Functions running in the Consumption plan, Durable Functions supports auto-scale via the Azure Functions scale controller. スケール コントローラーは、peek コマンドを定期的に発行してすべてのキューの待ち時間を監視します。The Scale Controller monitors the latency of all queues by periodically issuing peek commands. スケール コントローラーは、ピークされたメッセージの待ち時間に基づいて、VM を追加するか削除するかを決定します。Based on the latencies of the peeked messages, the Scale Controller will decide whether to add or remove VMs.

コントロール キューのメッセージ待ち時間が長すぎると判断された場合、メッセージ待ち時間が許容レベルまで低減されるか、コントロール キューのパーティション数に達するまで、VM インスタンスが追加されます。If the Scale Controller determines that control queue message latencies are too high, it will add VM instances until either the message latency decreases to an acceptable level or it reaches the control queue partition count. 同様に、作業項目キューの待ち時間が長い場合は、パーティション数に関係なく、VM インスタンスが継続的に追加されます。Similarly, the Scale Controller will continually add VM instances if work-item queue latencies are high, regardless of the partition count.

スレッドの使用Thread usage

オーケストレーター関数は、実行が多数の再生で決定論的であることを保証するために 1 つのスレッドで実行されます。Orchestrator functions are executed on a single thread to ensure that execution can be deterministic across many replays. このシングル スレッド実行のため、オーケストレーター関数のスレッドでは、CPU 集約型タスクや I/O を実行したり、何らかの理由でブロックしたりしないことが重要です。Because of this single-threaded execution, it's important that orchestrator function threads do not perform CPU-intensive tasks, do I/O, or block for any reason. I/O、ブロック、または複数のスレッドが必要になる可能性がある作業は、アクティビティ関数に移動する必要があります。Any work that may require I/O, blocking, or multiple threads should be moved into activity functions.

アクティビティ関数は、通常のキューによってトリガーされる関数とまったく同じように動作します。Activity functions have all the same behaviors as regular queue-triggered functions. アクティビティ関数では、I/O を安全に実行し、CPU 集約型操作を実行できます。また、複数のスレッドを使用することもできます。They can safely do I/O, execute CPU intensive operations, and use multiple threads. アクティビティ トリガーはステートレスであるため、無制限の VM に対して自由にスケールアウトできます。Because activity triggers are stateless, they can freely scale out to an unbounded number of VMs.

同時実行のスロットルConcurrency throttles

Azure Functions では、1 つのアプリ インスタンス内での複数の関数の同時実行をサポートしています。Azure Functions supports executing multiple functions concurrently within a single app instance. この同時実行により、並列処理を増やすことが可能になり、標準的なアプリで経時的に発生する "コールド スタート" の回数を最小限に抑えることができます。This concurrent execution helps increase parallelism and minimizes the number of "cold starts" that a typical app will experience over time. ただし、同時実行性が高いと、VM あたりのメモリ使用量が増える可能性があります。However, high concurrency can result in high per-VM memory usage. 関数アプリのニーズによっては、高負荷の状況でメモリ不足になる可能性を防ぐために、インスタンスごとの同時実行を調整することが必要になる場合があります。Depending on the needs of the function app, it may be necessary to throttle the per-instance concurrency to avoid the possibility of running out of memory in high-load situations.

アクティビティ関数とオーケストレーター関数の同時実行の制限は、どちらも host.json ファイルで構成できます。Both activity function and orchestrator function concurrency limits can be configured in the host.json file. 該当する設定は、それぞれ durableTask/maxConcurrentActivityFunctionsdurableTask/maxConcurrentOrchestratorFunctions です。The relevant settings are durableTask/maxConcurrentActivityFunctions and durableTask/maxConcurrentOrchestratorFunctions respectively.

{
  "durableTask": {
    "maxConcurrentActivityFunctions": 10,
    "maxConcurrentOrchestratorFunctions": 10,
  }
}

上記の例では、1 台の VM 上で最大 10 個のオーケストレーター関数と 10 個のアクティビティ関数を同時に実行できます。In the previous example, a maximum of 10 orchestrator functions and 10 activity functions can run on a single VM concurrently. 最大数が指定されていない場合、アクティビティ関数とオーケストレーター関数の同時実行数の上限は、VM のコア数の 10 倍に設定されます。If not specified, the number of concurrent activity and orchestrator function executions is capped at 10X the number of cores on the VM.

注意

これらの設定は、1 台の VM のメモリ使用量と CPU 使用率を管理するのに役立ちます。These settings are useful to help manage memory and CPU usage on a single VM. ただし、複数の VM にスケールアウトした場合、VM ごとに独自の一連の制限が適用されます。However, when scaled out across multiple VMs, each VM will have its own set of limits. これらの設定を使用して、グローバル レベルで同時実行を制御することはできません。These settings cannot be used to control concurrency at a global level.

オーケストレーター関数の再生Orchestrator function replay

前述のように、オーケストレーター関数は履歴テーブルの内容を使用して再生されます。As mentioned previously, orchestrator functions are replayed using the contents of the History table. 既定では、メッセージのバッチがコントロール キューからデキューされるたびに、オーケストレーター関数コードが再生されます。By default, the orchestrator function code is replayed every time a batch of messages are dequeued from a control queue.

このアグレッシブな再生動作を無効にするには、延長セッションを有効にします。This aggressive replay behavior can be disabled by enabling extended sessions. 延長セッションを有効にすると、オーケストレーター関数インスタンスがメモリに保持される期間が長くなり、フル再生なしで新しいメッセージを処理できます。When extended sessions are enabled, orchestrator function instances are held in memory longer and new messages can be processed without a full replay. 延長セッションを有効にするには、host.json ファイルで durableTask/extendedSessionsEnabledtrue に設定します。Extended sessions are enabled by setting durableTask/extendedSessionsEnabled to true in the host.json file. durableTask/extendedSessionIdleTimeoutInSeconds 設定は、アイドル セッションがメモリに保持される期間を制御するために使用します。The durableTask/extendedSessionIdleTimeoutInSeconds setting is used to control how long an idle session will be held in memory:

{
  "durableTask": {
    "extendedSessionsEnabled": true,
    "extendedSessionIdleTimeoutInSeconds": 30
  }
}

一般に、延長セッションを有効にすると、Azure ストレージ アカウントに対する I/O が減少し、全体的なスループットが向上します。The typical effect of enabling extended sessions is reduced I/O against the Azure Storage account and overall improved throughput.

ただし、この機能の潜在的な欠点の 1 つは、アイドル状態のオーケストレーター関数インスタンスがメモリに保持される期間が長くなることです。However, one potential downside of this feature is that idle orchestrator function instances will stay in memory longer. 注意すべき 2 つの影響は次のとおりです。There are two effects to be aware of:

  1. 関数アプリのメモリ使用量が全体的に増加します。Overall increase in function app memory usage.
  2. 実行時間の短いオーケストレーター関数の同時実行数が多い場合、スループットが全体的に低下します。Overall decrease in throughput if there are many concurrent, short-lived orchestrator function executions.

たとえば、durableTask/extendedSessionIdleTimeoutInSeconds を 30 秒に設定した場合、実行時間の短いオーケストレーター関数の 1 回の実行時間が 1 秒未満であっても、30 秒間メモリが占有されることになります。As an example, if durableTask/extendedSessionIdleTimeoutInSeconds is set to 30 seconds, then a short-lived orchestrator function episode that executes in less than 1 second will still occupy memory for 30 seconds. また、前述の durableTask/maxConcurrentOrchestratorFunctions クォータにもカウントされるので、他のオーケストレーター関数の実行を妨げる可能性があります。It will also count against the durableTask/maxConcurrentOrchestratorFunctions quota mentioned previously, potentially preventing other orchestrator functions from running.

注意

これらの設定は、オーケストレーター関数が十分に開発され、テストされた後にのみ使用してください。These settings should only be used after an orchestrator function has been fully developed and tested. 既定のアグレッシブな再生動作は、開発時にオーケストレーター関数のべき等エラーを検出するのに役立ちます。The default aggressive replay behavior is useful for detecting idempotency errors in orchestrator functions at development time.

パフォーマンスの目標Performance targets

運用アプリケーションに Durable Functions を使用する場合は、計画プロセスの早期にパフォーマンス要件を検討することが重要です。When planning to use Durable Functions for a production application, it is important to consider the performance requirements early in the planning process. このセクションでは、一部の基本的な使用シナリオと予想される最大スループットの数値について説明します。This section covers some basic usage scenarios and the expected maximum throughput numbers.

  • アクティビティの順次実行: このシナリオでは、オーケストレーター関数が一連のアクティビティ関数を順次実行します。Sequential activity execution: This scenario describes an orchestrator function that runs a series of activity functions one after the other. これは、関数チェーンのサンプルに最も似ています。It most closely resembles the Function Chaining sample.
  • アクティビティの並列実行: このシナリオでは、オーケストレーター関数がファンアウト/ファンイン パターンを使用して、多数のアクティビティ関数を並列実行します。Parallel activity execution: This scenario describes an orchestrator function that executes many activity functions in parallel using the Fan-out, Fan-in pattern.
  • 並列応答処理: このシナリオは、ファンアウト/ファンイン パターンの後半です。Parallel response processing: This scenario is the second half of the Fan-out, Fan-in pattern. ファンインのパフォーマンスが重視されます。It focuses on the performance of the fan-in. ファンアウトとは異なり、ファンインは 1 つのオーケストレーター関数インスタンスによって実行されるため、ファンインを実行できる VM は 1 台だけであることに注意してください。It's important to note that unlike fan-out, fan-in is done by a single orchestrator function instance, and therefore can only run on a single VM.
  • 外部イベント処理: このシナリオでは、1 つのオーケストレーター関数インスタンスが外部イベントを 1 つずつ待ちます。External event processing: This scenario represents a single orchestrator function instance that waits on external events, one at a time.

ヒント

ファンアウトとは異なり、ファンイン操作は 1 台の VM に制限されます。Unlike fan-out, fan-in operations are limited to a single VM. アプリケーションでファンアウト/ファンイン パターンを使用しており、ファンインのパフォーマンスを懸念している場合は、アクティビティ関数のファンアウトを複数のサブオーケストレーションに分けることを検討してください。If your application uses the fan-out, fan-in pattern and you are concerned about fan-in performance, consider sub-dividing the activity function fan-out across multiple sub-orchestrations.

次の表に、前述のシナリオで予想される "最大" スループットの数値を示します。The following table shows the expected maximum throughput numbers for the previously described scenarios. "インスタンス" は、Azure App Service の単一のサイズの小さい (A1) VM で実行されるオーケストレーター関数の単一のインスタンスを指します。"Instance" refers to a single instance of an orchestrator function running on a single small (A1) VM in Azure App Service. どの場合も、延長セッションが有効になっていることを前提としています。In all cases, it is assumed that extended sessions are enabled. 実際の結果は、関数コードで実行される CPU または I/O の処理によって異なる可能性があります。Actual results may vary depending on the CPU or I/O work performed by the function code.

シナリオScenario 最大スループットMaximum throughput
アクティビティの順次実行Sequential activity execution インスタンスあたり、5 アクティビティ/秒5 activities per second, per instance
アクティビティの並列実行 (ファンアウト)Parallel activity execution (fan-out) インスタンスあたり、100 アクティビティ/秒100 activities per second, per instance
並列応答処理 (ファンイン)Parallel response processing (fan-in) インスタンスあたり、150 応答/秒150 responses per second, per instance
外部イベント処理External event processing インスタンスあたり、50 イベント/秒50 events per second, per instance

注意

これらの数値は、Durable Functions 拡張機能の v1.4.0 (GA) リリース時点のものです。These numbers are current as of the v1.4.0 (GA) release of the Durable Functions extension. 機能が成熟し、最適化が行われるにつれて、これらの数値は経時的に変わる可能性があります。These numbers may change over time as the feature matures and as optimizations are made.

予想されるスループットの数値が得られず、CPU 使用率とメモリ使用量が正常と思われる場合は、原因がストレージ アカウントの正常性に関係していないかどうかを確認してください。If you are not seeing the throughput numbers you expect and your CPU and memory usage appears healthy, check to see whether the cause is related to the health of your storage account. Durable Functions 拡張機能は Azure ストレージ アカウントに大きな負荷をかける可能性があり、負荷が非常に高くなると、ストレージ アカウントのスロットルが発生する場合があります。The Durable Functions extension can put significant load on an Azure Storage account and sufficiently high loads may result in storage account throttling.

次の手順Next steps