pull サブスクリプションのトラブルシューティング

このドキュメントでは、Pub/Sub pull サブスクリプションに関する一般的なトラブルシューティングのヒントを示します。pull サブスクリプションの詳細については、pull サブスクライバー ガイドをご覧ください。

Pub/Sub サブスクリプションを効果的にモニタリングするには、まず配信レイテンシの健全性スコア(subscription/delivery_latency_health_score)を確認して、どの要因が予期しないレイテンシやレイテンシの増加に貢献しているかを確認することをおすすめします。

最も古い未確認メッセージの経過時間が増加し続ける

oldest_unacked_message_age は、Pub/Sub サブスクリプションの健全性をモニタリングするための重要な指標です。この指標は、サブスクリプションのバックログにある最も古いメッセージ(サブスクライバーによってまだ確認応答(ack)されていないメッセージ)の経過時間を秒単位で測定します。この指標は、処理の遅延やボトルネックの可能性に関する貴重な分析情報を提供します。

メッセージ バックログをモニタリングすることで、メッセージをタイムリーかつ効率的に処理できます。最も古い未確認メッセージの経過時間を追跡することで、コンシューマーが遅れている状況をプロアクティブに特定できます。この方法により、パフォーマンスの低下に関連する潜在的な問題に対処するための早期介入が可能になります。

調査できる一般的なバックログの問題には、次のようなものがあります。

クライアント構成に関する問題

oldest_unacked_message_age 指標と num_undelivered_messages 指標の両方が同時に増加している場合、サブスクライバーがメッセージ量に追いついていない可能性があります。この場合は、サブスクライバー コンポーネントに焦点を当てて調査します。

  • クライアントの健全性: サブスクライバー クライアントをホストするマシン上のリソース使用率(CPU、メモリ、ネットワーク帯域幅など)を分析します。処理効率を低下させる可能性のあるプレッシャー ポイントを探します。

  • クライアント コード: 最近のコード変更を確認し、エラーログを調べます。サブスクライバー コードのバグや非効率性は、メッセージ処理率に大きな影響を与える可能性があります。特定のメッセージに問題がある可能性があります。たとえば、複数のメッセージがデータベース内の同じ行に同時にアクセスする必要がある場合があります。この動作により、競合と高レイテンシが発生する可能性があります。

  • 割り当て制限: Pub/Sub の割り当てや、ホスティング サービスによって課せられた制限を超えていないことを確認します。サブスクライバーが Google Cloudでホストされている場合は、Compute Engine または GKE のリソース割り当てを確認して、ボトルネックが発生しないようにします。

サブスクライバーがメッセージを否定応答した

サブスクライバーがメッセージを否定応答(nack)すると、メッセージを正常に処理できなかったことが Pub/Sub に通知されます。Pub/Sub は同じメッセージの再配信を試みます。メッセージに対して nack が繰り返されると、重複が発生し、メッセージ配信が大幅に遅延する可能性があります。

メッセージを否定応答しても、次の pull で別のメッセージが取得されるとは限りません。Pub/Sub の再配信ポリシーでは、新しいメッセージの前に、否定応答されたメッセージの再配信が継続される場合があります。したがって、特定のメッセージをフィルタリングまたはスキップする方法として nack に依存しないでください。代わりに、再試行ポリシー(できれば指数バックオフ)を設定して、後で処理できる可能性はあるものの、再配信までに少し時間がかかる個々のメッセージをバックオフします。

特定のメッセージを意図的にスキップする必要がある場合は、処理しない場合でも、確認応答することをおすすめします。これにより、それらのアイテムはサブスクリプションから削除され、不要な再配信が回避され、リソースの消費が削減されます。意図的かどうかにかかわらず、メッセージを確認応答しないままにすると、バックログの問題や重複配信が発生します。

配信レイテンシが高い

Pub/Sub の配信レイテンシは、パブリッシャーからのメッセージがサブスクライバーに到達するまでにかかる時間です。配信レイテンシが高くなる原因として考えられるものを、次のセクションで説明します。

チャンネル登録者数が不足している

StreamingPull を使用するクライアントの場合、常に低レイテンシを実現するには、サブスクリプションに対する複数の StreamingPull 接続を維持します。アクティブなサブスクライバー接続がない場合、Pub/Sub はメッセージを迅速に配信できません。単一のストリームが単一障害点となり、遅延のリスクが高まる可能性があります。subscription/open_streaming_pulls 指標を使用すると、アクティブなストリーミング接続の数を把握できます。これを使用して、着信したメッセージを処理するのに十分なストリームが常に確保されていることを確認します。

