このガイドでは、Pub/Sub の信頼性機能の概要と全体像について説明します。このドキュメントでは、次のトピックについて説明します。
- Pub/Sub を使う理由
- フェイルオーバー
- パブリッシャーの微調整
- サブスクライバーのファインチューニング
- 安全なデプロイのためのスナップショットとシークの使用
Pub/Sub を使う理由
メッセージングのパラダイムとして、publish-subscribe はメッセージのプロデューサーとそれらのメッセージのコンシューマーを分離するように設計されています。プロデューサーは、データとともにコンシューマに直接リクエストを送信する代わりに、そのデータを Pub/Sub などの Pub/Sub サービスにパブリッシュします。このサービスは、サブスクライブしている関心のあるコンシューマーにこれらのメッセージを非同期で配信します。
その結果、このサービスは、データに関心のあるコンシューマーを見つける煩雑さをすべて吸収します。容量に基づいてコンシューマーがデータを受信するレートも管理します。分離することにより、データ プロデューサーは、コンシューマーの行動とは無関係に、低レイテンシで大規模にメッセージを書き込むことができます。
Pub/Sub は、スケーラビリティと信頼性に優れたメッセージを配信できます。サービスでこの処理の大部分は自動的に処理されますが、パブリッシャーとサブスクライバーのさまざまな側面を制御できます。これは可用性とパフォーマンスに影響する可能性があります。このガイドの残りの部分では、これらの側面について詳しく説明します。
フェイルオーバー
Pub/Sub はグローバル サービスである: トピックとトピックとサブスクリプションは本質的に特定のリージョンに結び付けられおらず、必要に応じて、リージョン間の Pub/Sub サービス内でメッセージが流れます。グローバル エンドポイント pubsub.googleapis.com
を使用すると、パブリッシャーとサブスクライバーは、Pub/Sub が実行されるネットワークに最も近いリージョンに接続します。us-central1-pubsub.googleapis.com
などのロケーション エンドポイントを使用する場合、パブリッシャーとサブスクライバーは、指定されたリージョンの Pub/Sub に接続します。 Google Cloudの外部でパブリッシャーまたはサブスクライバーを実行する場合は、ロケーション エンドポイントを使用して、想定されるリージョン間で一貫してメッセージが流れるようにすることをおすすめします。このセクションの残りの部分では、トピックとサブスクリプションの作成方法について説明します。さらに、さまざまな種類のフェイルオーバーとデータ冗長性をサポートするためにパブリッシャーとサブスクライバーを配置する方法についても説明します。
デフォルトのフェイルオーバー セマンティクス
単一のトピックとサブスクリプションがある場合を考えてみましょう。パブリッシャーは米国とオーストラリアのリージョンに存在し、サブスクライバーはヨーロッパとオーストラリアの Google Cloud リージョンにあります。すべてのサブスクライバーにメッセージを受信するのに十分な容量がある場合、メッセージの流れは次のようになります。

P はパブリッシャー、S はサブスクライバーを表します。青い六角形は Pub/Sub サービスを表します。シリンダーは、メッセージが保存される場所を表します(メッセージは常に、パブリッシュされるリージョン内の複数のゾーンに保持されます)。Pub/Sub では、サブスクライバーが利用可能なときにパブリッシュされたリージョン内でメッセージを送信することが優先されます。それ以外の場合は、容量に余裕があるサブスクライバーが存在するネットワークに最も近いリージョンにメッセージが送信されます。したがって、前の図に示すように、米国で公開されたメッセージはヨーロッパのサブスクライバーに配信され、オーストラリア内で公開されたメッセージはオーストラリアに残ります。
以降のセクションでは、さまざまな障害シナリオで何が起きるかについて説明します。
ヨーロッパのサブスクライバーが使用できない
ヨーロッパのサブスクライバーが停止するか、頻繁にクラッシュし、Pub/Sub への接続を維持できないとします。この場合、サービスはオーストラリアのサブスクライバーへのメッセージの配信を開始します。

ヨーロッパとオーストラリアのサブスクライバーが使用できない
すべてのサブスクライバーが使用できない場合、Pub/Sub は構成済みのメッセージ保持期間までメッセージを保存します。

