次の方法で共有


NoSQL の Azure Cosmos DB 用 Azure 関数トリガーを使用するときの問題の診断とトラブルシューティングを行う

適用対象: NoSQL

この記事では、NoSQL の Azure Cosmos DB 用 Azure 関数トリガーを使用するときの一般的な問題、回避策、診断手順について説明します。

依存関係

NoSQL の Azure Cosmos DB 用 Azure 関数トリガーとバインドは、基になる Azure 関数Runtime に対する拡張機能パッケージ Microsoft.Azure.WebJobs.Extensions.CosmosDB に依存します。 これらのパッケージには、発生する可能性のある問題に対処する新機能や修正プログラムが含まれている場合があるため、常に最新の状態にしておいてください。

Azure Cosmos DB SDK を個別に使用する

拡張機能パッケージの重要な機能は、Azure Cosmos DB 用 Azure 関数のトリガーとバインドのサポートを提供することです。 また、パッケージには Azure Cosmos DB .NET SDK も含まれており、トリガーやバインドを使わずにプログラムで Azure Cosmos DB とやり取りする場合に便利です。

Azure Cosmos DB SDK を使う場合は、別の NuGet パッケージの参照をプロジェクトに追加しないでください。 代わりに、Azure 関数の拡張機能パッケージによって SDK の参照が解決されるようにします。 トリガーおよびバインドとは別に Azure Cosmos DB SDK を使用します。

さらに、Azure Cosmos DB SDK クライアントの独自のインスタンスを手動で作成する場合は、シングルトン パターン アプローチを使用して、クライアントのインスタンスを 1 つだけ使用するパターンに従う必要があります。 このプロセスにより、操作でのソケットの問題の可能性を回避できます。

一般的なシナリオと回避策

Azure 関数が失敗し、コレクション"doesn't exist"というエラー メッセージが表示される

Azure 関数は失敗し、次のエラー メッセージが表示されます: 「ソース コレクション collection-name (データベース内 database-name) またはリース コレクション collection2-name(データベース内database2-name) が存在しません。 Both collections must exist before the listener starts. リース コレクションを自動的に作成するには、 CreateLeaseCollectionIfNotExiststrue に設定します。

このエラーは、トリガーが動作するために必要な Azure Cosmos DB コンテナのどちらか、または両方が以下に該当することを意味します。

  • 存在しない
  • Azure 関数に到達できない

構成に基づいて、エラー テキスト自体にはトリガーが探している Azure Cosmos DB データベースとコンテナーが示されています。

この問題を解決するには、次の手順を実行します。

  1. Connection 属性を確認し、それが Azure 関数アプリ内に存在する設定を参照していることを確認します。

    • この属性の値は、接続文字列自体ではなく、構成設定の名前になっている必要があります。
  2. Azure Cosmos DB アカウントに databaseNamecontainerName の値が存在していることを確認します。

    • 値の自動置換を使用している場合は (%settingName% パターンを使用)、設定の名前が自分の Azure 関数アプリに存在することを確認します。
  3. LeaseContainerName/leaseContainerName の値を指定しない場合、既定値は leases になります。 そのようなコンテナーが存在することを確認します。

    • 必要に応じて、トリガーの CreateLeaseContainerIfNotExists 属性を true に設定し、自動的にそれを作成することができます。
  4. Azure Cosmos DB アカウントが Azure 関数をブロックしていないことを確認するには、Azure Cosmos DB アカウントのファイアウォール構成を確認します。

Azure 関数の起動に失敗し、"Shared throughput collection should have a partition key" というエラー メッセージが表示される

以前のバージョンの Azure Cosmos DB 拡張機能では、共有スループット データベース内で作成されたリース コンテナーの使用はサポートされていませんでした。

この問題を解決するには、次の手順を実行します。

Azure 関数の起動に失敗し、"PartitionKey must be supplied for this operation" というエラー メッセージが表示される

このエラーは、古い拡張機能の依存関係を持つ、パーティション分割されたリース コレクションが現在使用されていることを示しています。

この問題を解決するには、次の手順を実行します。

  • 利用可能な最新バージョンにアップグレードしてください

Azure 関数の起動に失敗し、"Forbidden (403); Substatus: 5300... The given request [POST ...] can't be authorized by Microsoft Entra token in data plane" というエラー メッセージが表示される

このエラーは、関数が Microsoft Entra ID を使用してデータ以外の操作を実行しようとしている場合を意味します。 Microsoft Entra ID を使用する場合は CreateLeaseContainerIfNotExists = true を使用できません。

Azure 関数の起動に失敗し、"The lease collection, if partitioned, must have partition key equal to id" というエラー メッセージが表示される

このエラーは、現在のリース コンテナーがパーティション分割されているのに、パーティション キーのパスが /id ではないことを意味します。

