Azure Logic Apps で調整の問題 (429 - "要求が多すぎます" エラー) を処理する

適用対象: Azure Logic Apps (従量課金プラン + Standard)

ロジック アプリのワークフローで調整が発生すると、"HTTP 429 要求が多すぎます" エラーが返されます。これは、一定時間にわたって要求数が送信先の処理速度を超えた場合に発生します。 調整により、データ処理の遅延、パフォーマンス速度の低下、指定した再試行ポリシーの超過などのエラーといった問題が発生する可能性があります。

たとえば、従量課金ワークフローの次の SQL Server アクションは、調整の問題を報告する 429 エラーを示しています。

429 エラーが発生した SQL Server アクションを含む従量課金ワークフローを示すスクリーンショット。

次のセクションでは、ワークフローで調整が発生する可能性がある一般的なレベルについて説明します。

ロジック アプリのリソースの調整

Azure Logic Apps には、独自のスループット制限があります。 ロジック アプリ リソースがこれらの制限を超えると、特定のワークフロー インスタンスや実行だけでなく、ロジック アプリのリソースが調整されます。

このレベルで調整イベントを見つけるには、次の手順に従います。

  1. Azure portal で、ロジック アプリ リソースを開きます。

  2. ロジック アプリ リソースのメニューで [監視] の下にある [メトリック] を選択します。

  3. [グラフ タイトル][メトリックの追加] を選択します。これにより、グラフに別のメトリック バーが追加されます。

  4. 最初のメトリック バーの [メトリック] リストから [アクションの調整イベント] を選択します。 [集計] リストから [カウント] を選択します。

  5. 2 つ目のメトリック バーで、[メトリック] リストから [トリガー調整イベント] を選択します。 [集計] リストから [カウント] を選択します。

グラフには、ロジック アプリ ワークフロー内のアクションとトリガーの両方の調整イベントが表示されるようになりました。 詳細については、「Azure Logic Apps でワークフローの正常性とパフォーマンスのメトリックを表示する」を参照してください。

このレベルで調整を処理するには、次の選択肢があります。

  • 同時に実行できるワークフロー インスタンスの数を制限します。

    既定では、ワークフローのトリガー条件が同時に複数回満たされた場合、そのトリガーの複数のインスタンスが同時に (つまり "並列して") 実行されます。 直前のワークフロー インスタンスが実行を終了する前に、各トリガー インスタンスが起動します。

    同時に実行できるトリガー インスタンスの既定数は無制限ですが、トリガーのコンカレンシー設定をオンにすることでこの数を制限できます。また、必要に応じて、既定値以外の制限を選択できます。

  • 高スループット モードを有効にします。

  • トリガーの配列のデバッチつまり "分割" 動作を無効にします。

    処理する残りのワークフロー アクションの配列がトリガーから返される場合、トリガーの [分割] 設定によって配列項目が分割され、各配列項目のワークフロー インスタンスが開始されます。 この動作により、[分割] 制限まで複数の同時実行が効果的にトリガーされます。

    調整を制御するには、トリガーの [分割] 動作をオフにし、呼び出しごとに 1 つの項目を処理するのではなく、ワークフローから 1 回の呼び出しで配列全体を処理するようにします。

  • アクションを複数の小さなワークフローにリファクタリングします。

    前述のように、従量課金ロジック アプリ ワークフローは 5 分間で実行できるアクションの既定数に制限されています。 高スループット モードを有効にするとこの制限を引き上げることができますが、各ワークフローで実行されるアクションの数が制限を超えないようにワークフローのアクションを小さなワークフローに分割するかどうかを検討することもできます。 このように、1 つのワークフローの負荷を軽減し、複数のワークフローに負荷を分散します。 このソリューションは、大規模なデータ セットを処理するアクションや、同時に実行されるアクション、ループ反復、または各ループ反復内のアクションがアクション実行の制限を超えるほど多くなるアクションに適しています。

    たとえば、次の従量課金ワークフローでは、SQL Server データベースからテーブルを取得するためのすべての作業を実行し、各テーブルから行を取得します。 For each ループは各テーブルで同時に反復されるため、Get rows アクションから各テーブルの行が返されます。 こうしたテーブルのデータ量によっては、これらのアクションがアクション実行の制限を超える可能性があります。

    リファクタリングの「前」の従量課金ワークフローを示すスクリーンショット。

    リファクタリング後、元のワークフローは親ワークフローと子ワークフローに分割されます。

    次の親ワークフローでは SQL Server からテーブルを取得し、各テーブルの子ワークフローを呼び出して行を取得します。

    SQL Server テーブルを取得し、子ワークフローを呼び出す従量課金親ワークフローを示すスクリーンショット。

    親ワークフローによって次の子ワークフローが呼び出され、各テーブルの行が取得されます。

    各テーブルの行を取得する従量課金子ワークフローを示すスクリーンショット。

