Azure Document Intelligenceの高遅延・処理停止(West Europe/Prebuilt Invoice)の原因と対策|プレビューAPIと本番運用ガイド

West EuropeのAzure Document Intelligence(旧Form Recognizer)で、Prebuilt Invoiceなどの推論が長時間Runningのまま完了しない――2024年9月から断続的に報告され、2025年9月時点でも再発が示唆されています。本記事はその症状・背景・再発防止の設計指針・運用チェックリストを体系化し、すぐに現場で役立つワークアラウンドと本番運用のベストプラクティスを提供します。

目次

Azure Document Intelligence 高遅延・処理停止問題の全体像

対象は West Europe リージョンの Azure Document Intelligence。Python SDK(azure‑ai‑documentintelligence 1.0.0‑b2/b4)や REST API(api‑version=2024‑07‑31 / 2024‑02‑29)を用いた呼び出しで、1ページのPDFのような軽量入力でも 15分以上かかる、あるいは完了しない事象が観測されています。特に Prebuilt Invoice などの事前学習済みモデルで顕在化しやすいという報告が複数あります。

観測された症状

項目内容
発生リージョンWest Europe(westeurope)。他リージョンでは影響が軽微または非再現のケースあり。
対象モデルPrebuilt Invoice を中心に一部のプリビルト・レイアウト分析でも遅延。
API/SDKREST(2024‑07‑31 / 2024‑02‑29)および Python SDK(1.0.0‑b2 / b4)双方で再現。
ステータス推論ジョブの状態が running から遷移しない、または非常に遅い。
入力サイズ1ページPDF・小さな画像でも 15分超や未完了に至る場合がある。
再発状況2024年9月以降に複数回。2025年9月時点でも「依然として遅い」との追加報告。

時系列(公式コメント・ユーザー報告の整理)

時点コメント状況
2024‑09‑17Microsoft モデレーターが「高遅延は既知の障害。プロダクトチーム調査中」と表明。既知障害としてエスカレーション。
2024‑09‑18一時復旧の兆候があるも、その後再発。安定性に課題。
2024‑09‑23支払サポート窓口より「プレビューAPIはSLA対象外」との説明。インシデントクローズだが根治せず。
2025‑09‑18別ユーザーから「依然として遅い」との追補報告。恒久対策は未判明と推測。

なぜ「Running」のまま止まるのか:技術的背景

Azure Document Intelligence は非同期の LRO(Long‑Running Operation)を採用し、202 Accepted と同時に Operation-Location(操作ID)を返します。裏側では以下の要因が遅延を増幅させます。

  • リージョン内のスループット逼迫・キュー滞留:同時実行増大や特定モデルの負荷集中により、推論ワーカーへの割当て待ちが延びる。
  • コールドスタート・モデル切替:コンテナ起動やモデルの新バージョン適用時に一時的な初期化コストが増大。
  • 入力特性の影響:高解像度画像、重いフォント埋め込みPDF、ページ数の多い帳票は前処理やOCR過程で遅延。
  • プレビュー版の安定性:2024‑07‑31 などの Public Preview はSLA対象外で、バースト負荷時の挙動が安定しにくい。

再現条件と影響範囲を見極める

以下の条件が揃うと遅延・未完了の確率が上がります。

  • West Europeでピーク時間帯に多数の LRO を同時投入している。
  • 入力PDFが「300dpi超・スキャン系・大量の埋め込みフォント・多ページ」。
  • クライアント側が短間隔で過剰ポーリングを行い、リソース側でスロットリングが発生。
  • SDK/クライアントのタイムアウトが短すぎ、内部リトライと干渉している。

最小再現と検証:RESTでの確実な切り分け

SDK由来の要因とサービス側の要因を切り分けるため、REST APIでの最小再現を用意します。

1) 解析リクエスト(Prebuilt Invoice)

POST https://<your-resource-name>.cognitiveservices.azure.com/
documentintelligence/documentModels/prebuilt-invoice:analyze?api-version=2024-07-31
Content-Type: application/pdf
Ocp-Apim-Subscription-Key: <key>

