Durable Functionsには、永続的なオーケストレーションとエンティティを HTTP ワークフローに簡単に組み込むことができるいくつかの機能があります。 この記事では、これらの機能の一部について詳しく説明します。
HTTP API の公開
オーケストレーションとエンティティは、HTTP 要求を使用して起動および管理できます。 Durable Functions拡張機能は、組み込みの HTTP API を公開します。 また、HTTP によってトリガーされる関数内からオーケストレーションやエンティティと対話する API も用意されています。
組み込みの HTTP API
Durable Functions拡張機能は、一連の HTTP API を Azure Functions ホストに自動的に追加します。 これらの API を使用すると、コードを書くことなく、オーケストレーションやエンティティとの対話や管理を行うことができます。
次の組み込みの HTTP API がサポートされています。
- 新しいオーケストレーションを開始する
- オーケストレーション インスタンスのクエリを実行する
- オーケストレーション インスタンスを終了する
- オーケストレーションに外部イベントを送信する
- オーケストレーション履歴を消去する
- エンティティに操作イベントを送信する
- エンティティの状態を取得する
- エンティティの一覧を問い合わせる
Durable Functions拡張機能によって公開されるすべての組み込み HTTP API の詳細については、HTTP API に関する記事を参照してください。
HTTP API URL の検出
オーケストレーション クライアントのバインドにより、便利な HTTP 応答ペイロードを生成できる API が公開されます。 たとえば、特定のオーケストレーション インスタンスの管理 API へのリンクを含む応答を作成できます。 次の例では、この API を新しいオーケストレーション インスタンスに使用する方法を示す HTTP トリガー関数を示します。
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.DurableTask;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Extensions.Logging;
namespace VSSample
{
public static class HttpStart
{
[FunctionName("HttpStart")]
public static async Task<HttpResponseMessage> Run(
[HttpTrigger(AuthorizationLevel.Function, methods: "post", Route = "orchestrators/{functionName}")] HttpRequestMessage req,
[DurableClient] IDurableClient 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);
}
}
}
前述の HTTP トリガー関数を使用したオーケストレーター関数の開始は、任意の HTTP クライアントを使用して実行できます。 次の cURL コマンドでは、 という名前のオーケストレーター関数を開始します。
curl -X POST https://localhost:7071/orchestrators/DoWork -H "Content-Length: 0" -i
次に、ID が指定されたオーケストレーションに対する応答の例を示します。 わかりやすくするために、細部をいくらか省略しています。
HTTP/1.1 202 Accepted
Content-Type: application/json; charset=utf-8
Location: http://localhost:7071/runtime/webhooks/durabletask/instances/abc123?code=XXX
Retry-After: 10
{
"id": "abc123",
"purgeHistoryDeleteUri": "http://localhost:7071/runtime/webhooks/durabletask/instances/abc123?code=XXX",
"sendEventPostUri": "http://localhost:7071/runtime/webhooks/durabletask/instances/abc123/raiseEvent/{eventName}?code=XXX",
"statusQueryGetUri": "http://localhost:7071/runtime/webhooks/durabletask/instances/abc123?code=XXX",
"terminatePostUri": "http://localhost:7071/runtime/webhooks/durabletask/instances/abc123/terminate?reason={text}&code=XXX"
}
前の例では、末尾に が付く各フィールドは、組み込みの HTTP API に対応しています。 これらの API を使用して、ターゲット オーケストレーション インスタンスを管理できます。
注
webhook URL の形式は、実行しているAzure Functions ホストのバージョンによって異なります。 前の例は、Azure Functions 2.0 ホスト用です。
すべての組み込みの HTTP API の詳細については、「HTTP API リファレンス」を参照してください。
非同期操作の追跡
前述の HTTP 応答は、Durable Functionsで実行時間の長い HTTP 非同期 API を実装するために設計されています。 このパターンは、ポーリング コンシューマー パターンと呼ばれる場合もあります。 クライアント/サーバー フローは次のように動作します。
- クライアントが、オーケストレーター関数など、実行時間の長いプロセスを開始する HTTP 要求を発行します。
- ターゲット HTTP トリガーは、"statusQueryGetUri" の値を持つ Location ヘッダーを含む HTTP 202 応答を返します。
- クライアントが Location ヘッダー内の URL をポーリングします。 クライアントは引き続き、Location ヘッダーを含む HTTP 202 応答を参照します。
- インスタンスが終了 (または失敗) すると、Location ヘッダー内のエンドポイントから HTTP 200 が返されます。
このプロトコルでは、HTTP エンドポイントのポーリングと Location ヘッダーのフォローをサポートする、外部のクライアントまたはサービスでの実行時間の長いプロセスを調整できます。 このパターンのクライアント実装とサーバー実装の両方が、Durable Functions HTTP API に組み込まれています。
注
既定では、Azure Logic Apps によって提供されるすべての HTTP ベースのアクションは、標準の非同期操作パターンをサポートします。 この機能により、実行時間の長い Durable Functions を Logic Apps ワークフローの一部として組み込むことができます。 非同期 HTTP パターンに対する Logic Apps のサポートの詳細については、Azure Logic Apps ワークフロー アクションとトリガーに関するドキュメントを参照してください。
注
オーケストレーションとの対話は、HTTP によってトリガーされる関数だけでなく、任意の関数型から実行できます。
クライアント API を使用してオーケストレーションとエンティティを管理する方法の詳細については、インスタンスの管理に関する記事を参照してください。
HTTP API の利用
オーケストレーター コードの制約で説明されているように、オーケストレーター関数は I/O を直接実行できません。 代わりに、通常は I/O 操作を行う アクティビティ を呼び出します。
Durable Functions 2.0 以降では、オーケストレーションは、orchestration トリガー バインドを使用して、HTTP API をネイティブに使用できます。
次のコード例は、送信 HTTP 要求を行うオーケストレーター関数を示しています。
[FunctionName(nameof(CheckSiteAvailable))]
public static async Task CheckSiteAvailable(
[OrchestrationTrigger] IDurableOrchestrationContext context)
{
Uri url = context.GetInput<Uri>();
// Makes an HTTP GET request to the specified endpoint
DurableHttpResponse response =
await context.CallHttpAsync(HttpMethod.Get, url);
if (response.StatusCode >= 400)
{
// handling of error codes goes here
}
}
注
この機能が組み込みの .NET HttpRequestMessage 型や HttpResponseMessage 型の代わりに、なぜ DurableHttpRequest と DurableHttpResponse の型を使用するのか疑問に思うかもしれません。
この設計の選択は意図的なものです。 主な理由は、カスタム型を使用することで、内部 HTTP クライアントのサポートされている動作についてユーザーが誤った想定を行うことを回避するためです。 Durable Functionsに固有の型を使用すると、API の設計を簡略化することもできます。 また、マネージド ID の統合やポーリング コンシューマー パターンなどの特別な機能を、より簡単に利用できるようになります。
"call HTTP" アクションを使用して、オーケストレーター関数で次のアクションを実行できます。
- オーケストレーション関数から HTTP API を直接呼び出す (後述するいくつかの制限があります)。
- クライアント側の HTTP 202 状態ポーリング パターンを自動的にサポートする。
- Azureマネージド ID を使用して、他のAzure エンドポイントに対して承認された HTTP 呼び出しを行います。
オーケストレーター関数から HTTP API を直接使用する機能は、一般的なシナリオの特定のセットに合わせた利便性が意図されています。 これらの機能はいずれも、アクティビティ関数を使用して自分で実装できます。 多くの場合、アクティビティ関数を使用すると、柔軟性が向上します。
HTTP 202 の処理 (.NETのみ)
"call HTTP" API では、ポーリング コンシューマー パターンのクライアント側を自動的に実装できます。 呼び出された API から Location ヘッダーを含む HTTP 202 応答が返される場合、202 以外の応答が返されるまで、オーケストレーター関数では Location リソースが自動的にポーリングされます。 この応答は、オーケストレーター関数コードに返される応答です。
[FunctionName(nameof(CheckSiteAvailabilityWithPolling))]
public static async Task CheckSiteAvailabilityWithPolling(
[OrchestrationTrigger] IDurableOrchestrationContext context)
{
Uri url = context.GetInput<Uri>();
// HTTP automatic polling on 202 response is enabled by default in .NET in-process.
DurableHttpResponse response =
await context.CallHttpAsync(HttpMethod.Get, url);
}
注
- オーケストレーター関数は、「非同期操作の追跡」で説明されているように、サーバー側のポーリング コンシューマー パターンもネイティブでサポートします。 このサポートにより、1 つの関数アプリ内のオーケストレーションで、他の関数アプリのオーケストレーター関数を簡単に調整できます。 これは、サブオーケストレーションの概念と似ていますが、アプリ間通信がサポートされています。 このサポートは、マイクロサービススタイルのアプリ開発に特に役立ちます。
- 組み込みの HTTP ポーリング パターンは現在、.NET ホストでのみ使用できます。
- ポーリング パターンは、.NETインプロセスでは既定で有効になっていますが、.NET Isolated では既定で無効になっています。 .NET Isolated で有効にする場合は、サンプル コードを参照し、asynchronousPatternEnabled 引数を true に設定します。
- HTTP 自動ポーリングパターンは、Durable Functions .NET Isolated バージョン v1.5.0 以降でサポートされています。
マネージド アイデンティティ
Durable Functionsは、承認のためにMicrosoft Entraトークンを受け入れる API の呼び出しをネイティブにサポートします。 このサポートでは、Azure マネージド ID を使用してこれらのトークンを取得します。
次のコードは、オーケストレーター関数の例です。 この関数は、Azure Resource Manager 仮想マシン REST API を使用して、仮想マシンを再起動するための認証済み呼び出しを行います。
[FunctionName("RestartVm")]
public static async Task RunOrchestrator(
[OrchestrationTrigger] IDurableOrchestrationContext context)
{
string subscriptionId = "mySubId";
string resourceGroup = "myRG";
string vmName = "myVM";
string apiVersion = "2019-03-01";
// Automatically fetches an Azure AD token for resource = https://management.core.windows.net/.default
// and attaches it to the outgoing Azure Resource Manager API call.
var restartRequest = new DurableHttpRequest(
HttpMethod.Post,
new Uri($"https://management.azure.com/subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}/providers/Microsoft.Compute/virtualMachines/{vmName}/restart?api-version={apiVersion}"),
tokenSource: new ManagedIdentityTokenSource("https://management.core.windows.net/.default"));
DurableHttpResponse restartResponse = await context.CallHttpAsync(restartRequest);
if (restartResponse.StatusCode != HttpStatusCode.OK)
{
throw new ArgumentException($"Failed to restart VM: {restartResponse.StatusCode}: {restartResponse.Content}");
}
}
前の例では、tokenSource パラメーターは、Azure Resource Manager のMicrosoft Entra トークンを取得するように構成されています。 このトークンは、リソース URI によって識別されます。 この例では、現在の関数アプリがローカルで実行されているか、マネージド ID を使用する関数アプリとしてデプロイ済みであることを前提としています。 ローカル ID またはマネージド ID は、指定されたリソース グループ 内の VM を管理できるアクセス許可を持っていると見なされます。
実行時に、構成されたトークン ソースにより OAuth 2.0 アクセス トークンが自動的に返されます。 次に、ソースによって、送信要求の Authorization ヘッダーにトークンがベアラー トークンとして追加されます。 このモデルは、次の理由により、Authorization ヘッダーを HTTP 要求に手動で追加するよりも優れています。
- トークンの更新は自動的に処理されます。 期限切れのトークンについて心配する必要はありません。
- トークンは、持続的なオーケストレーション状態には格納されません。
- トークンの取得を管理するコードを記述する必要はありません。
より完全な例については、定義済みの C# RestartVMs サンプルを参照してください。
マネージド ID は、Azureリソース管理に限定されません。 マネージド ID を使用して、Microsoft の Azure サービスやパートナーの Web アプリを含め、Microsoft Entra のベアラー トークンを受け入れる任意の API にアクセスできます。 パートナーの Web アプリを別の関数アプリにすることもできます。 Microsoft Entra IDによる認証をサポートする Microsoft のAzure サービスの一覧については、「Microsoft Entra認証をサポートする Azure サービスを参照してください。
制限事項
HTTP API を呼び出す組み込みのサポートは便利な機能です。 これは、すべてのシナリオに適しているわけではありません。
オーケストレーター関数によって送信された HTTP 要求とその応答は、Durable Functions ストレージ プロバイダーのメッセージとしてシリアライズおよび永続化されます。 この永続キュー動作によって、HTTP 呼び出しで信頼性が高く、安全にオーケストレーションを再生することが保証されます。 ただし、永続キュー動作にも制限事項があります。
- 各 HTTP 要求では、ネイティブの HTTP クライアントと比較すると、追加の待機時間が発生します。
- 構成された記憶域プロバイダーによっては、大規模な要求または応答メッセージによって、オーケストレーションのパフォーマンスが大幅に低下する可能性があります。 たとえば、Azure Storageを使用する場合、キュー メッセージに収まらない大きすぎる HTTP ペイロードAzure圧縮され、Azure Blob Storage に格納されます。
- ストリーミング、チャンク、およびバイナリのペイロードはサポートされません。
- HTTP クライアントの動作をカスタマイズする機能は制限されています。
これらの制限事項のいずれかがお客様のユースケースに影響する可能性がある場合は、代わりにアクティビティ関数と言語固有の HTTP クライアント ライブラリを使用して送信 HTTP 呼び出しを行うことを検討してください。
拡張性 (.NETインプロセスのみ)
オーケストレーションの内部 HTTP クライアントの動作をカスタマイズするには、インプロセス ワーカーのAzure Functions .NET依存関係の挿入を使用します。 この機能は、小規模な動作変更を行う場合に役立ちます。 これは、モック オブジェクトを挿入することによる、HTTP クライアントの単体テストにも役立ちます。
次の例では、外部 HTTP エンドポイントを呼び出すオーケストレーター関数に対する TLS/SSL 証明書の検証を無効にするために、依存関係の挿入を使用する方法を示します。
public class Startup : FunctionsStartup
{
public override void Configure(IFunctionsHostBuilder builder)
{
// Register own factory
builder.Services.AddSingleton<
IDurableHttpMessageHandlerFactory,
MyDurableHttpMessageHandlerFactory>();
}
}
public class MyDurableHttpMessageHandlerFactory : IDurableHttpMessageHandlerFactory
{
public HttpMessageHandler CreateHttpMessageHandler()
{
// Disable TLS/SSL certificate validation (not recommended in production!)
return new HttpClientHandler
{
ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator,
};
}
}
次のステップ
持続性のあるエンティティについて学習します