Azure Functions トリガー・バインディング シリーズ - Azure Cosmos DB トリガー

Published: feedback 共有

Azure Cosmos DB トリガー は Azure Cosmos DB の 変更フィード を利用し、Azure Cosmos DB のコンテナーに対するドキュメントの作成・更新を検知して実行される関数です。

Azure Cosmos DB トリガーは、内部的に Azure Cosmos DB SDK の変更フィード プロセッサを利用して動作しています。Azure Functions Host は起動時に変更フィード プロセッサ (ChangeFeedProcessor) のインスタンスを構築し、監視対象のコンテナーに対してポーリングを行います。変更が検出されると、変更されたドキュメントのコレクションをトリガーの入力として関数が実行されます。

動作の仕組み

Azure Cosmos DB トリガーの動作は以下の流れとなります。

  1. 変更フィード プロセッサの構築: Azure Functions Host が ChangeFeedProcessorBuilder を利用して変更フィード プロセッサを構築します。この際、監視対象コンテナーとリース コンテナーへの参照が設定されます。
  2. ポーリング: 変更フィード プロセッサが監視対象コンテナーの各物理パーティションに対してポーリングを行い、変更を検出します。ポーリング間隔は FeedPollDelay 属性で制御でき、既定値は 5,000 ミリ秒 (5 秒) です。
  3. リースの管理: 各パーティションの処理進行状況は「リース」と呼ばれる仕組みで管理され、専用のリース コンテナーにチェックポイント情報として格納されます。リース コンテナーの既定名は leases です。
  4. 関数の実行: 変更が検出されると、変更されたドキュメントのコレクション (IReadOnlyCollection<T>) を引数として関数が実行されます。
  5. チェックポイントの更新: 関数の実行が正常に完了すると、リース コンテナーのチェックポイントが更新され、処理済み位置が記録されます。関数実行が失敗した場合はチェックポイントが更新されず、次のポーリングで同じ変更が再度処理されます。

※ Azure Cosmos DB トリガーは既定の変更フィード モード (LatestVersion) で動作し、各ドキュメントの最新バージョンの変更のみを処理します。ドキュメントの削除は検知されず、中間バージョンも取得されません。Azure Cosmos DB には削除や中間バージョンの変更も取得できる AllVersionsAndDeletes モード(プレビュー機能)が存在しますが、Azure Functions トリガーではこのモードはサポートされていません。削除や全バージョンの変更を処理する必要がある場合は、変更フィード プル モデル変更フィード プロセッサを直接使用する方法をご検討ください。

リースについて

リースは Azure Cosmos DB の変更フィード プロセッサが処理の進行状況を追跡するための仕組みです。リースの状態は専用のリース コンテナーに格納され、リース コンテナー内の各ドキュメントが監視対象コンテナーの物理パーティション範囲に対応しています。

リース コンテナーの構成

リース コンテナーは、変更フィード プロセッサが各物理パーティションの処理位置(チェックポイント)やリースの所有権情報を永続化するための専用コンテナーです。変更フィード プロセッサが複数のインスタンス間でパーティションの処理を分散・調整する際にも、このリース コンテナーが中心的な役割を果たします。

リース コンテナーは、監視対象のコンテナーとは異なるコンテナーである必要があります。ソースコード上で監視対象コンテナーとリース コンテナーが同一の場合はエラーが発生するよう検証されています。

リース コンテナーの配置先や接続先、リース コンテナー自体の構成に関する設定はトリガーの属性で設定できます。

属性 既定値 説明
LeaseContainerName leases リース コンテナーの名称
LeaseDatabaseName 監視対象と同じデータベース リース コンテナーが存在するデータベース名
LeaseConnection Connection と同じ接続先 リース コンテナーの接続文字列(監視対象と異なる Cosmos DB アカウントにリースを配置する場合に設定)
CreateLeaseContainerIfNotExists false リース コンテナーが存在しない場合に自動作成するかどうか。接続文字列認証時のみ有効です。マネージド ID (Entra ID) 認証時はコンテナーの作成が許可された操作ではないため使用できません。リース コンテナーを事前に作成してください
LeasesContainerThroughput 0 (未設定) 自動作成時のリース コンテナーのスループット
LeaseContainerPrefix なし リース ドキュメントのプレフィックス。同一のリース コンテナーを複数トリガーで共有する場合に有用

