このページでは、Pub/Sub の exactly-once 機能を使用してメッセージを受信して確認応答する方法について説明します。これにより、メッセージの重複処理を追跡して防止できます。この機能を有効にすると、Pub/Sub では次のセマンティクスが提供されます。
サブスクライバーは、メッセージの確認が成功したかどうかを確認できます。
メッセージの確認応答が正常に完了すると、再配信は行われません。
メッセージが未処理の間、再配信は発生しません。メッセージは、確認応答期限が切れるか、確認応答が行われるまで、未処理とみなされます。
複数の有効な配信が存在する場合は、確認応答期限の経過またはクライアントが開始した否定確認応答により、メッセージの確認応答に最新の確認応答 ID のみを使用できます。以前の確認応答 ID を持つリクエストは失敗します。
1 回限りが有効になっている場合、サブスクライバーは次のガイドラインに従って、メッセージが 1 回だけ処理されるようにできます。
確認応答期限内にメッセージを確認応答します。
メッセージの処理が正常に完了するまで、メッセージの処理の進行状況に関する情報を保持します。
メッセージの処理の進行状況に関する情報を使用して、確認応答が失敗した場合に作業が重複しないようにします。
StreamingPull API を使用するサブスクライバーを含め、pull サブスクリプション タイプのみが 1 回限りの配信をサポートします。push とエクスポートのサブスクリプションでは 1 回限りの配信はサポートされていません。
Pub/Sub では、Pub/Sub で定義された一意のメッセージ ID に基づき、クラウド リージョン内で exactly-once(1 回限り)の配信がサポートされます。
推奨されるクライアント ライブラリのバージョン
- 最適なパフォーマンスを得るには、最新バージョンのクライアント ライブラリである Python v2.13.6 以降、Java v1.120.11 以降、PHP v1.39.0 以降、C# v3.2.0 以降、C++ v2.1.0、Go v1.25.1 以降、Node v3.2.0 以降、Ruby v2.12.1 以降を使用してください。
再配達と重複
想定されている再配信と予期しない再配信の違いを理解することが重要です。
再配信は、メッセージに対してクライアントによる否定確認応答が行われた場合、または確認応答期限が切れる前にクライアントが確認応答期限を延長しなかった場合のいずれかか原因で発生することがあります。再配信は有効であり、システムは意図したとおりに動作しているとみなされます。
再配信のトラブルシューティングについては、重複の処理をご覧ください。
重複とは、確認応答が成功した後、または確認応答期限が切れる前にメッセージが再送信された場合を指します。
再配信されたメッセージには、再配信の試行までの同じメッセージ ID が保持されます。
1 回限りの配信が有効になっているサブスクリプションに対して、配信が重複することはありません。
クライアント ライブラリでの 1 回限りの配信のサポート
サポートされているクライアント ライブラリには、レスポンスを含む確認応答のインターフェースがあります(例: Go)。このインターフェースを使用して、確認応答リクエストが成功したかどうかを確認できます。確認応答リクエストが成功した場合、クライアントは再配信を受信しないことが保証されます。確認応答リクエストが失敗した場合、クライアントは再配信を想定できます。
クライアントは、確認応答インターフェースなしで、サポートされているクライアント ライブラリを使用することもできます。ただし、このような確認応答の失敗によってメッセージのサイレント再配信が生じる可能性があります。
サポートされているクライアント ライブラリには、最小リース延長時間を設定するためのインターフェースがあります(例: Go)。ネットワーク関連の確認応答の有効期限切れを回避するには、最小リース延長の値を大きな値に設定する必要があります。最大値は 600 秒に設定されています。
exactly-once 配信に関連する変数のデフォルト値と範囲、および変数の名前は、クライアント ライブラリによって異なる場合があります。たとえば、Java クライアント ライブラリでは、次の変数によって 1 回限りの配信が制御されます。
変数 | 説明 | 値 |
---|---|---|
setEnableExactlyOnceDelivery |
1 回限りの配信を有効または無効にします。 | true または false(デフォルト =false) |
minDurationPerAckExtension |
変更確認応答の期限の延長に使用する最小時間(秒単位)。 | 範囲=0~600(デフォルト =none) |
maxDurationPerAckExtension |
変更確認応答期限の延長に使用できる最大時間(秒単位)。 | 範囲=0~600(デフォルト =none) |
1 回限りの配信の場合、確認応答 ID がすでに期限切れの場合、PubASub への modifyAckDeadline
または acknowledgment
リクエストが失敗します。この場合、新しい配信がすでに処理中の可能性があるため、サービスは期限切れの確認応答 ID を無効と見なします。これは 1 回限りの配信の配信のための設計です。acknowledgment
リクエストと ModifyAckDeadline
リクエストが INVALID_ARGUMENT
レスポンスを返します。1 回限りの配信の配信が無効になっていると、確認応答 ID が期限切れになった場合にこれらのリクエストは OK
を返します。
acknowledgment
リクエストと ModifyAckDeadline
リクエストに有効な確認 ID が設定されるように、minDurationPerAckExtension
の値を大きな数に設定することを検討してください。
リージョンに関する考慮事項
1 回限りの配信の保証は、サブスクライバーが同じリージョンのサービスに接続する場合にのみ適用されます。サブスクライバー アプリケーションが複数のリージョンに分散されている場合、1 回限りの配信が有効になっている場合でも、メッセージの重複配信が発生する可能性があります。パブリッシャーは任意のリージョンにメッセージを送信でき、exactly-once の保証は維持されます。
Google Cloud 内でアプリケーションを実行すると、デフォルトでは同じリージョンの Pub/Sub エンドポイントに接続します。したがって、通常、Google Cloud 内の単一のリージョンでアプリケーションを実行すると、単一のリージョンとやり取りすることになります。
サブスクライバー アプリケーションを Google Cloud の外部または複数のリージョンで実行している場合は、Pub/Sub クライアントの構成時に位置情報エンドポイントを使用して、単一のリージョンに接続することを保証できます。Pub/Sub のすべてのロケーション エンドポイントは、単一のリージョンを参照します。ロケーション エンドポイントの詳細については、Pub/Sub エンドポイントをご覧ください。Pub/Sub のすべてのロケーション エンドポイントのリストについては、ロケーション エンドポイントのリストをご覧ください。
1 回限りの配信のサブスクリプションを作成する
Google Cloud コンソール、Google Cloud CLI、クライアント ライブラリ、または Pub/Sub API を使用して、1 回限りの配信を行うサブスクリプションを作成できます。
pull サブスクリプション
Console
1 回限りの配信を行う pull サブスクリプションを作成するには、次の手順を行います。
Google Cloud コンソールで、[サブスクリプション] ページに移動します。
[サブスクリプションを作成] をクリックします。
[サブスクリプション ID] を入力します。
プルダウン メニューからトピックを選択するか、作成します。
サブスクリプションがトピックからメッセージを受信します。
[1 回限りの配信] セクションで、[1 回限りの配信を有効にする] を選択します。
[作成] をクリックします。
gcloud
1 回限りの配信を行う pull サブスクリプションを作成するには、--enable-exactly-once-delivery
フラグを指定して gcloud pubsub subscriptions create
コマンドを使用します。
gcloud pubsub subscriptions create SUBSCRIPTION_ID \ --topic=TOPIC_ID \ --enable-exactly-once-delivery
次のように置き換えます。
- SUBSCRIPTION_ID: 作成するサブスクリプションの ID
- TOPIC_ID: サブスクリプションに関連付けるトピックの ID
REST
1 回限りの配信を行うサブスクリプションを作成するには、projects.subscriptions.create
メソッドを使用します。
PUT https://pubsub.googleapis.com/v1/projects/PROJECT_ID/subscriptions/SUBSCRIPTION_ID Authorization: Bearer $(gcloud auth print-access-token)
次のように置き換えます。
- PROJECT_ID: サブスクリプションを作成するプロジェクトのプロジェクト ID
- SUBSCRIPTION_ID: 作成するサブスクリプションの ID
1 回限りの配信を行う pull サブスクリプションを作成するには、リクエスト本文に次のように指定します。
{ "topic": "projects/PROJECT_ID/topics/TOPIC_ID", "enableExactlyOnceDelivery": true, }
次のように置き換えます。
- PROJECT_ID: トピックが含まれるプロジェクトのプロジェクト ID
- TOPIC_ID: サブスクリプションに関連付けるトピックの ID
C++
このサンプルを試す前に、クイックスタート: クライアント ライブラリの使用の C++ の設定手順を実施してください。詳細については、Pub/Sub C++ API リファレンス ドキュメントをご覧ください。
C#
このサンプルを試す前に、クイックスタート: クライアント ライブラリの使用の C# の設定手順を実施してください。詳細については、Pub/Sub C# API リファレンス ドキュメントをご覧ください。
Go
このサンプルを試す前に、クイックスタート: クライアント ライブラリの使用の Go の設定手順を実施してください。詳細については、Pub/Sub Go API のリファレンス ドキュメントをご覧ください。
Java
このサンプルを試す前に、クイックスタート: クライアント ライブラリの使用の Java の設定手順を実施してください。詳細については、Pub/Sub Java API のリファレンス ドキュメントをご覧ください。
Python
このサンプルを試す前に、クイックスタート: クライアント ライブラリの使用の Python の設定手順を実施してください。詳細については、Pub/Sub Python API のリファレンス ドキュメントをご覧ください。
Node.js
このサンプルを試す前に、クイックスタート: クライアント ライブラリの使用の Node.js の設定手順を実施してください。詳細については、Pub/Sub Node.js API リファレンス ドキュメントをご覧ください。
Node.js
このサンプルを試す前に、クイックスタート: クライアント ライブラリの使用の Node.js の設定手順を実施してください。詳細については、Pub/Sub Node.js API リファレンス ドキュメントをご覧ください。
Ruby
このサンプルを試す前に、クイックスタート: クライアント ライブラリの使用の Ruby の設定手順を実施してください。詳細については、Pub/Sub Ruby API リファレンス ドキュメントをご覧ください。
PHP
このサンプルを試す前に、クイックスタート: クライアント ライブラリの使用の PHP の設定手順を実施してください。詳細については、Pub/Sub PHP API リファレンス ドキュメントをご覧ください。
1 回限りのメッセージ配信でサブスクライブする
次のコードサンプルは、クライアント ライブラリを使用して exactly-once 配信でサブスクライブするコードを示しています。
pull サブスクリプション
Go
このサンプルを試す前に、Pub/Sub クイックスタート: クライアント ライブラリの使用にある Go 向けの手順に従って設定を行ってください。 詳細については、Pub/Sub Go API のリファレンス ドキュメントをご覧ください。
Pub/Sub に対する認証を行うには、アプリケーションのデフォルト認証情報を設定します。詳細については、ローカル開発環境の認証を設定するをご覧ください。
Java
このサンプルを試す前に、Pub/Sub クイックスタート: クライアント ライブラリの使用にある Java 向けの手順に従って設定を行ってください。 詳細については、Pub/Sub Java API のリファレンス ドキュメントをご覧ください。
Pub/Sub に対する認証を行うには、アプリケーションのデフォルト認証情報を設定します。詳細については、ローカル開発環境の認証を設定するをご覧ください。
Node.js
このサンプルを試す前に、Pub/Sub クイックスタート: クライアント ライブラリの使用にある Node.js 向けの手順に従って設定を行ってください。 詳細については、Pub/Sub Node.js API のリファレンス ドキュメントをご覧ください。
Pub/Sub に対する認証を行うには、アプリケーションのデフォルト認証情報を設定します。詳細については、ローカル開発環境の認証を設定するをご覧ください。
PHP
このサンプルを試す前に、Pub/Sub クイックスタート: クライアント ライブラリの使用にある PHP 向けの手順に従って設定を行ってください。 詳細については、Pub/Sub PHP API のリファレンス ドキュメントをご覧ください。
Pub/Sub に対する認証を行うには、アプリケーションのデフォルト認証情報を設定します。詳細については、ローカル開発環境の認証を設定するをご覧ください。
Python
このサンプルを試す前に、Pub/Sub クイックスタート: クライアント ライブラリの使用にある Python 向けの手順に従って設定を行ってください。 詳細については、Pub/Sub Python API のリファレンス ドキュメントをご覧ください。
Pub/Sub に対する認証を行うには、アプリケーションのデフォルト認証情報を設定します。詳細については、ローカル開発環境の認証を設定するをご覧ください。
Ruby
このサンプルを試す前に、Pub/Sub クイックスタート: クライアント ライブラリの使用にある Ruby 向けの手順に従って設定を行ってください。 詳細については、Pub/Sub Ruby API のリファレンス ドキュメントをご覧ください。
Pub/Sub に対する認証を行うには、アプリケーションのデフォルト認証情報を設定します。詳細については、ローカル開発環境の認証を設定するをご覧ください。
C++
このサンプルを試す前に、Pub/Sub クイックスタート: クライアント ライブラリの使用にある C++ 向けの手順に従って設定を行ってください。 詳細については、Pub/Sub C++ API のリファレンス ドキュメントをご覧ください。
Pub/Sub に対する認証を行うには、アプリケーションのデフォルト認証情報を設定します。詳細については、ローカル開発環境の認証を設定するをご覧ください。
C#
このサンプルを試す前に、Pub/Sub クイックスタート: クライアント ライブラリの使用にある C# 向けの手順に従って設定を行ってください。 詳細については、Pub/Sub C# API のリファレンス ドキュメントをご覧ください。
Pub/Sub に対する認証を行うには、アプリケーションのデフォルト認証情報を設定します。詳細については、ローカル開発環境の認証を設定するをご覧ください。
Node.js (TypeScript)
このサンプルを試す前に、Pub/Sub クイックスタート: クライアント ライブラリの使用にある Node.js 向けの手順に沿って設定を行ってください。 詳細については、Pub/Sub Node.js API のリファレンス ドキュメントをご覧ください。
Pub/Sub に対する認証を行うには、アプリケーションのデフォルト認証情報を設定します。詳細については、ローカル開発環境の認証を設定するをご覧ください。
1 回限りの配信サブスクリプションをモニタリングする
subscription/exactly_once_warning_count
指標には、再配信の原因となる可能性のあるイベント(有効または重複)の数を記録します。この指標は、Pub/Sub が確認 ID に関連付けられたリクエスト(ModifyAckDeadline
リクエストまたは acknowledgment
リクエスト)を処理できなかった回数をカウントします。失敗の原因は、サーバーまたはクライアントベースである可能性があります。たとえば、1 回限りの配信情報を維持するために使用される永続性レイヤが使用できない場合、サーバーベースのイベントになります。クライアントが無効な確認応答 ID でメッセージを確認応答しようとすると、クライアント ベースのイベントになります。
指標について
subscription/exactly_once_warning_count
は、実際の再配信につながる可能性がある、またはないイベントであり、クライアントの動作によってはノイズの原因となるイベントをキャプチャします。たとえば、確認応答 ID が無効な acknowledgment
リクエストまたは ModifyAckDeadline
リクエストを繰り返すと、指標が繰り返し増加します。
次の指標は、クライアントの動作の把握する際にも有効です。
subscription/expired_ack_deadlines_count
指標は、確認応答 ID の有効期限切れの数を示します。確認応答 ID の有効期限切れは、ModifyAckDeadline
リクエストとacknowledgment
リクエストの両方が失敗する原因となる可能性があります。service.serviceruntime.googleapis.com/api/request_count
指標を使用すると、リクエストが Google Cloud に到達したにもかかわらず Pub/Sub に到達しない場合のModifyAckDeadline
リクエストまたはacknowledgment
リクエストの失敗をキャプチャできます。クライアントが Google Cloud から切断された場合など、この指標ではキャプチャできない障害があります。
再試行可能な障害イベントでは、ほとんどの場合、サポートされているクライアント ライブラリによってリクエストが自動的に再試行されます。
割り当て
1 回限りの配信サブスクリプションには、追加の割り当て要件が適用されます。これらの割り当ては、次の場合に適用されます。
- 1 回限りの配信が有効になっているサブスクリプションから消費されたリージョンごとのメッセージ数。
- 1 回限りの配信が有効になっているサブスクリプションを使用する場合に、確認応答済みのメッセージまたは期限が延長されたメッセージのリージョンごとの数。
これらの割り当ての詳細については、割り当てのトピックの表をご覧ください。
1 回限りの配信と順序指定サブスクリプション
Pub/Sub では、順序付けられた配信による 1 回限りの配信がサポートされています。
1 回限りの配信で順序付けを使用する場合、Pub/Sub は確認応答が順序どおりであることを想定しています。確認応答が順不同である場合、サービスへのリクエストは一時的なエラーによって失敗します。配信に対する正しい確認応答が行われる前に確認応答期限が切れると、クライアントはメッセージの再配信を受け取ります。そのため、1 回限りの配信で順序指定を使用する場合、クライアントのスループットは 1 秒あたり数千件のメッセージに制限されます。
1 回限りの配信と push サブスクリプション
Pub/Sub では、pull サブスクリプションによる 1 回限りの配信のみがサポートされています。
push サブスクリプションからのメッセージを使用するクライアントは、push リクエストに正常なレスポンスで応答することによってメッセージの確認応答を行います。しかし、クライアントには、Pub/Sub サブスクリプションがレスポンスを受信して処理したかどうかはわかりません。これは、クライアントによって確認応答リクエストが開始され、リクエストが正常に処理されると Pub/Sub サブスクリプションが応答する pull サブスクリプションと異なります。このため、1 回限りの配信セマンティクスは、push サブスクリプションと一致しません。
知っておくべきこと
CreateSubscription で確認応答期限が指定されていない場合、1 回限りの配信が有効になっているサブスクリプションには、60 秒のデフォルトの確認応答期限が設定されます。
デフォルトの確認応答期限が長いほど、ネットワーク イベントによる再配信を回避できる可能性が高まります。サポートされているクライアント ライブラリでは、デフォルトのサブスクリプション確認応答期限は使用されません。
1 回限りの配信サブスクリプションでは、通常のサブスクリプションよりもパブリッシュ/サブスクライブ間のレイテンシが大幅に高くなります。
高スループットが必要な場合は、1 回限りの配信クライアントでもストリーミング pull を使用する必要があります。
1 回限りの配信が有効になっていても、パブリッシュ側の重複によって、サブスクリプションが同じメッセージの複数のコピーを受信する場合があります。パブリッシュ側の重複は、パブリッシュを行うクライアントまたは Pub/Sub サービスによる複数の一意のパブリッシュの再試行が原因で発生する可能性があります。再試行を複数回実施する際にパブリッシュを行うクライアントが複数回の一意のパブリッシュを行うと、異なるメッセージ ID を持つ再配信につながります。クライアントのパブリッシュ リクエストに応答するための Pub/Sub サービスによる複数回の一意のパブリッシュが、同じメッセージ ID を持つ再配信につながります。
subscription/exactly_once_warning_count
でエラーを再試行できます。サポートされているクライアント ライブラリは、これらのエラーを自動的に再試行します。ただし、無効な確認応答 ID に関連する失敗は再試行できません。