単項 pull を使用するクライアントの場合、常に低レイテンシを実現するには、サブスクリプションに対する未処理の pull リクエストを複数保持します。リクエストの頻度が低いと、バックログにメッセージが蓄積され、レイテンシが増加する可能性があります。このアプローチにより、接続性のギャップを最小限に抑え、配信のレイテンシを改善できます。

高レベルのクライアント ライブラリは、最小限の運用オーバーヘッドと処理コストで高スループットと低レイテンシが必要な場合におすすめします。デフォルトでは、高レベル クライアント ライブラリは StreamingPull API を使用します。これは、レイテンシを最小限に抑えるためのより良い選択肢となる傾向があるためです。高レベル クライアント ライブラリには、認証、スループット、レイテンシの最適化、メッセージのフォーマットなどの機能のために基盤となる API 呼び出しを処理するビルド済み関数とクラスが含まれています。

クライアント構成に関する問題

クライアント構成の問題をご覧ください。

バックログが多い

Pub/Sub サブスクリプションの未確認応答メッセージのメッセージ バックログは、サブスクライバーによってメッセージがすぐに処理されないため、エンドツーエンドのレイテンシが本質的に増加します。

順序指定キーと 1 回限りの配信

順序キーと 1 回限りの配信は便利な機能ですが、Pub/Sub 内で追加の調整を行い、正しい配信を保証する必要があります。この調整により、可用性が低下し、レイテンシが増加する可能性があります。定常状態では差はごくわずかですが、必要な調整手順によってレイテンシが一時的に増加したり、エラー率が増加したりする可能性があります。順序指定が有効になっている場合、順序指定キーを持つメッセージは、同じ順序指定キーを持つ以前のメッセージが ACK されるまで配信できません。

メッセージの順序付けや 1 回限りの配信がアプリケーションに不可欠かどうかを検討してください。低レイテンシが最優先事項である場合は、これらの機能の使用を最小限に抑えることで、メッセージ処理の遅延を軽減できます。

メッセージ サイズの増加

メッセージ サイズが急増すると、Pub/Sub とクライアントとの間の転送時間が長くなり、クライアント側でのメッセージの処理時間が長くなる可能性があります。

配信レイテンシの増加が見られる場合は、topic/message_sizes 指標を使用してメッセージ サイズを確認し、topic_id でグループ化できます。メッセージ サイズの急増と、観察されたパフォーマンスの問題を関連付けます。

メッセージが見つからない

メッセージがサブスクライバーに正常に配信されていないと思われる場合は、次のいずれかの理由が考えられます。

複数のコンシューマを使用する Pub/Sub サブスクリプションでのメッセージ配信

Pub/Sub では、同じサブスクリプションのコンシューマー間でメッセージが不均等に分散されることがあります。Pub/Sub は、すべてのアクティブなクライアント間でメッセージのロード バランシングを行いますが、主な目的は、完全に均等な分散を保証することではなく、メッセージ処理の全体的なスループットを最大化し、バックログを最小限に抑えることです。システムは、より高い処理能力を示すコンシューマー(メッセージを迅速に確認し、フロー制御設定による制約を受けないコンシューマー)に、より多くのメッセージを動的に転送します。メッセージを処理する速度が異なるコンシューマや、異なる条件(リソースの可用性、ネットワーク レイテンシなど)で動作するコンシューマは、処理するメッセージの量が異なる可能性があります。通常、高速で応答性の高いコンシューマは、メッセージ負荷のより大きな部分を受信して処理します。

複数のコンシューマーに分散されるこの方法では、メッセージの受信と処理の順序が異なる場合があります。そのため、サブスクリプションでメッセージの順序付けが有効になっていて、パブリッシャーに順序指定キーが含まれていない限り、メッセージがパブリッシュされた順序でコンシューマーによって処理されるとは限りません。

メッセージはすでにクライアントに届いている可能性があり、未確認のメッセージのバックログがあるからといって、必ずしも次の pull リクエストでそれらのメッセージを受け取れるとは限らないことに注意してください。コンシューマは、 Google Cloud コンソールまたは Google Cloud CLI で pull を使用しているか、カスタム サブスクライバーをローカルで実行してメッセージを確認している場合があります。