リースのパラメーター

リースの更新間隔や有効期限といった動作に関する主要なパラメーターは以下の通りです。

パラメーター 既定値 説明
LeaseRenewInterval 17,000 ミリ秒 (17 秒) 現在保持しているリースの更新間隔
LeaseAcquireInterval 13,000 ミリ秒 (13 秒) パーティションが既知のホスト インスタンス間で均等に分散されているかを検出するタスクを開始する間隔
LeaseExpirationInterval 60,000 ミリ秒 (60 秒) リースの有効期限。この期間内にリースが更新されない場合、リースが失効し、他のインスタンスに所有権が移動

ソースコード上では、CosmosDBTriggerListenerInitializeBuilder メソッドにて ChangeFeedProcessorBuilder にこれらのリースパラメーターが設定されています。

※ リースの失効や再取得が発生した場合、CosmosDBTriggerHealthMonitor にて PreconditionFailed (HTTP 412) のログが記録されることがあります。スケーリングや初期化時のリース再分散中に一時的に発生するのは想定された動作となりますが、412 が継続的に発生し、かつ変更フィードの処理が進行していない場合は、リース競合やインスタンス間の構成不整合が疑われるため、リース コンテナーの状態やインスタンス数を確認してください。

作成手順

Azure Cosmos DB トリガーの作成方法はチュートリアルで紹介されているテンプレートをご利用ください。チュートリアルでは HTTP トリガーを利用しておりますが、同画面にて Cosmos DB トリガーを選択いただけます。その後、ローカル環境にて実行した際に接続する Cosmos DB の環境を選択しますが、その際に Azure 上のリソースを参照させずに エミュレーター を使用することも可能なため、要件に合わせて選択ください。

Cosmos DB の環境選択画面:

image.png

また、各属性情報は、アプリケーション設定にて管理できます。C# の例ですが、CosmosDBTrigger の引数で各属性情報を % 括りのアプリケーション設定名とします(上段黄色枠)。ローカルの実行のため local.settings.json となりますが(下段黄色枠)、設定値の中身を宣言します。

Cosmos DB の接続文字列については Connection プロパティで指定した値と一致する名前のアプリケーション設定(青色枠)を定義します。

Azure 上の Azure Functions リソースの場合には local.settings.json にて定義いただいた同項目をアプリケーション設定に設定してください。

例:

image.png

実行状況をログで確認する

Cosmos DB トリガーの実行詳細をログから確認します。host.json の logging で下記のカテゴリのログを出力するように設定します。デバッグ用となるため、運用状況によって有効/無効化を検討ください。

host.json

1
2
3
4
5
6
"logging": {
"logLevel": {
"Microsoft.Azure.WebJobs.Hosting": "Debug",
"Host.Triggers.CosmosDB": "Debug"
}
}

Application Insights で利用するクエリ

1
2
3
4
5
traces
| where timestamp > datetime("yyyy-mm-dd hh:mi")
| where customDimensions.Category startswith "Host.Triggers.CosmosDB" or operation_Name =~ "<関数名>"
| project timestamp, message, customDimensions
| order by timestamp asc

上記の設定を行った際に記録されるログの例です。

リスナーの開始

Azure Functions Host 起動時に、変更フィード プロセッサのリスナーが開始されます。Host.Triggers.CosmosDB カテゴリにて ”Started the listener for ~” というログが記録されます。
リスナーが正常に開始されたこと、監視対象のコンテナーとリース コンテナーの情報を確認できます。

traces ログ:

image.png

リースの取得・解放,変更の配信

変更フィード プロセッサがリースを取得・解放した際に、以下のログ(黄色ハイライト)が記録されます。

  • 取得: Lease {LeaseToken} was acquired to start processing.
  • 解放: Lease {LeaseToken} was released.

変更フィードから変更を取得して関数に配信した際には下記のログ(青色ハイライト)が記録されます。

  • Events delivered to lease {LeaseToken}, Continuation {Continuation} with diagnostics {Diagnostics}

traces ログ:

image.png

実行ログ

Cosmos DB の変更フィードが読み込まれることで、トリガーの実行され、Executing~Executed~ が記録されます。

traces ログ:

image.png

並行処理とチューニング

並行処理の考え方

Cosmos DB トリガーの並行処理は、監視対象コンテナーの物理パーティション数ホスト インスタンス数の関係で決まります。