コネクタの調整

各コネクタには、独自の調整制限があります。これについては、各コネクタのテクニカル リファレンス ページを参照してください。 たとえば、Azure Service Bus コネクタには、1 分あたり最大 6,000 回の呼び出しを許可する調整制限がありますが、SQL Server コネクタには、操作の種類に基づいて変化する調整制限があります。

HTTP などの一部のトリガーとアクションには、再試行ポリシーの制限に基づいてカスタマイズして例外処理を実装することができる "再試行ポリシー" があります。 このポリシーを使用すると、元の要求が失敗するかタイムアウトして 408、429、または 5xx 応答の結果になったときに、トリガーまたはアクションで要求を再試行するかどうかと、その頻度を指定できます。 そのため、調整が開始され、429 エラーが返された場合、Logic Apps は、サポートされていれば再試行ポリシーに従います。

トリガーまたはアクションで再試行ポリシーがサポートされているかどうかを調べるには、トリガーまたはアクションの設定を確認します。 トリガーまたはアクションの再試行回数を確認するには、ロジック アプリの実行履歴にアクセスして、確認する実行を選択し、そのトリガーまたはアクションを展開して、入力、出力、および再試行の詳細を表示します。

次の従量課金ワークフローの例は、HTTP アクションでこの情報を見つけることができる場所を示しています。

HTTP アクションの実行履歴、再試行、入力、出力を含む従量課金ワークフローを示すスクリーンショット。

再試行履歴にはエラー情報が含まれていますが、コネクタの調整と接続先の調整を区別できないことがあります。 このような場合は、必要に応じて応答の詳細を確認するか、いくつかの調整間隔の計算を実行してソースを特定します。

マルチテナント Azure Logic Apps の従量課金ロジック アプリ ワークフローの場合、"接続" レベルで調整が行われます。

このレベルで調整を処理するには、次の選択肢があります。

  • 処理のためにワークフローでデータをパーティションできるように 1 つのアクションに対して複数の接続を設定します。

    同じ資格情報を使用して、同じ接続先への複数の接続にアクションの要求を分割することにより、ワークロードを分散できるかどうかを検討します。

    たとえば、ワークフローで SQL Server データベースからテーブルを取得し、各テーブルから行を取得するとします。 処理する必要がある行数に基づいて、複数の接続と複数の For each ループを使用して、処理のために行の総数を少数のセットに分割できます。 このシナリオでは、2 つの For each ループを使用して、行の総数を半分に分割します。 最初の For each ループでは、前半を取得する式を使用します。 もう 1 つの For each ループでは、後半を取得する別の式を使用します。次に例を示します。

    • 式 1:take() 関数を使用してコレクションの前部を取得します。 詳細については、take() 関数に関するページを参照してください。

      @take(collection-or-array-name, div(length(collection-or-array-name), 2))

    • 式 2:skip() 関数を使用してコレクションの前部を削除し、他のすべてのアイテムを返します。 詳細については、skip() 関数に関するページを参照してください。

      @skip(collection-or-array-name, div(length(collection-or-array-name), 2))

      次の従量課金ワークフローの例は、これらの式を使用する方法を示しています。

      1 つのアクションに対して複数の接続を使用する従量課金ワークフローを示すスクリーンショット。

  • アクションごとに異なる接続を設定します。

    アクションが同じサービスまたはシステムに接続して同じ資格情報を使用する場合でも、各アクションの要求を独自の接続に分散することでワークロードを分散できるかどうかを検討します。

    たとえば、ワークフローで SQL Server データベースからテーブルを取得し、各テーブルの各行を取得するとします。 テーブルの取得に 1 つの接続を使用し、各行の取得に別の接続を使用するように、個別の接続を使用することができます。

    次の例は、アクションごとに異なる接続を作成して使用する従量課金ワークフローを示しています。

    アクションごとに異なる接続を作成して使用する従量課金ワークフローを示すスクリーンショット。

  • "For each" ループのコンカレンシーまたは並列処理を変更します。

    既定では、"For each" ループの反復は、コンカレンシーの制限を上限として同時に実行されます。 "For each" ループ内に調整されている接続がある場合は、並列で実行されるループの反復回数を減らすことができます。 詳しくは、次のドキュメントをご覧ください。

接続先のサービスまたはシステムの調整

コネクタには独自の調整制限がありますが、コネクタから呼び出される接続先のサービスまたはシステムにも調整制限が存在する場合があります。 たとえば、Microsoft Exchange Server の一部の API には、Office 365 Outlook コネクタよりも厳しい制限があります。

既定では、ロジック アプリのワークフロー インスタンスと、それらのインスタンス内のすべてのループまたは分岐は並列して実行されます。 この動作は、複数のインスタンスから同時に同じエンドポイントを呼び出すことができることを意味します。 各インスタンスは、他のインスタンスの存在を認識していません。そのため、失敗したアクションを再試行しようとすると、競合状態が発生する可能性があります。この場合、複数の呼び出しの実行が同時に試行されますが、成功するには、調整が開始される前に、これらの呼び出しが接続先のサービスまたはシステムに到達している必要があります。