単項 Pull クライアントの場合、一部の pull リクエストでメッセージが返されないことがあります。サブスクライバーが足りないセクションで説明したように、バックログが存在する場合でも、一部のリクエストでは、構成された最大メッセージ数より少ないメッセージが返される場合や、メッセージが返されない場合があるため、未処理の pull リクエストを複数保持することをおすすめします。これは、他のコンシューマが利用可能なメッセージのリースを保持している可能性があるためです。

コンシューマーが確認応答期限内にメッセージを確認応答できなかった場合、またはメッセージを否定応答(NACK)した場合、Pub/Sub はメッセージの再配信を試みます。この再配信の試行は、サブスクリプションのアクティブなコンシューマに対して行われます。最初に受信したコンシューマに対して行われるとは限りません。そのため、特定のメッセージ ID が、サブスクリプションに接続されている複数の異なるコンシューマに配信され、その処理が試行される可能性があります。これは、いずれかのコンシューマが正常に確認応答するまで続きます。

予期しないメッセージ配信動作が疑われる場合は、複数のコンシューマーがサブスクリプションに同時に接続されているかどうかを調査し、個々のパフォーマンス指標と構成を調べます。

サブスクリプションのフィルタ

サブスクリプションにフィルタが接続されているかどうかを確認します。その場合、フィルタに一致するメッセージのみを受信します。Pub/Sub サービスは、フィルタに一致しないメッセージの確認応答を自動的に行います。フィルタがバックログ指標に与える影響を考慮してください。

returnImmediately オプションを使用する

クライアントが単項 Pull を使用している場合は、returnImmediately フィールドが true に設定されているかどうかを確認します。これは非推奨のフィールドです。このフィールドは、メッセージが返されない場合でも、pull リクエストにすぐに応答するように Pub/Sub サービスに指示します。これにより、バックログがある場合でも、pull リクエストが 0 件のメッセージを返すことがあります。

クライアント構成に関する問題

Java クライアント ライブラリを使用していて、setChannelProvider() メソッドを使用してカスタム gRPC チャネルでサブスクライバーを初期化する場合は、TransportChannelProvider をビルドするときに maxInboundMessageSize の設定が 20 MB 以上(ライブラリのデフォルト値と一致)であることを確認する必要があります。この値が 10 MB 未満の場合、maxInboundMessageSize より大きいメッセージは正しく受信されません。この設定を構成する一般的な方法には、InstantiatingGrpcChannelProvider.Builder.setMaxInboundMessageSize() と ManagedChannelBuilder.maxInboundMessageSize() があります。

重複の処理

サブスクライバーは、次の場合に重複メッセージを受信することがあります。

  • 再納品。クライアントがメッセージに対して否定確認応答を行ったか、確認応答期限が切れた。この動作は予期されたものです。

  • 重複配信。確認応答が成功した後、または確認応答期限が切れる前に、メッセージが再送信された場合。1 回限りの配信が有効になっているサブスクリプションでは、配信が重複することはありません。

  • パブリッシャーからの重複メッセージ。パブリッシャーのアプリケーション ロジックにより、パブリッシャーがメッセージを 2 回送信する。Pub/Sub サービスは、これらを個別の Pub/Sub メッセージとして扱い、一意のメッセージ ID を割り当てます。

メッセージ ID が同じ場合は、Pub/Sub がメッセージを再送信または再配信したことを意味します。メッセージ ID が異なる場合は、パブリッシャーの上流で重複が発生したことを意味します。

期限切れの確認応答期限

Pub/Sub でのメッセージの重複は、サブスクライバーが確認応答期限内にメッセージを確認応答できない場合に発生することがよくあります。これにより、メッセージが再配信され、重複しているように見えます。サブスクライバーがどれくらいの割合で確認応答期限を逃しているかを測定するには、subscription/expired_ack_deadlines_count 指標を使用します。確認応答期限のモニタリング方法の詳細を確認する。

メッセージの期限を延長すると、重複率を低下させることができます。

  • クライアント ライブラリは期限の延長を自動的に処理しますが、構成できる最大延長期限にはデフォルトの上限があります。
  • 独自のクライアント ライブラリを構築する場合は、modifyAckDeadline メソッドを使用して、確認応答期限を延長します。