変更フィード プロセッサは、監視対象コンテナーの各物理パーティションに対してリースを作成します。1 つのリースは同時に 1 つのホスト インスタンスのみが保持できるため、物理パーティション数がインスタンス間の並行処理の上限となります。

例えば、監視対象コンテナーに 4 つの物理パーティションがある場合:

  • インスタンス 1 台: 1 台で 4 つのパーティション全てを処理
  • インスタンス 2 台: 各インスタンスが 2 つのパーティションを処理
  • インスタンス 4 台: 各インスタンスが 1 つのパーティションを処理
  • インスタンス 5 台以上: 4 台が各 1 パーティション、残りのインスタンスはアイドル状態

この動作は Azure Cosmos DB 変更フィード プロセッサのドキュメントにも記載されています。

トリガー動作のチューニング

トリガー実行の際に受信する最大件数やポーリング間隔、処理を行う開始位置の調整などのトリガーの動作をチューニングする場合は以下のパラメーターを変更します。

パラメーター 既定値 説明
MaxItemsPerInvocation 0 (未設定) 1 回のトリガー実行で受け取るドキュメントの最大件数。未設定 (0) の場合、Azure Cosmos DB SDK の既定動作に従います
FeedPollDelay 5,000 ミリ秒 (5 秒) 変更フィードのポーリング間隔。現在の変更が全て処理された後に次のポーリングを行うまでの遅延時間
StartFromBeginning false コンテナーの先頭から変更の読み取りを開始するかどうか。リースの状態が既に存在する場合、この設定は無視されます
StartFromTime なし 変更フィードの読み取り開始位置を日時で指定。例: 2021-02-16T14:19:29Z。リースの状態が既に存在する場合、この設定は無視されます
PreferredLocations なし geo レプリケーションされたアカウントの優先リージョン(カンマ区切り)

StartFromBeginningStartFromTime は同時に設定することはできません。ソースコード上で両方が設定された場合は InvalidOperationException がスローされます。また、これらの設定はリース コンテナーにチェックポイント情報がまだ存在しない初回開始時のみ有効です。一度リースの状態が作成された後は、変更しても影響しません。

スケーリングの仕組み

従量課金プラン、Flex 従量課金プランおよび Elastic Premium プランでは、Cosmos DB トリガーはターゲットベースのスケーリングによりインスタンス数が制御されます。スケーリング判断には以下の指標が使用されます。

  • パーティション数: リース コンテナーから取得された物理パーティション数
  • 残りの変更件数 (RemainingWork): 変更フィード エスティメーター (ChangeFeedEstimator) を使用して各パーティションの未処理の変更推定数の合計を計算

ターゲットベースのスケーリングでは、残りの変更件数を同時実行数で割ることにより、必要なワーカー数を直接算出します。同時実行数は MaxItemsPerInvocation が設定されている場合はその値、未設定の場合は既定値 100 が使用されます。算出される target worker count はパーティション数を上限とするため、パーティション数を超える追加インスタンスは処理効率向上に寄与しません。

よくお問い合わせいただく動作

弊サポートにてよくお問い合わせいただく事例について紹介します。下記に記載しますログ出力例は、Function Host のランタイム バージョン が v4.1047.100.26071 時点の例となります。バージョンが異なることにより出力内容が異なる可能性がありますことをご留意ください。なお、ログは Application Insights で利用するクエリ にて記載したクエリ、及び、以下のエラー詳細を確認するクエリを実行した結果より確認しています。

1
2
3
4
exceptions
| where timestamp > datetime("yyyy-mm-dd hh:mi")
| where cloud_RoleName =~ "<関数アプリ名>"
| project timestamp, outerMessage, details

デプロイ後に Cosmos DB トリガーが実行されない

Azure 上に展開した後に動作しない場合の代表的な原因のひとつに、Cosmos DB の接続情報が正しく設定されていないことがあります。下記のようなログが記録されている場合は設定を見直していただくことで、事象が解消する可能性があります。

監視対象コンテナーまたはリース コンテナーが存在しない(404 NotFound)

変更フィード プロセッサの起動時に CosmosExceptionNotFound (404) がエラーメッセージとして出力されます。
下記のログからリソースが見つからない(404)ことに起因して、リスナー起動に失敗していることを確認できます。