この問題を解決するには、次の手順を実行します。

  • パーティション キーとして /id を使用してリース コンテナーを再作成します

トリガーを実行しようとすると、"Value can't be null. Parameter name: o" in your Azure function logs"というエラー メッセージが表示されます。

この問題は、Azure portal を使用していて、そのトリガーを使用する Azure 関数を調べているときに画面の [実行] ボタンを選択しようとすると発生します。 トリガーを開始するために [実行] を選択する必要はありません。 関数をデプロイすると自動的に開始されます。

この問題を解決するには、次の手順を実行します。

  • Azure portal で関数のログ ストリームを確認したい場合は、監視対象のコンテナーに移動して新しい項目をいくつか挿入します。 トリガーが、自動的に実行されます。

変更の受信に時間がかかりすぎる

このシナリオには、複数の原因が考えられます。 次の解決策のいずれか、またはすべてを試してみることを検討してください。

  • Azure 関数と Azure Cosmos DB アカウントが、別のリージョンにデプロイされていませんか? ネットワーク待機時間を最適にするには、Azure 関数と Azure Cosmos DB アカウントが、同じ Azure リージョンに併置されている必要があります。

  • Azure Cosmos DB コンテナーで行われた変更は、継続的なものですか、それとも散発的なものですか?

    • 散発的である場合は、変更が格納されてから Azure 関数によって取得されるまでに、若干の遅延が生じる可能性があります。 この動作は、トリガーが内部で Azure Cosmos DB コンテナー内の変更を確認し、読み取りを待機している変更が見つからない場合に発生します。 トリガーは、新しい変更をチェックする前に、構成可能な時間 (デフォルトでは 5 秒) スリープ状態になります。 トリガーでは、この動作を利用して、要求ユニット (RU) の消費量が多くなるのを回避します。 このスリープ時間は、トリガーの構成にある FeedPollDelay/feedPollDelay の設定から構成できます。 この値はミリ秒単位で指定する必要があります。
  • お使いの Azure Cosmos DB コンテナーが、レート制限されている可能性があります。

  • トリガーの PreferredLocations 属性を使用して Azure リージョンのコンマ区切りリストを指定し、ユーザー設定の優先接続順序を定義することができます。

  • 新しい変更を処理する速度によって、トリガーがそれらの変更を受信する速度が決まります。 関数の実行時間 (期間) を確認します。 関数の速度が遅い場合は、トリガーが新しい変更を取得するのにかかる時間が長くなります。 実行時間が最近増加した場合は、最近コードに加えた変更が影響しているかもしれません。 Azure Cosmos DB コンテナーでの操作の受信速度がトリガーの速度よりも速い場合は、遅れが続くことになります。 関数のコードを調査して、最も時間のかかる操作、および最適化方法について調べることをお勧めします。

  • デバッグ ログを使用して診断をチェックし、ネットワーク遅延があるかどうかを確認できます。

一部の変更がトリガーで繰り返される

変更 の概念は、項目に対する 1 つの操作です。 同じ項目に対して複数のイベントが受信される最も一般的なシナリオは、次のとおりです:

  • 実行中に関数が失敗します。 関数に対して再試行ポリシーが有効になっている場合、または関数の実行が許可された実行時間を超えている場合は、同じ変更バッチが関数に再度配信される可能性があります。 この失敗は予期される動作であり、設計上、関数ログでエラーの兆候を確認し、トリガー ログを有効にして詳細を確認してください。

  • インスタンス間でリースの負荷分散が行われます。 インスタンスが増減すると、負荷分散 によって同じ変更のバッチが複数の関数インスタンスに配信される可能性があります。 こ負荷分散は設計上、予期される動作であり、一時的であるはずです。 トリガー ログには、インスタンスがリースを取得するときと解放するときのイベントが含まれます。

  • 項目が更新されています。 変更フィードには、同じ項目に対する複数の操作が含まれることがあります。 その項目が更新を受信している場合は、複数のイベント (更新ごとに 1 つ) を取得できます。 同じ項目に対する異なる操作を区別する簡単な方法の 1 つは、_lsn変更ごとのプロパティを追跡することです。 プロパティが一致しない場合、その変更は異なるものです。

  • id のみで項目を識別する場合、項目の一意の識別子は id とそのパーティション キーであることに注意してください。 (同じ id を持つものの、異なるパーティション キーを持つ 2 つの項目が存在する可能性があります。)

トリガーに一部の変更がありません

