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