サブスクライバーが再接続されると、停止が構成済みのメッセージ保持期間を超えない限り、メッセージは配信されます。デフォルトでは、サブスクリプション メッセージの保持期間は 7 日間に設定されています。トピックのメッセージ保持期間を最大 31 日間構成することもできます。メッセージ保持期間は、予想される停止または許容される最大停止よりも短くしないでください。
Pub/Sub がヨーロッパで使用できない
まれですが、Pub/Sub 自体が使用できない場合にも対処する場合があります。Pub/Sub が使用できなくなると、パブリッシュまたはサブスクライブ リクエストで予期しないエラーが長時間発生する、またはパブリッシュされたメッセージをサブスクライバーに配信できなくなることがあります。たとえば、ヨーロッパのリージョンで Pub/Sub がダウンした場合、シナリオはサブスクライバーがダウンした場合とほぼ同じになります。

この場合、グローバル エンドポイントを使用しても、ヨーロッパのサブスクライバーは別のリージョンにフェイルオーバーしません。Pub/Sub は自動的にフェイルオーバーしませんサブスクライバー自身が Pub/Sub で予期しない問題を発生させ、使用不能になったとします。このような問題は、重大なサービス停止として扱われます。ただし、サービス停止の影響の範囲は、サブスクライバーが接続しているリージョンに限定できます。サービスで別のリージョンにフェイルオーバーできると、サブスクライバーもそこで使用できなくなり、サービス全体でカスケード障害が発生する可能性があります。
オーストラリアのパブリッシャーが使用できない
1 つのリージョンのパブリッシャーが使用不能になっても、すでにパブリッシュされているメッセージは最も近いサブスクライバーに配信されます。

最終的には、すべてのメッセージがサブスクライバーによって消費され、確認応答されます。Pub/Sub は、メッセージを送信する際に、ネットワーク距離を最小限に抑えようとします。 したがって、ヨーロッパのサブスクライバーに、米国でパブリッシュされたすべてのメッセージを処理するのに十分な容量がある場合、オーストラリアのリージョンのサブスクライバーはメッセージの受信を停止できます。
Pub/Sub が米国で使用できない
Pub/Sub は、リージョン内の複数のゾーンに同期的にメッセージを書き込みます。したがって、メッセージの配信を防ぐには、ゾーンの停止では不十分です。リージョン全体を使用不可にする必要があります。パブリッシャーがメッセージを送信しているリージョンで Pub/Sub が使用できなくなると、サービスが完全に復元されるまで、そのリージョンのメッセージは配信されない可能性があります。