<< PDF バイナリ >>

202 Accepted が返り、レスポンスヘッダ Operation-Location にジョブURL(操作ID)が入ります。

2) ポーリング(状態確認)

GET {Operation-Location}
Ocp-Apim-Subscription-Key: <key>

通常は notStarted → running → succeeded|failed と遷移します。遅延時は running のまま長時間継続します。

cURLの例

# 解析リクエスト
curl -i -X POST \
  "https://<name>.cognitiveservices.azure.com/documentintelligence/documentModels/prebuilt-invoice:analyze?api-version=2024-07-31" \
  -H "Ocp-Apim-Subscription-Key: <key>" \
  -H "Content-Type: application/pdf" \
  --data-binary "@sample.pdf"

# Operation-Location を控える。続けてポーリング

curl -i -X GET "" 
-H "Ocp-Apim-Subscription-Key: "

運用メトリクスとログの取り方

調査・サポート連携を加速するため、以下を必ず取得します。

  • 操作ID:Operation-Location のURL全体。
  • クライアントID:x-ms-client-request-id(クライアントで設定推奨)。
  • サーバID:x-ms-request-id、x-ms-error-code が返る場合は併記。
  • 時刻:Accepted を受けた時刻、running へ遷移した時刻、タイムアウト・キャンセル時刻。
  • 入力要約:ページ数、dpi、ファイルサイズ、圧縮率、スキャン/ネイティブPDF別。

すぐに効くワークアラウンド(再現条件がある場合)

  • リージョン変更:West Europe以外(例:North Europe、East US)に新規リソースを立て、同一データで比較。多くの現場で遅延が有意に減るケースがあります。
  • 入力の簡素化:解像度を 200–300dpiへ、モノクロ化、不要画像削除、フォント埋め込みの最適化、ページ分割(多ページは1〜5ページ単位にシャーディング)。
  • ポーリング間隔の調整:2–10秒間隔に抑制し、指数バックオフを必ず適用。リクエストの無駄打ちが減り成功率が上がります。
  • キャンセル→再送:running が10分以上続いたら一度クライアント側でタイムアウトし、同じ入力で再送。成功することがあるため、再送回数(例:最大2回)を設ける。
  • リソーススケールの見直し:S0→S1(該当SKUが提供されている場合)やスケールユニット追加を検討。並列度上限もアプリ側で制御。
  • SDK更新:azure‑ai‑documentintelligence の最新版へ更新し、既知のバグ修正・最適化を取り込む。

本番運用のための設計ガイド(再発を前提に強くする)

アーキテクチャの基本方針

  1. 多リージョン冗長化:West Europe ↔ North Europe のペアや、East US などの離隔リージョンを用意。
  2. キュー駆動・非同期:入力をメッセージキューに積み、ワーカーでLROを起動。結果はストレージに集約。
  3. フォールバック:一定時間(例:600秒)でrunningが続いたら、別リージョンに自動フェイルオーバー。
  4. アイドempotency:同一ドキュメントの重複処理を避けるため、コンテンツハッシュ(SHA‑256)をキーに結果をキャッシュ。
  5. サーキットブレーカー:連続エラーや極端な遅延を検知したら自動的にリージョンやモデルを切り替える。

推奨するエラー処理・バックオフ

状況対処上限・目安
429/503(スロットリング/一時不調)指数バックオフ(2,4,8,16…秒)+ジッタ。並列度を即時半減。最大再試行5回、全体TTL 15分以内。
runningが継続10分でタイムアウト→キャンセル→別リージョン再送。再送は最大2回まで。
入力不備(415/400/422)前処理(MIME/拡張子/ページ数)を修正し再送。恒久修正必須。

参考実装(Python・RESTポーリング)

import os, time, hashlib, json, requests
from urllib.parse import urlparse

ENDPOINT = os.environ["AZURE_DI_ENDPOINT"]  # https://<name>.cognitiveservices.azure.com
KEY = os.environ["AZURE_DI_KEY"]
API_VERSION = "2024-07-31"
MODEL = "prebuilt-invoice"

