[Azure Functions] Durable Functions とキューストレージ・テーブルストレージの関係について

記事内に広告が含まれています。

Durable functions の概要

Azureのサーバレスのサービスとして Azure Functions があり、これの拡張機能としてのサービス。Azure Functionsに比べて長時間稼働などが可能となる。一言で簡略化していえば、

状態管理・再実行により長時間稼働に対応できる Azure Functions

と言えるかと思う。

Durable Functions は、Azure Functions の拡張機能であり、オーケストレーター、アクティビティ、エンティティ関数をコードに記述することで、サーバーレス環境でステートフル ワークフローを構築できます。 Durable Functions ランタイムは、状態、チェックポイント、再試行、復旧を管理するため、ワークフローを長期間にわたって確実に実行できます。

Durable Functions の概要: ステートフル サーバーレス ワークフロー
Durable Functions Azure Functionsを拡張して、サーバーレス環境で信頼性の高いステートフル ワークフローを構築する方法について説明します。 サポートされている言語、ストレージプロバイダー、クイックスタートの利用…

長時間稼働をするため、各タスクの進行状況をサーバだけでなくストレージアカウントを用いて管理するような仕組みになっている。

  • キューストレージ
  • テーブルストレージ

Task Hubとキュー・テーブルストレージの関係

durable functions の名前を付けることができ、公式ドキュメントでは Task Hub という名前で定義されている。Task Hub はストレージ管理のための論理的な単位としてみなせる。

# host.json
{
  "version": "2.0",
  "extensions": {
    "durableTask": {
      "hubName": "xyz"  # ここがTaskhub名
    }
  }
}

この Task Hub 名を使って、キューストレージ・テーブルストレージのテーブル名が作成される。

キューストレージ・テーブルストレージのうち、以下の4つが重要。

  • インスタンステーブル(左から一つ目の instances と記載のもの)
  • 履歴テーブル(左から2つ目の History と記載のもの)
  • 作業項目キュー(左から3つ目の Work items と記載のもの)
  • コントロールキュー(左4つ目の Control-00)

これらのストレージの名前は、Task Hub の名前から始まるようになっている。(インスタンステーブルであれば、<TaskHub名>Instances )

durable functions をトリガーした際、インスタンスIDという一意のIDが自動生成される。

instance_id = await client.start_new()  # ここでインスタンスIDが生成

インスタンスIDはインスタンスの識別子であり、これが キューストレージ・テーブルストレージの各種テーブルのキーとして利用される。(=どのインスタンスがもつレコードかが判別できるようになっている)

各種ストレージの役割について

キューストレージ

作業項目キューは、実行待ちのアクティビティを管理するためのもの。以下のメソッドでアクティビティが呼び出されるとこのキューの中に格納され、オーケストレータが順次実行していく。

# pythonランタイム
result1 = yield context.call_activity(...)

コントロールキューはオーケストレータの管理用のキューとなっている。作業項目キューのアクティビティが完了すると、レスポンスなどの情報がこのキューへ格納される。

テーブルストレージ

キューストレージはメッセージ配信に利用されており、永続的に管理するためにテーブルストレージが必要となる。永続的に保管できるため、durable functions のリプレイ時が可能となる。

  • コントロールキューの内容は一時的な保管のため、永続的に管理するために履歴テーブルが必要になる。
  • インスタンステーブルにはインスタンスIDの情報(ステータス、作成日時等)が格納されている

durable functionsの大まかな処理の流れ

HTTP トリガーされた場合を想定。公式ドキュメントのコード例を参考に、durable の処理とキュー・テーブルの関係性を概略的に整理する。

# クライアント関数
@app.route(route="StartChaining", methods=["POST"])
@app.durable_client_input(client_name="client")
async def start_chaining(req: func.HttpRequest, client) -> func.HttpResponse:
    """HTTP trigger to start the function chaining orchestration."""
    instance_id = await client.start_new("chaining_orchestration")
    logging.info(f"Started chaining orchestration with ID = '{instance_id}'.")
    return client.create_check_status_response(req, instance_id)

# アクティビティ関数
@app.activity_trigger(input_name="city")
def say_hello(city: str) -> str:
    """Activity function that returns a greeting for a city."""
    logging.info(f"Saying hello to {city}.")
    return f"Hello {city}!"

# オーケストレータ関数
@app.orchestration_trigger(context_name="context")
def chaining_orchestration(context: df.DurableOrchestrationContext):
    """Function chaining orchestration: calls activities sequentially."""
    result1 = yield context.call_activity("say_hello", "Tokyo")
    result2 = yield context.call_activity("say_hello", "Seattle")
    result3 = yield context.call_activity("say_hello", "London")
    return [result1, result2, result3]
HTTP trigger
↓
クライアント関数のインスタンス生成(client.start_new())
↓
インスタンステーブルに新規追加・管理される
↓
オーケストレータ関数がアクティビティをスケジュール(context.call_activity())
↓
作業項目キューにアクティビティが追加・管理
↓
アクティビティ関数がアクティビティを処理
↓
コントロールキューへレスポンス
↓
オーケストレータがヒストリーテーブルを使ってリプレイしながら処理を進める

参考

Durable Functions 向け Azure Storage プロバイダー – Durable Task
Durable Functions 用 Azure Storage プロバイダーがキュー、テーブル、BLOB を使用して状態を格納する方法について説明します。 オーケストレーションのパフォーマンスを構成して最適化します。
クイック スタート: Python Durable Functions アプリを作成する
Durable Task Scheduler エミュレーターを使用して、関数チェーンとファンアウト/ファンイン パターンを使用して、Python Durable Functionsサンプル アプリを実行します。 今すぐ始めましょう。
Durable Functions を始めるときに知っていると幸せになれる7つの Tip – Qiita
Durable Functions に初めて入門する方のために、Durable Functions を始めるときに知っておくと良い7つのティップスをまとめておきました。英語のオリジナルはこちらです。 Tip 1. クラスと責務 Tip 2….
AWS, Azure
スポンサーリンク