メッセージは、停止期間中遅延しますが、最終的に配信されます(メッセージの保持期間が経過していないと想定)。 サブスクライバーと同様に、米国のパブリッシャーもサービス障害中に別のリージョンにフェイルオーバーしません。この動作により、パブリッシャーまたはサブスクライバーの欠陥によってリージョン間でのカスケード障害が発生する可能性を回避できます。
分離
デフォルトのフェイルオーバー セマンティクスは、データの分離と、パブリッシャー、サブスクライバー、Pub/Sub 自体が使用できないことによりメッセージ フローに影響します。ユースケースによっては、さまざまなレベルの分離が必要になる場合があります。たとえば、すべてのメッセージをリージョン内で配信する必要があるとします。
分離が必要な場合は、デフォルトのフェイルオーバー セマンティクスで十分です。1 つのトピック、1 つのサブスクリプションを作成し、指定したすべてのリージョンにパブリッシャーとサブスクライバーを配置する必要があります。サブスクライバー使用できなくなるか、Pub/Sub が接続先のリージョンでダウンすると、別のリージョンのサブスクライバーに配信がフェイルオーバーされます。
データがリージョンから離れることがないことが保証されるリージョン分離の場合、各リージョンのメッセージを処理するトピックとサブスクリプションを作成します。各リージョンでパブリッシャーとサブスクライバーを見つけ、対応するリージョン トピックとサブスクリプションにパブリッシュし、サブスクライバーにサブスクライブさせます。また、データがリージョン内でのみ移動するように、リージョン エンドポイントを使用する必要があります。単一のリージョンでパブリッシャー、サブスクライバー、Pub/Sub に障害が発生した場合、そのリージョンでのメッセージ配信が停止します。他のリージョンのトピックとサブスクリプションのメッセージ配信は影響を受けません。
最後に、データが 1 つのゾーン内に留まることが保証されているゾーン分離は、Pub/Sub ではできません。個々のゾーンを独立させる必要がある場合は、Pub/Sub Lite を使用します。
お客様が制御するフェイルオーバーと冗長性
Pub/Sub のデフォルトのフェイルオーバー セマンティクスでは、間に停止が発生した場合に、メッセージが常にパブリッシャーからサブスクライバーに流れることを保証するものではありません。サービス停止は、クライアントや、パブリッシャーまたはサブスクライバーが稼働するサービス、ネットワーク、さらには Pub/Sub 自体においても、さまざまな場所で発生する可能性があります。 このような停止に対するサービスの復元性が必要な場合は、独自の冗長性を実装する必要があります。通常、これらの冗長性には、パブリッシャーとサブスクライバーのクライアントの複数のインスタンスを使用することがあり、それぞれが異なるロケーション エンドポイントを使用します。
ゾーンまたはリージョンという 2 つの異なる影響範囲に対して復元力を設定できます。 それぞれの設定オプションは次のとおりです。
ゾーンの復元性
Pub/Sub にはゾーン間レプリケーションが組み込まれています。サービス自体に影響を与えるシングルゾーンの停止に対処するために、特別な手順を行う必要はありません。ただし、クライアントやネットワークの停止に対する復元力を確保するには、リージョン内の複数のゾーンで十分な容量を持つパブリッシャーとサブスクライバーを実行することをおすすめします。1 つのゾーンが停止した場合、他のゾーンのクライアントはトラフィックを受信してメッセージを処理できます。バグが発生しても、手つかずの他のゾーンがメッセージの処理を継続できるように、これらのクライアントに対する変更を同時に公開しないことをおすすめします。
リージョンの復元性
リージョンの障害に対する復元力を確保するため、パブリッシャーとサブスクライバーに追加の冗長性を設定します。パブリッシャーとサブスクライバーを複数のリージョンで実行して、これらのクライアントやネットワークの停止の可能性に対処できます。
リージョンの Pub/Sub の障害に対する復元力を確保するには、このような停止に対処するためのフェイルオーバー メカニズムが必要です。エンドツーエンドのメッセージ配信のレイテンシと費用のトレードオフが考えられるアプローチがあります。
費用が問題でない場合のレイテンシを最小限に抑えるには、異なるリージョンで常に公開とサブスクライブを同時に行うことをおすすめします。まず、冗長性が必要なリージョンの数を選択します。 次に、厳密には必要ありませんが、これらのリージョンごとにトピックとサブスクリプションを設定できます。
各パブリッシャーは、リージョンと同じ数のパブリッシャー クライアントを作成し(リージョンごとに 1 つずつ)、異なるロケーション エンドポイントを使用して、メッセージが別々のリージョンに送られるようにします。別々のトピックを使用する場合、各パブリッシャー クライアントは対応するリージョンごとのトピックにパブリッシュする必要があります。メッセージごとに、パブリッシャーは各クライアントにパブリッシュします。冗長なパブリッシュでは、1 つのパブリッシュが失敗しても再試行する必要はありません。
同様に、各サブスクライバーはリージョンごとに 1 つのサブスクライバー クライアントを作成し、ロケーション エンドポイントを使用して別のリージョンに接続します。リージョンごとに異なるサブスクリプションを使用する場合は、各サブスクライバー クライアントが対応するサブスクリプションを使用する必要があります。パブリッシャーとサブスクライバーに使用されるリージョンは、必ずしも同じである必要はありません。サブスクライバーは 3 つのサブスクリプション間でメッセージを受信し、処理します。
この設定の主な機能と要件は次のとおりです。
- シングルリージョンの停止は、すでにパブリッシュされたメッセージの処理や、停止中にパブリッシュされたメッセージの処理に影響しません。メッセージは複数のリージョンにパブリッシュされているため、1 つのリージョンがダウンしても他のリージョンで使用できます。停止中、影響を受けるリージョンでは公開呼び出しが失敗しますが、他のリージョンでは成功します。
- メッセージが流れるリージョンのいずれかが利用可能である限り、メッセージ処理のレイテンシは影響を受けません。
- メッセージ処理はべき等である必要があります。すべてのメッセージが複数回配信されるため、メッセージ処理には重複に対する復元力が必要です。リージョンが停止した場合、これらの重複の一部は、最初にメッセージが配信された時点よりもかなり遅れて発生する可能性があります。これらに重複は、停止が発生していない別のリージョンで発生している可能性があります。
このような種類の冗長性を実行することにより、いかなる種類の停止に対しても高い復元力を実現できます。Pub/Sub を使用し、最も高い可用性を必要とする内部 Google サービスの場合は、この設定をおすすめします。ただし、この設定では、メッセージ配信の費用が使用するリージョン数の倍数となるというトレードオフがあります。また、メッセージがリージョン間で移動する必要がある場合、リージョン間のネットワーク使用量によって追加コストが発生します。
冗長性のもう 1 つのアプローチは、リクエストが失敗した場合や、パブリッシャーからサブスクライバーにメッセージが想定どおりに流れない場合にのみフェイルオーバーすることです。このシナリオでは、ロケーション エンドポイントを介してパブリッシャーとサブスクライバーを誘導するプライマリ リージョンが 1 つあります。以前と同様に、これらは同じリージョンである必要はありません。さらに、プライマリ リージョンが利用できない場合に使用されるパブリッシャーとサブスクライバー用のフォールバック リージョンも作成されます。
パブリッシャーは、リクエストが正常に送信された場合(ロケーション エンドポイントを介して)プライマリ リージョンにのみパブリッシュします。リージョンが停止していると判断されるたびに、パブリッシャーはフォールバック リージョンへの公開を開始します。リージョンの停止とフェイルオーバーを判断するには、2 つの方法があります。これは手動プロセスで行うことができます。この設定はパブリッシャーで動的に更新されます。パブリッシャーは、パブリッシュ リクエストのエラー率が十分に高い場合は、構成を自ら更新することもできます。
サブスクライバーは常にロケーション エンドポイントを介してプライマリ リージョンに接続する必要があります。サブスクライバーが次の 1 つ以上のトリガーでフォールバック リージョンを使用できるかどうかを判断できます。
- 常にフォールバック リージョンにサブスクライブする。この場合、サブスクライバーはプライマリ リージョンとフォールバック リージョンの両方への接続を常に維持します。パブリッシャーとサブスクライバーの両方のプライマリとフォールバックに同じリージョンを使用できます。この場合、サブスクライバーは、パブリッシャーがフェイルオーバーした場合にのみ、バックアップ リージョン経由でメッセージを受信する必要があります。
- 構成を使用して、サブスクライバーを手動で検出し、フォールバック リージョンに切り替えます。サービス停止を検出した場合は、フォールバック リージョンにフェイルオーバーし、停止が解消したらプライマリ リージョンに戻すことができます。
- サブスクライバー エラーでフェイルオーバーする。サブスクライバー リクエストでエラーが返された場合、これをフォールバック リージョンにフェイルオーバーする必要があることを示すものとして使用できます。Pub/Sub クライアント ライブラリは、一時的なエラー時に内部でストリーミング pull リクエストを再試行するため、予期しないエラーが長時間発生していることを検出できない場合があります。また、通常のオペレーションであっても、ストリーミング pull のエラー率は 100% と想定されています。
- サブスクライバーがメッセージを受信せずに、予期せず長時間経過した場合にフェイルオーバーする。メッセージが一貫してパブリッシュされると仮定すると、サブスクライバーは常にメッセージを受信できます。サブスクライブがメッセージを長期に渡ってしない場合、プライマリ リージョンの Pub/Sub にサブスクライブ側の問題がある可能性があります。この問題は、フォールバック リージョンにフェイルオーバーすることで解決します。
4 つのうち、1 番目の方法が理想的です。サブスクライバーの接続にメッセージが流れない場合、サブスクライバーの接続に料金は発生しません。唯一の費用は、サブスクライバー クライアント ライブラリの追加インスタンスのフットプリントですが、これはごくわずかである場合があります。また、リージョン割り当てごとのオープン ストリーミング pull 接続数にも注意する必要があります。
この 2 番目のモデルの利点は、メッセージが 1 回だけパブリッシュされるため、Pub/Sub の費用に乗数がないことです。ただし、トレードオフとして、特定の種類の停止では、停止が開始する前にパブリッシュされたメッセージは、停止から復旧するまで利用できないことがあります。使用できないリージョンに保存されているメッセージは、接続場所に関係なく、サブスクライバーに配信できない場合があります。停止中にフォールバック リージョンにパブリッシュされたメッセージを使用できます。また、パブリッシャーまたはサブスクライバーのエラー率が上昇し、利用できなくなる期間が生じることがあります。これは、停止を検出する方法と、フォールバック リージョンにフェイルオーバーする時間によって異なります。
どのオプションを選択した場合でも、Pub/Sub の機能とどのように相互作用するかに注意してください。注文型配達と exactlyOnce 配達はどちらも、リージョン内の保証を提供します。たとえば、フェイルオーバーの冗長性技術を使用する場合、メッセージ配信は、同じリージョンにパブリッシュされるメッセージに対してのみ保証されます。メッセージが最初にプライマリー リージョンにパブリッシュされていた場合でも、プライマリ リージョンにメッセージがパブリッシュされる前に、サブスクライバーは、フォールバック リージョンにパブリッシュされたメッセージを受信できます。
パブリッシャーの微調整
どのフェイルオーバー オプションを選択しても、パブリッシャー内で追加の調整手順を行う必要があります。パブリッシャーの動作を調整することで、負荷が高い状況でも最適なパフォーマンスを実現できます。メッセージのバッチ処理は、コストとレイテンシをトレードオフする方法ですが、信頼性にはそれほど重要でないため、ここでは説明しません。代わりに、再試行設定やフロー制御設定など、信頼性の調整に役立つ他のパラメータに焦点を当てます。
パブリッシュは、ネットワーク使用不能などの一時的なものや、権限の変更などユーザーの操作が必要なものなど、さまざまな理由で失敗する可能性があります。Pub/Sub クライアント ライブラリは、再試行設定で指定されたパラメータを使用して一時的なエラーを再試行します。これらの設定は、一時的な理由で失敗した公開 RPC の再試行時の指数バックオフの動作を制御します。通常はデフォルト設定のままで問題ありませんが、これらの値の調整が必要になる場合もあります。
チューニングする可能性が高い 2 つのプロパティは、初期 RPC タイムアウトと合計タイムアウトです。初期 RPC タイムアウトは、最初のパブリッシュ RPC が完了するまでの時間です。いずれかの RPC が失敗するかタイムアウトすると、リクエストの合計数または合計タイムアウトを超えるまで、より長いタイムアウトで別の RPC が試行されます。
初期タイムアウトは、パブリッシャーがネットワークの制約を受けている場合や、Pub/Sub を実行する最も近いデータセンターから Google Cloud 離れている場合に調整できます。ネットワークの制約は、パブリッシャーが稼働しているマシンのスループットの制限である場合もあれば、同じマシン上で実行され、ネットワーク負荷の高い他のサービスの結果である場合もあります。タイムアウトの設定が短すぎると、最初の RPC が繰り返し失敗し、パブリッシュに成功するまでの試行が多くなります(タイムアウトが長くなります)。繰り返しの再試行が必要になると、パブリッシュのレイテンシが増加します。この場合、初期タイムアウトを長くするとパブリッシュが高速化される可能性があります。
ネットワーク接続が不安定な場合は、合計タイムアウトと初期タイムアウトを増やすと解決することがあります。合計タイムアウトを長くすると、パブリッシュ RPC が常に完了するための時間が長くなります。公開 RPC が期限超過エラーにより常に失敗する場合は、これらの値の調整を検討してください。
連続した期限超過エラーは、パブリッシャーのフロー制御を調整する必要があることを示している場合もあります。これらの設定により、Pub/Sub に送信されるメッセージをさらに生成する受信トラフィックの急増に対して、パブリッシャーの復元力を確保できます。送信リクエストが大幅に増加すると、パブリッシャーの CPU、メモリ、またはネットワーク容量が過負荷状態になる可能性があります。パブリッシュが過負荷になると、タイムアウト前にパブリッシュ リクエストまたはレスポンスを処理できなくなります。これにより、パブリッシュ リクエストがさらに増加し、最終的に合計タイムアウトに達します。パブリッシャー フロー制御では、パブリッシュ リクエストからのレスポンスのない未処理のメッセージまたはバイト数が制限されます。このようにリクエスト数を制限することで、急増時でもリソース使用率を管理可能なレベルに維持できます。パブリッシャーの運用方法によっては、パブリッシュにそれ以上のリクエストをブロックできるようにすることで、後続の publish RPC が容量を待機できるようにすることができます。または、容量に達したときにフロー制御がエラーを返すようにすることで、サービスの呼び出し元に push バックできます。パブリッシャー クライアント ライブラリが上限超過の動作に応答する方法を構成します。
サブスクライバーのファインチューニング
確実に動作させるには、サブスクライバーの調整が必要になることもあります。パブリッシャーと同様に、サブスクライバーのフロー制御設定を調整して、過負荷にならないようにすることができます。サブスクライバー クライアント ライブラリはストリーミング pull を使用します。この場合、クライアントがサーバーに永続ストリームを開き、サーバーは利用可能になるとメッセージを送信します。パブリッシュされたメッセージが大幅に増加した場合、サブスクライバーは処理可能な量を超えるメッセージを受信することがあります。フロー制御を実装すると、クライアントに同時に送られる未確認メッセージの数が制限されます。これにより、同時に処理されるメッセージの数が減少し、長期間にわたって処理を分散させます。負荷の分散により、サブスクライバーをメッセージ処理に影響を与えるリソースの制限内にとどまらせることができます。これによりメッセージを処理できなくなるカスケード効果が発生する可能性があります。
処理するデータ量の急増が予想される場合は、フロー制御のみで十分です。使用率の増加によってトラフィックが時間とともに増加する場合、フロー制御によってサブスクライバーを保護します。ただし、バックログが蓄積され続け、メッセージの保持期間が経過する前にメッセージを配信できなくなる可能性があります。そのような場合は、自動スケーリングを設定して、未確認メッセージの増加に対応してサブスクライバーを増やすこともできます。設定方法は、サブスクライバーで使用しているコンピューティング プラットフォームによって異なります。たとえば、Compute Engine のオートスケーラーを使用すると、未配信メッセージの数などの指標に基づいてスケーリングできます。自動スケーリングとフロー制御の両方を使用することで、メッセージ スループットのその他の短期的な急増や、より多くのコンピューティング能力を必要とする長期的な増加に対して、サブスクライバーが耐障害性を確保できます。Pub/Sub 指標をスケーリング シグナルとして使用するためのベスト プラクティスに従ってください。
安全なデプロイのためにスナップショットとシークを使用する
通常、メッセージ損失は致命的な事態です。Pub/Sub では、パブリッシュされたすべてのメッセージについて、少なくとも 1 回の配信が行われます。ただし、これらのメッセージを正しく処理できるかどうかは、サブスクライバーの動作によって異なります。メッセージの確認応答に成功しても、Pub/Sub はメッセージを再配信しません。したがって、デプロイする新しいサブスクライバー コードでバグが発生し、メッセージが正しく処理されなかった場合、サブスクライバーによってメッセージが失われる可能性があります。 Pub/Sub にはスナップショットとシーク機能があり、サブスクライバーにバグが発生した場合でも、すべてのメッセージを正しく処理できます。
サブスクライバーのデプロイのパターンは次のようになります。

新しいサブスクライバーが機能しているかどうかを判断するまでの待機時間は、ユースケースによって異なります。ステップのフローを終了する唯一の方法は、サブスクライバーが動作していると見なされたときです。動作している時点でスナップショットを削除できます。
スナップショットとシークの使用は、非本番環境でのソフトウェアの初回実行と本番環境への段階的なデプロイに関するベスト プラクティスに代わるものではありません。これらは、データ処理の信頼性を確保するための、保護強化策を提供するものです。トレードオフは、スナップショットまでシークすると、サブスクライバーが処理したメッセージが重複して配信される可能性があることです。ただし、Pub/Sub には少なくとも 1 回配信のセマンティクスがあるため、サブスクライバーはすでにメッセージの再配信に対して復元性を備えています。