def sha256_of(path):
h = hashlib.sha256()
with open(path, "rb") as f:
for chunk in iter(lambda: f.read(8192), b""):
h.update(chunk)
return h.hexdigest()

def analyze_invoice(pdf_path, timeout_sec=600, region_fallback_endpoint=None):
with open(pdf_path, "rb") as f:
url = f"{ENDPOINT}/documentintelligence/documentModels/{MODEL}:analyze?api-version={API_VERSION}"
headers = {"Ocp-Apim-Subscription-Key": KEY, "Content-Type": "application/pdf"}
r = requests.post(url, headers=headers, data=f)
r.raise_for_status()
op = r.headers["Operation-Location"]

```
start = time.time()
interval = 2.0
while True:
    h = {"Ocp-Apim-Subscription-Key": KEY}
    s = requests.get(op, headers=h)
    s.raise_for_status()
    body = s.json()
    sta = body.get("status", "").lower()
    if sta in ("succeeded", "failed", "canceled"):
        return body
    if time.time() - start &gt; timeout_sec:
        break
    time.sleep(interval)
    interval = min(interval * 1.5, 10.0)

# fallback
if region_fallback_endpoint:
    alt = ENDPOINT
    try:
        globals()["ENDPOINT"] = region_fallback_endpoint
        return analyze_invoice(pdf_path, timeout_sec=timeout_sec, region_fallback_endpoint=None)
    finally:
        globals()["ENDPOINT"] = alt
raise TimeoutError("runningが長時間継続しました。")
```

入力前処理の実践ガイド(速度と精度のトレードオフ)

施策ポイント期待効果
解像度最適化200–300dpiを目安。超高解像はダウンサンプリング。前処理・OCRレイテンシ低減。
モノクロ化カラー情報が不要な場合はグレースケール化。転送量・解析コスト減。
ページ分割多ページPDFは1〜5ページ単位に分割し並列処理。大きな1ジョブ滞留の回避。
フォント最適化不要な埋め込みフォント/画像を削減。レイアウト分析の安定化。
セキュリティ解除パスワード付PDFは解除してから送信。422/400の解消。

プレビューAPIとSLAの理解

  • Public Previewの前提:2024‑07‑31 などのプレビューAPIはSLA対象外。安定運用が必須の本番には不向きです。
  • 本番要件:SLAが必要な場合は GA(一般提供)版APIを優先。プレビュー機能を使う場合はフォールバック設計が不可欠。

スロットリング回避と並列度管理

過剰ポーリングや無制限の並行処理は、スロットリング(429)を招き、かえって全体の遅延を悪化させます。次の制御を推奨します。

  • クライアント側の同時実行数を「リージョン×リソース能力」に応じて上限化(例:1ワーカーあたり最大同時ジョブ数=2〜5)。
  • ポーリング間隔は初回2秒→最大10秒へ指数バックオフ。Retry-After ヘッダがあれば尊重。
  • ジョブTTL(例:15分)超過で強制終了し、別リージョンにフェイルオーバー。

サポートチケットの切り方(テンプレート付き)

有償サポート契約がある場合は、以下の情報を添えてチケット発行することで調査が加速します。

  • 影響リージョン・リソース名・サブスクリプションID(伏せ字可)。
  • 発生時刻(UTC/JST明記)と頻度、ピーク時間帯の傾向。
  • Operation-Location、x-ms-request-id、x-ms-client-request-id。
  • 入力の要約(ページ数・dpi・サイズ)。
  • 再現手順(RESTのcURLコマンド)と実行ログ。
  • リージョン切替や再送の結果(成功/失敗・時間)。

監視KPIとアラート設計

KPI定義しきい値例アラート内容
TTS(Time to Succeeded)Accepted→succeededまでの所要時間P95> 180秒(平常) / > 600秒(異常)600秒超で「遅延インシデント」
running継続率10分超runningのジョブ割合> 2%サーキット開放・リージョン切替
429/503比率全リクエストに占める割合> 1%並列度半減・バックオフ強化
再送成功率再送後に成功した割合< 80%根本対策の要検討