サブスクライバーでメッセージが pull される速度が、処理と確認応答の速度を上回っている場合、一部のメッセージが期限切れになり、期限の延長が必要になることがあります。ただし、サブスクライバーが過負荷状態のままであると、期限の延長を繰り返しても最終的には失敗します。最悪の場合、サブスクライバーが重複で溢れ、バックログが悪化する可能性があります。期限切れの重複が新しい重複を生成します。

サブスクライバーの過負荷を回避するには、サブスクライバーが一度に pull するメッセージの数を減らします。これにより、サブスクライバーが期限内に処理するメッセージの数が少なくなります。期限切れになるメッセージが減り、再配信されるメッセージも減ります。

サブスクライバーが一度に pull するメッセージの数を減らすには、サブスクライバーのフロー制御構成で未処理メッセージの最大数の設定を減らす必要があります。万能な値はないため、スループットとサブスクライバーの容量に基づいて、未処理メッセージの最大数の上限を調整する必要があります。各アプリケーションはメッセージを異なる方法で処理し、メッセージの確認応答に異なる時間を要することを考慮してください。

再試行を強制する

Pub/Sub にメッセージの再試行を強制するには、nack リクエストを送信します。高レベルのクライアント ライブラリを使用していない場合は、ackDeadlineSeconds を 0 に設定して modifyAckDeadline リクエストを送信します。

順序指定キー

Pub/Sub は、順序指定キーを含むメッセージを再配信するときに、順序指定キーが同じ後続のメッセージ(以前に確認応答されたメッセージを含む)もすべて再配信します。これは、シーケンスの順序を維持するために行われます。ただし、依存メッセージがシーケンス内の前のメッセージの確認応答が成功した後にのみ送信されるという厳密な保証はありません。

サブスクライバーがメッセージを否定応答している

サブスクライバーがメッセージを否定応答しているをご覧ください。

シーク オペレーション

タイムスタンプまたはスナップショットに対してシーク オペレーションを実行すると、Pub/Sub はタイムスタンプより後にパブリッシュされたメッセージ、またはスナップショットに含まれているメッセージを再配信します。この再配信は想定される動作であり、サブスクリプションで 1 回限りの配信が有効になっている場合でも発生します。詳細については、1 回限りの配信でシークするをご覧ください。

ダウンストリームの重複除去

サブスクライバーやその他のダウンストリーム システムでメッセージの重複除去が行われることがあります。たとえば、Dataflow は 1 回限りの配信をサポートしています。重複するメッセージがダウンストリームに予期せず表示される場合は、Pub/Sub ではなくサブスクライバーに原因がある可能性があります。

StreamingPull サブスクリプションのトラブルシューティング

リクエスト レイテンシ指標とエンドツーエンドの配信レイテンシの関係

StreamingPull の場合、指標 serviceruntime.googleapis.com/api/request_latencies は、ストリームが開いている時間を表します。この指標は、エンドツーエンドの配信レイテンシを判断するのに役立ちません。

リクエスト レイテンシ指標を使用する代わりに、配信レイテンシの健全性スコアを使用して、エンドツーエンドの配信レイテンシの増加の原因となっている要因を確認します。

StreamingPull 接続が OK 以外のステータスで終了する

StreamingPull ストリームは、常に OK 以外のステータスで終了します。単一 RPC のエラー ステータスとは異なり、StreamingPull のこのステータスは、ストリームが切断されたことを示しています。リクエストは失敗していません。そのため、StreamingPull API のエラー率が 100% にもなることがありますが、この動作は設計によるものです。

StreamingPull ストリームは常にエラーで終了するため、エラーの診断中にストリーム終了の指標を調べることは役に立ちません。代わりに、response_code または response_class でグループ化された StreamingPull レスポンス指標 subscription/streaming_pull_response_count を重視します。

次のエラーを探します。

  • サブスクリプション バックログに無効な Cloud KMS 鍵で暗号化されたメッセージがある場合、前提条件失敗のエラーが発生することがあります。pull を再開するには、鍵へのアクセスを復元します。

  • Pub/Sub でリクエストを処理できないときに発生する可能性のある使用不可のエラー。これは一時的な状態である可能性が高く、クライアント ライブラリはリクエストを再試行します。クライアント ライブラリを使用している場合は、特に対応は必要ありません。

  • 存在しないエラーは、サブスクリプションが削除された場合、またはサブスクリプションが最初から存在しなかった場合に発生する可能性があります。後者のケースは、無効なサブスクリプション パスを指定した場合に発生します。

その他の関連情報