exceptions ログ:

image.png

対処方法:

  • 監視対象コンテナーとリース コンテナーが存在することを確認してください
  • 接続文字列認証をご利用の場合、リース コンテナーを自動作成するには CreateLeaseContainerIfNotExiststrue に設定してください。なお、マネージド ID (Entra ID) 認証をご利用の場合はこの設定は使用できないため、リース コンテナーを事前に作成してください
  • データベース名、コンテナー名が正しいことを確認してください

Cosmos DB の認証情報が正しくない

Azure Functions にて設定している接続文字列やマネージド ID が不正である場合に、認証エラーが発生します。
以下のログはアクセス許可のないマネージド ID 使用した場合に、 401 エラーが記録されたログとなります。

exceptions ログ:

image.png

対処方法:

  • アプリケーション設定にて接続文字列が正しく設定されているか確認してください
  • マネージド ID 認証を利用する場合は、Connection で指定した接頭辞に __accountEndpoint を付与したアプリケーション設定が正しいか確認してください

Cosmos DB 側のネットワーク制限による接続エラー

Cosmos DB のネットワーク設定(ファイアウォール、VNet サービス エンドポイント、プライベート エンドポイント)により Azure Functions からの接続がブロックされている場合があります。
その際には下記のログのように、403 エラーによりアクセスできなかったことが記録されます。

exceptions ログ:

image.png

対処方法:

  • Cosmos DB アカウントの [ネットワーク] 設定にて、Azure Functions からのアクセスが許可されていることを確認してください
  • Azure Functions にて VNet 統合を使用している場合は、NSG の Outbound 通信で Cosmos DB への接続(ポート 443)が許可されているか確認してください
  • connectionModeDirect の場合は TCP やポート範囲 10000-20000 への通信も必要となるため、接続モードのドキュメントを参照してください

Cosmos DB トリガーが二重実行される

変更フィード プロセッサの仕組みとして、少なくとも 1 回 (at-least-once) 処理されますが、以下のシナリオでは同じドキュメントが再度処理される場合があります。

  • 関数実行中にアプリケーション コードで例外が発生した場合(チェックポイントが更新されない)
  • インスタンスのスケーリングやリスタートによりリースが再分散された場合
  • 変更フィード プロセッサが停止される際にチェックポイントの更新前であった場合

対処方法:

  • アプリケーション コードを冪等(べきとう)に設計してください。同じ変更イベントが再度処理されても副作用が発生しないよう、出力先での重複許容や条件付き書き込み(ETag やバージョン管理の活用)を検討してください

StartFromBeginning を変更してもコンテナーの先頭から処理されない

StartFromBeginning および StartFromTime は、リース コンテナーにチェックポイント情報が存在しない初回起動時のみ有効です。

既にリース状態がある場合にコンテナーの先頭から処理し直したい場合は、以下の対応を検討してください。

  1. LeaseContainerPrefix を新しい値に変更する(推奨): 既存のリース コンテナーを維持したまま、新しいプレフィックスで別のリース状態を作成します。他のトリガー関数に影響を与えずに再処理を開始できます
  2. リース コンテナーを削除して再作成する: 同じリース コンテナーを利用する全てのトリガー関数に影響があるため、本番環境での実施は慎重に検討してください。削除前に、対象リース コンテナーを参照する関数が他にないか確認が必要です

注意: いずれの方法でも、コンテナーの先頭から全ての変更が再処理されることになります。再処理範囲が広い場合はアプリケーションの負荷や処理時間に影響する可能性があるため、計画的に実施してください。

まとめ

本ブログでは Cosmos DB トリガー関数の動作及び作成方法について整理しました。Cosmos DB トリガーのトラブルシューティングの参考になれば幸いです。

参考ドキュメント

Azure Functions(関数アプリ)の内部アーキテクチャ概要や関連する用語について

Azure Functions の Azure Cosmos DB トリガー

Azure Cosmos DB の変更フィード

Azure Cosmos DB の変更フィード プロセッサ

Azure Functions の Azure Cosmos DB トリガーでのターゲットベースのスケーリング






2026 年 4 月 16 日時点の内容となります。

本記事の内容は予告なく変更される場合がございますので予めご了承ください。



※本情報の内容(添付文書、リンク先などを含む)は、作成日時点でのものであり、予告なく変更される場合があります。