実運用で役立つチェックリスト

  • プレビューAPIの使用有無と本番SLA要件の整合を取ったか。
  • 多リージョン構成(少なくとも2リージョン)を持っているか。
  • キュー・非同期・フォールバック・サーキットブレーカーを実装したか。
  • 入力前処理(解像度・ページ分割・フォント最適化)を自動化したか。
  • メトリクス(TTS、running継続率、429/503率)をダッシュボード化したか。
  • 10分超running時の「キャンセル→再送」ルールを共有しているか。
  • サポート提出に必要なログ(Operation-Location等)を収集しているか。
  • SDK・依存コンポーネントを最新に保守しているか。

FAQ(よくある質問)

Q. West Europe以外なら完全に安全ですか?
いいえ。相対的に改善する事例が多いだけで、ワークロードや時間帯で状況は変わります。複数リージョンを用いたフォールバック設計を推奨します。

Q. どのくらいのポーリング間隔が適切?
初回2秒、以降は指数バックオフで最大10秒を目安に。Retry-After が返る場合はそれを優先してください。

Q. どの時点で「キャンセル→再送」すべき?
running が10分以上続く、またはTTSのP95が600秒を超えるとき。

Q. プレビューAPIを本番で使う場合の注意点は?
SLA非適用を前提に、フェイルオーバー・フォールバック・リトライ上限・結果キャッシュなど「壊れても止まらない」設計を入れてください。

まとめ

本件は、リージョン負荷・プレビュー版の安定性・入力特性など複数の要因が重なり、LROの running が長時間継続することで顕在化します。根本的な解決はサービス側の恒久対処に依存しますが、システム側でできることは多くあります。すなわち、多リージョン冗長化・キュー駆動の非同期化・適切なバックオフと並列度制御・前処理の自動化・「キャンセル→再送」の運用ルール化です。これらを組み合わせることで、West Europe再発時でもビジネス影響を最小化し、安定稼働に近づけられます。

付録:設計スニペット(擬似アーキ図)

Client
  └─&gt; Queue (ingress)
        └─&gt; Worker-A (WEU) --&gt; DI Analyze (WEU) --&gt; Result Store
        └─&gt; Worker-B (NEU) --&gt; DI Analyze (NEU) --&gt; Result Store
  └─&gt; API Gateway(サーキットブレーカー)
  └─&gt; Dashboard(TTS/429/503/Running率)
Result Store(hashキーで重複回避・キャッシュ)

付録:入力品質バリデーション例(擬似コード)

# 送信前にチェック:失敗や遅延の温床を排除
def validate(doc):
    assert doc.mime in ("application/pdf","image/png","image/jpeg")
    assert 1 &lt;= doc.pages &lt;= 5 or doc.use_sharding
    assert 150 &lt;= doc.dpi &lt;= 400
    # ファイルサイズは 20MB 目安(運用ポリシーで調整)
    assert doc.size_mb &lt;= 20
    return True

付録:運用ポリシー(サンプル)

  • ドキュメント1件あたりのSLO:TTS P95 ≤ 180秒、P99 ≤ 480秒。
  • 10分超runningのジョブは強制タイムアウト。フェイルオーバーを1回まで。
  • 429/503の移動平均が1%超で並列度を50%に自動減衰。
  • 結果は24時間キャッシュ。ハッシュ一致は再送しない。
  • リリース時は2リージョンのカナリア運用を経て全面展開。

この記事を書いた人

実務の現場で詰まりがちなポイントを地図にするITブログ「IT trip」を運営。Windows/Office(Teams・Excel)からSQL、サーバ運用、ガジェットまで、再現性のある手順と“なぜそうなるか”を丁寧に解説します。読んだらすぐ試せること、そして迷った人の次の一歩が見えることを大切にしています。

コメント

コメントする

目次