Durable Functions ランタイムは、関数パラメーター、戻り値、およびその他の状態をtask hub に自動的に永続化して、信頼性の高い実行を提供します。 ただし、永続的なストレージに永続化されるデータの量と頻度は、アプリケーションのパフォーマンスとストレージ トランザクションのコストに影響を与える可能性があります。 アプリケーションで格納されるデータの種類によっては、データ保有とプライバシー ポリシーも考慮する必要があります。
タスク ハブの内容
タスク ハブには、インスタンスの現在の状態と保留中のメッセージが格納されます。
- インスタンスの状態 には、インスタンスの現在の状態と履歴が格納されます。 オーケストレーション インスタンスの場合、この状態にはランタイム状態、オーケストレーションの履歴、入力、出力、カスタム状態が含まれます。 エンティティ インスタンスの場合、エンティティの状態が含まれます。
- "メッセージ" には、関数の入力または出力、イベント ペイロード、ルーティングやエンド ツー エンドの関連付けなどの内部目的で使用するメタデータが格納されます。
メッセージは処理後に削除されますが、インスタンスの状態は、アプリケーションまたはオペレーターによって明示的に削除されない限り保持されます。 特に、オーケストレーションの完了後も、オーケストレーションの履歴はストレージに残ります。
状態とメッセージがオーケストレーションの進行状況を表す方法の例については、 タスク ハブの実行例を参照してください。
ストレージ内の状態とメッセージを表す場所と方法は、 ストレージ プロバイダーによって異なります。 Durable Functionsの既定のプロバイダーは Azure Storage で、指定した Azure Storage アカウント内のキュー、テーブル、BLOB にデータを保持します。
シリアル化および永続化されるデータの種類
次の一覧は、Durable Functionsの機能を使用するときにシリアル化および永続化されるさまざまな種類のデータを示しています。
- オーケストレーター、アクティビティ、およびエンティティ関数のすべての入力と出力には、任意の ID やハンドルされない例外が含まれます。
- オーケストレーター、アクティビティ、およびエンティティ関数の名前
- 外部イベントの名前とペイロード
- カスタム オーケストレーションの状態ペイロード
- オーケストレーションの終了メッセージ
- 持続的タイマー ペイロード
- 持続的な HTTP 要求と応答の URL、ヘッダー、およびペイロード
- エンティティの呼び出しとシグナル ペイロード
- エンティティ状態ペイロード
入力と出力を小さくする
DURABLE FUNCTIONS API との間で大きな入力と出力を提供すると、メモリの問題が発生する可能性があります。 入力と出力はオーケストレーション履歴にシリアル化されます。つまり、大規模なペイロードは時間の経過と同時に、無制限の履歴の増加に大きく貢献できます。 この増加は 、再生中にメモリ例外を引き起こすリスクがあります。
大きな入力と出力の影響を軽減するには、次の操作を行います。
- サブオーケストレーターに作業を委任して、複数のオーケストレーター間で履歴のメモリ負荷を負荷分散し、個々の履歴のメモリ占有領域を小さく保ちます。
- 外部ストレージ (Azure Blob Storage など) に大きなデータを格納し、必要に応じてアクティビティ関数内でそのデータを取得できるようにする軽量識別子を渡します。
ヒント
大規模なデータを処理するためのベスト プラクティスは、外部ストレージに保持し、必要に応じてアクティビティ内でのみそのデータを具体化することです。
機密性の高いデータの使用
Durable Functions API との間の入力と出力 (例外を含む) は、選択した storage プロバイダーに永続的に保持されます。 これらの入力、出力、または例外に機密データ (シークレット、接続文字列、個人を特定できる情報など) が含まれている場合は、ストレージ プロバイダーのリソースへの読み取りアクセス権を持つすべてのユーザーがそれらを取得できます。
機密データを安全に処理するには、アクティビティ関数内のデータをAzure Key Vaultまたは環境変数からフェッチし、オーケストレーターまたはエンティティとの間でそのデータを直接またはやり取りしないようにします。 この方法は、機密データがストレージ リソースに漏えいするのを防ぐのに役立ちます。
ヒント
このガイダンスは、 オーケストレーター API にも適用され、要求と応答のペイロードがストレージに保持されます。 ターゲット HTTP エンドポイントで認証が必要な場合は、アクティビティ内に HTTP 呼び出しを実装するか、 CallHttp によって提供される組み込みのマネージド ID サポートを使用します。これは、資格情報をストレージに保持しません。
注
ログへの読み取りアクセス権を持つすべてのユーザー (Application Insights など) がそれらのシークレットを取得する可能性がある場合は、シークレットを含むデータをログに記録しないようにします。
Azure Storage プロバイダーを使用すると、すべてのデータが保存時に自動的に暗号化されます。 ただし、ストレージ アカウントへのアクセス権を持つユーザーは、暗号化されていない形式でデータを読み取ることができます。 機密データのより強力な保護が必要な場合は、事前に暗号化された形式でデータが永続化されるように、最初に独自の暗号化キーを使用してデータを暗号化することを検討してください。
または、.NETユーザーには、自動暗号化を提供するカスタム シリアル化プロバイダーを実装するオプションがあります。 暗号化を使用したカスタムシリアル化の例は、このGitHubサンプルで確認できます。
注
アプリケーション レベルの暗号化を実装する場合は、オーケストレーションとエンティティが無期限に存在する可能性があることに注意してください。 オーケストレーションまたはエンティティはキーのローテーション ポリシーよりも長く実行される可能性があるため、暗号化キーをローテーションするときにこれが重要になります。 キーのローテーションが行われると、データの暗号化に使用されたキーが、次にオーケストレーションまたはエンティティを実行したときに復号化できなくなる可能性があります。 このため、ユーザー暗号化は、オーケストレーションとエンティティの実行時間が比較的短い場合にのみ推奨されます。
シリアル化と逆シリアル化のカスタマイズ
既定のシリアル化のロジック
.NETインプロセスのDurable Functionsでは、内部的に Json.NET を使用してオーケストレーションとエンティティ データを JSON にシリアル化します。 使用される既定の Json.NET 設定は次のとおりです。
入力、出力、および状態:
JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.None,
DateParseHandling = DateParseHandling.None,
}
例外:
JsonSerializerSettings
{
ContractResolver = new ExceptionResolver(),
TypeNameHandling = TypeNameHandling.Objects,
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
}
に関する詳細なドキュメントについては、こちらを参照してください。
.NET属性を使用したシリアル化のカスタマイズ
シリアル化中、Json.NET は、データを JSON にシリアル化およびデシリアル化する方法を制御するさまざまな属性をクラスやプロパティに探します。 Durable Functions API に渡されるデータ型のソース コードを所有している場合は、シリアル化と逆シリアル化をカスタマイズするために、これらの属性を型に追加することを検討してください。
依存関係の挿入によるシリアル化のカスタマイズ
.NETを対象とし、Functions V3 ランタイムで実行する関数アプリは、Dependency Injection (DI) を使用して、データと例外のシリアル化方法をカスタマイズできます。 次のサンプル コードは、DI を使用して、IMessageSerializerSettingsFactory および IErrorSerializerSettingsFactory サービス インターフェイスのカスタム実装を使用して、既定の Json.NET シリアル化設定をオーバーライドする方法を示しています。
using Microsoft.Azure.Functions.Extensions.DependencyInjection;
using Microsoft.Azure.WebJobs.Extensions.DurableTask;
using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json;
using System.Collections.Generic;
[assembly: FunctionsStartup(typeof(MyApplication.Startup))]
namespace MyApplication
{
public class Startup : FunctionsStartup
{
public override void Configure(IFunctionsHostBuilder builder)
{
builder.Services.AddSingleton<IMessageSerializerSettingsFactory, CustomMessageSerializerSettingsFactory>();
builder.Services.AddSingleton<IErrorSerializerSettingsFactory, CustomErrorSerializerSettingsFactory>();
}
/// <summary>
/// A factory that provides the serialization for all inputs and outputs for activities and
/// orchestrations, as well as entity state.
/// </summary>
internal class CustomMessageSerializerSettingsFactory : IMessageSerializerSettingsFactory
{
public JsonSerializerSettings CreateJsonSerializerSettings()
{
// Return your custom JsonSerializerSettings here
}
}
/// <summary>
/// A factory that provides the serialization for all exceptions thrown by activities
/// and orchestrations
/// </summary>
internal class CustomErrorSerializerSettingsFactory : IErrorSerializerSettingsFactory
{
public JsonSerializerSettings CreateJsonSerializerSettings()
{
// Return your custom JsonSerializerSettings here
}
}
}
}