たとえば、100 個の項目を持つ配列があるとします。 "For each" ループを使用して配列を反復処理し、ループのコンカレンシー制御をオンにして、並列反復の数を 20 個または現在の既定の制限に制限できます。 このループ内では、アクションによって配列の項目が SQL Server データベースに挿入されます。これにより、1 秒あたり 15 回の呼び出しのみが許可されます。 このシナリオでは、再試行のバックログが蓄積されて実行されないため、調整の問題が発生します。

次の表は、アクションの再試行間隔が 1 秒の場合にループで何が行われるかについてのタイムラインを示しています。

[特定の時点] 実行するアクションの数 失敗したアクションの数 待機の再試行回数
T + 0 秒 20 回の挿入 5 回の失敗 (SQL の制限のため) 5 回の再試行
T + 0.5 秒 以前の 5 回の再試行が待機しているため、15 回の挿入 以前の SQL の制限がさらに 0.5 秒間有効であるため、15 個すべてが失敗します。 20 回の再試行
(以前の 5 回 + 15 回の新規)
T + 1 秒 20 回の挿入 5 回の失敗と以前の 20 回の再試行 (SQL の制限のため) 25 回の再試行 (以前の 20 回 + 5 回の新規)

このレベルで調整を処理するには、次の選択肢があります。

  • 個々に 1 つの操作を処理するように個々のワークフローを作成します。

    • このセクションの SQL Server シナリオの例を続けて、配列項目を Azure Service Bus キューなどのキューに格納するワークフローを作成できます。 次に、そのキュー内の各項目に対して挿入操作のみを実行する別のワークフローを作成します。 このようにすると、特定の時点で実行されるワークフロー インスタンスは 1 つのみになります。これにより、挿入操作が完了してキュー内の次の項目に移動するか、インスタンスで 429 エラーを受け取っても無意味な再試行が行われなくなります。

    • 各アクションの子または入れ子になったワークフローを呼び出す親ワークフローを作成します。 親の結果に基づいて、親から異なる子ワークフローを呼び出す必要がある場合は、呼び出す子ワークフローを決定する条件アクションまたは切り替えアクションを使用できます。 このパターンを使うと、呼び出しまたは操作の数を減らすために役立ちます。

      たとえば、2 つのワークフローがあり、それぞれに "成功" や "失敗" などの特定の件名についてメール アカウントを毎分確認するポーリング トリガーがあるとします。 この設定の結果、1 時間あたり 120 回の呼び出しが発生します。 代わりに、毎分ポーリングし、件名が "成功" か "失敗" かに基づいて実行される子ワークフローを呼び出す 1 つの親ワークフローを作成すると、ポーリング確認の数が半分 (この場合は 60) に減ります。

  • バッチ処理を設定します。 (従量課金ワークフローのみ)

    接続先サービスがバッチ操作をサポートしている場合は、項目を個別にではなく、グループまたはバッチで処理することで、調整に対処できます。 バッチ処理ソリューションを実装するには、"バッチ レシーバー" ロジック アプリ ワークフローと "バッチ センダー" ロジック アプリ ワークフローを作成します。 バッチ センダーでは、指定された条件が満たされるまでメッセージまたは項目を収集し、それらのメッセージまたは項目を 1 つのグループにまとめて送信します。 バッチ レシーバーでは、そのグループを受け入れ、それらのメッセージや項目を処理します。 詳細については、メッセージをグループにまとめてバッチ処理する方法に関するページを参照してください。

  • トリガーとアクションには、ポーリング バージョンではなく、Webhook バージョンを使用します。

    なぜですか? ポーリング トリガーでは、特定の間隔で接続先サービスまたはシステムが引き続き確認されます。 間隔が非常に頻繁な場合は (毎秒など)、調整の問題が生じる可能性があります。 ただし、HTTP Webhook などの Webhook トリガーまたはアクションでは、接続先サービスまたはシステムに対する 1 回の呼び出しのみを作成します。これはサブスクリプション時に行われ、イベントが発生したときにのみ接続先からトリガーまたはアクションに通知するように要求されます。 このようにすると、トリガーまたはアクションで接続先を継続的に確認する必要がなくなります。

    そのため、接続先サービスまたはシステムが Webhook をサポートしている場合、または Webhook バージョンを持つコネクタを用意している場合、この方法はポーリング バージョンを使用するよりも優れています。 Webhook トリガーとアクションを識別するには、その種類が ApiConnectionWebhook であること、または繰り返しを指定する必要がないことを確認します。 詳細については、「APIConnectionWebhook トリガー」と「APIConnectionWebhook アクション」を参照してください。

次のステップ