このページでは、Pub/Sub の 1 回限りの機能を使用してメッセージを受信して確認応答する方法について説明します。これにより、メッセージの重複処理を追跡して防止できます。この機能を有効にすると、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 秒に設定されています。
1 回限りの配信に関連する変数のデフォルト値と範囲と、変数の名前はクライアント ライブラリによって異なる場合があります。たとえば、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 回限りの配信が有効になっている場合でも、メッセージの重複配信が発生する可能性があります。パブリッシャーは任意のリージョンにメッセージを送信でき、1 回限りの保証は維持されます。
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 回限りのメッセージ配信でサブスクライブする
クライアント ライブラリを使用して 1 回限りの配信でサブスクライブするためのコードサンプルを以下に示します。
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 に関連する失敗は再試行できません。