関数が、Azure Cosmos DB for NoSQL コンテナーで発生した変更の一部を取得していない可能性があります。 または、一部の変更のコピー中にコピー先で変更が失われることもあります。 その、このセクションにあるソリューションをお試しください。

  • ログが有効になっていることを確認します。 処理中にエラーが発生していないか検証します。

  • Azure 関数では、多くの場合、受け取った変更の処理が行われ、必要に応じて結果が別の宛先に送信されることがあります。 不足している変更を調査する場合は、取り込みポイントでどの変更が受信されているかを必ず測定してください。 宛先ではなく、Azure 関数がいつ開始するかを測定します。

  • 宛先でいくつかの変更が欠落している場合、変更を受け取った後の Azure 関数での実行の間に何らかのエラーが発生していることを示している可能性があります。

    • このシナリオでの最善の対応策は、try/catch ブロックをコードと、変更を処理している可能性があるループ内に追加することです。 これを追加することで、項目の特定のサブセットに対する障害を検出して、それらを適切に処理する (さらに分析するために別のストレージに送信するか、再試行する) ことができます。 または、Azure 関数の再試行ポリシーを構成することもできます。

      Note

      NoSQL の Azure Cosmos DB 用 Azure 関数トリガーでは、コードの実行中にハンドルされない例外が発生した場合、既定では変更のバッチの再試行は行われません。 つまり、宛先に変更が到達しなかった理由は、それらの処理に失敗したことである可能性があります。

  • コピー先が別の Azure Cosmos DB コンテナーであり、アイテムをコピーするためにアップサート操作を実行している場合は、両方のコンテナーのパーティション キー定義を確認します。 監視対象コンテナーとターゲット コンテナーのパーティション キーは同じである必要があります。 この構成の違いが原因で、複数のソース項目が、Upsert 操作によってコピー先で 1 つの項目として保存されている可能性があります。

  • トリガーにいくつかの変更が届いていない場合、考えられる最も一般的なシナリオは、別の Azure の関数が実行されていることです。 他の関数は、Azure にデプロイされている場合や、開発者のコンピューター上で全く同じ構成でローカルに実行されている場合があります。 その場合、この関数によって、Azure 関数で処理するはずの変更の一部が盗まれている可能性があります。

さらに、実行している Azure 関数アプリ インスタンスの数がわかっている場合は、そのシナリオを検証できます。 リース コンテナーを調べて、その中のリース項目の数を数えた場合、Owner プロパティの異なる値の数は、関数アプリのインスタンスの数と等しくなっている必要があります。 既知の Azure 関数アプリ インスタンスの数より所有者の数が多い場合、余分な所有者が変更を "盗んでいる" ことを意味します。

このような状況を回避する簡単な方法は、LeaseCollectionPrefix/leaseCollectionPrefix を新規または別の値で関数に適用するか、または新しいリース コンテナーでテストします。

再起動してコンテナーにあるすべての項目を最初から再処理する必要がある

コンテナーにあるすべての項目を最初から再処理するには、次の手順を実行します。

  1. 現在実行中の場合は、Azure 関数を停止します。

  2. リース コレクション内のドキュメントを削除します (または、空になるようにリース コレクションを削除して再作成します)。

  3. 関数内の StartFromBeginning CosmosDBTrigger 属性を true に設定します。

  4. Azure 関数を再起動します。 この関数は、最初からすべての変更を読み取って処理するようになりました。

StartFromBeginningtrue に設定すると、現在の時刻ではなく、コレクションの履歴の最初から変更の読み取りを開始するように、Azure 関数が指示されます。

このソリューションは、リースがまだ作成されていないとき (つまり、リース コレクションにドキュメントがあるとき) にのみ機能します。

既に作成されているリースがある場合は、このプロパティを true に設定しても影響はありません。 このシナリオでは、関数を停止して再起動すると、リース コレクションで定義されている最後のチェックポイントから読み取りが開始されます。

エラー: Binding can be done only with IReadOnlyList<Document> or JArray

このエラーは、Azure 関数プロジェクトに、バージョンの競合がある Azure Cosmos DB SDK への手動 NuGet パッケージ参照が含まれている場合に発生します。 このエラーは一般的に、パッケージに Azure 関数用の Azure Cosmos DB 拡張機能によって提供されるバージョンとは異なるバージョンがあるために発生します

この状況を回避するには、手動で追加された NuGet の参照を削除し、Azure Cosmos DB SDK の参照が Azure 関数の Azure Cosmos DB 拡張機能パッケージで解決されるようにします。

Azure 関数で変更を検出するポーリング間隔を変更する

前述の「変更の受信に時間がかかりすぎる」の説明にあるように、Azure 関数は、(高い RU 消費を避けるため) 新しい変更を確認する前に、構成可能な時間 (既定では 5 秒) だけスリープ状態になります。 このスリープ時間は、トリガーの構成FeedPollDelay/feedPollDelay の設定を使用して構成できます (値はミリ秒単位)。