今回も、Professional Cloud Data Engineer認定取得するために、私が勉強した内容をアウトプットしていきます。
今回は、Pub/Subの主要な4つのサブスクリプションタイプ、Pub/Subに送られてくるデータの加工、Pub/Subサブスクリプションのベストプラクティスについて説明します!
ぜひ、最後までご覧いただけると嬉しいです!
Pub/Subの主要な4つのサブスクリプションタイプ
この記事では、Pub/Subの主要な4つのサブスクリプションタイプ、Pull(プル)、Push(プッシュ)、BigQuery、そしてCloud Storageについて、その仕組みと最適なユースケースを詳しく解説します。
Pull(プル)配信 – アプリケーション主導のメッセージ受信
Pull配信は、サブスクライバーアプリケーションが自らのタイミングで能動的にPub/Subサーバーにメッセージを要求(プル)しに行く方式です。
- 仕組み:サブスクライバーは、メッセージが必要になるとPub/Subに対して「メッセージをください」というリクエストを送信します。Pub/Subは、サブスクリプションに溜まっているメッセージをレスポンスとして返します。
- 特徴:アプリケーション側でメッセージを処理するペースを完全に制御できます。大量のメッセージをバッチ的に処理したり、負荷に応じて処理量を調整したりするのに適しています。
- 最適なユースケース:
- 大量のタスクを処理するワーカープロセス。
- 外部からのリクエストを受け付けられないセキュアな環境で稼働するアプリケーション。
- 処理負荷の変動が大きいシステム。
Push(プッシュ)配信 – イベント駆動型のリアルタイム通知
Push配信は、Pub/Subがメッセージを受信すると、即座に事前設定されたHTTPSエンドポイント(Webhook)にメッセージを送信(プッシュ)する方式です。
- 仕組み:トピックに新しいメッセージが到着すると、Pub/SubがサブスクライバーのWebサーバーに対してPOSTリクエストを送信します。サブスクライバーは、リクエストのボディに含まれるメッセージを処理します。
- 特徴:メッセージの到着から処理までの遅延が非常に少なく、リアルタイム性が求められる処理に適しています。サーバーレスアーキテクチャ(Cloud Run FunctionsやCloud Run)との親和性が非常に高いです。
- 最適なユースケース:
- リアルタイムでの通知送信(例:チャットアプリへの通知)。
- Cloud Run FunctionsやCloud Runをトリガーするイベントソース。
- 他のシステムとの即時連携。
BigQueryサブスクリプション – 分析のためのダイレクト連携
BigQueryサブスクリプションは、受信したメッセージを、サブスクライバーアプリケーションを介さずに直接BigQueryテーブルに書き込むための特別なタイプです。
- 仕組み:Pub/Subトピックにスキーマ(メッセージの構造定義)を設定しておくと、その構造に従ってメッセージが自動的にBigQueryテーブルの行として追加されます。サブスクライバーのコードを記述する必要はありません。
- 特徴:データ分析パイプラインを大幅に簡素化できます。サーバーレスでスケーラブルなデータインジェスト(取り込み)が可能です。
- 最適なユースケース:
- IoTデバイスからのセンサーデータやログデータのストリーミング分析。
- アプリケーションのイベントログを収集し、リアルタイムで可視化・分析。
- 大量のデータを分析基盤へ継続的に取り込む場合。
Cloud Storageサブスクリプション – データレイクとバッチ処理のための保存
Cloud Storageサブスクリプションは、受信したメッセージを直接Cloud Storageバケットにオブジェクトとして保存するタイプです。
- 仕組み:Pub/Subはメッセージを一定期間または一定サイズでバッチ化し、テキストファイルなどの形式でCloud Storageバケットに書き出します。こちらもサブスクライバーのコードは不要です。
- 特徴:生データをそのままの形で、安価かつ永続的に保存できます。データレイクの構築や、後続のバッチ処理システムへのデータ供給源として活用できます。
- 最適なユースケース:
- すべてのイベントデータを安価にアーカイブ(長期保存)。
- DataflowやDataprocなどのバッチ処理ジョブの入力データソース。
- 機械学習モデルのトレーニングデータの収集。
サブスクリプションタイプの比較表
特徴 | Pull(プル) | Push(プッシュ) | BigQuery | Cloud Storage |
---|---|---|---|---|
制御 | アプリケーション側 | Pub/Sub側 | Pub/Sub側 | Pub/Sub側 |
主な用途 | 大量・バッチ処理 | リアルタイム・イベント駆動 | ストリーミング分析 | データアーカイブ・バッチ入力 |
サブスクライバーコード※ | 必要 | 必要 | 不要 | 不要 |
レイテンシ | 中〜高 | 低 | 低 | 高 |
※サブスクライバーコードは、サブスクライブしたメッセージを処理するプログラムです。
Pub/Subの主要な4つのサブスクリプションタイプのまとめ
Pub/Subには、Pull・Push・BigQuery・Cloud Storageの4つのサブスクリプションタイプがあり、それぞれ適したユースケースが存在します。
Pullは処理ペースを制御したいバッチ処理に、Pushはリアルタイム性が求められる通知やイベント連携に最適です。BigQueryは分析基盤への直接連携を可能にし、Cloud Storageは安価で長期的なデータ保存に強みがあります。
ユースケースに応じてこれらを使い分けることで、柔軟かつ効率的なデータ処理基盤を構築できます。適切なサブスクリプション選択は、システムの拡張性と運用効率を大きく左右します。
Pub/Subに送られてくるデータの加工
Pub/Subに送られてくるデータを、別のツールを使わずに直接加工・振り分けできたら便利だと思いませんか?それを実現するのが、Pub/Subの単一メッセージ変換(SMT)とユーザー定義関数(UDF)です。
これまで、メッセージのフィルタリングやデータ形式の変換、個人情報のマスキングなどを行うには、Dataflowのような別のデータ処理サービスを組み合わせるのが一般的でした。しかし単一メッセージ変換とユーザー定義関数を使えば、これらの処理をPub/Sub内で完結させ、データパイプラインを大幅に簡素化できます。
単一メッセージ変換(SMT)とは?
単一メッセージ変換(SMT)は、Pub/Subのメッセージが流れる途中で、そのデータや属性を軽量に変換する機能です。これにより、以下のような処理をノーコードまたはローコードで実現できます。
- データマスキング:個人情報(PII)などの機密データをマスキングまたは削除する。
- フォーマット変換:JSONからAvroへの変換など、データ形式を変更する。
- メッセージのフィルタリング:不要なイベントデータなどを条件に基づいて破棄する。
- 簡単なデータ操作:新しいフィールドを追加したり、既存のフィールド名を変更したりする。
単一メッセージ変換には、メッセージがトピックに保存される直前に適用されるトピックレベル単一メッセージ変換と、サブスクリプションからメッセージが配信される直前に適用されるサブスクリプションレベル単一メッセージ変換の2種類があります。これにより、「全ての受信者に対して一律の変換を行う」ことや、「受信者ごとに異なる変換を施す」といった柔軟な対応が可能です。
ユーザー定義関数(UDF)で実現するカスタム変換ロジック
単一メッセージ変換の中でも特に強力なのがユーザー定義関数(UDF)です。ユーザー定義関数を使うと、開発者はSQL 式またJavaScriptで独自の変換ロジックを記述し、より複雑で柔軟な処理を実行できます。
<ユーザー定義関数でできること>
- 高度なフィルタリング:メッセージの内容を解析し、特定の条件を満たすメッセージだけを通過させる。
- 動的なデータ変換:メッセージ内の値に基づいて、ペイロードの構造を動的に変更する。
- メッセージの検証:データが特定のスキーマに準拠しているか検証し、準拠していない場合はエラーとして扱う。
制限事項
Pub/Sub の ユーザー定義関数 を利用する際には、いくつかの制約があります。BigQuery の ユーザー定義関数 とは異なる点に注意が必要です。
- 言語の制約:JavaScript のみ利用可能であり、SQL ベースの定義はできません。
- 実行環境の制約:ユーザー定義関数 はサンドボックス環境で実行されるため、外部ネットワークや OS 機能にはアクセスできません。
- 実行時間・サイズの制約:メッセージのサイズや処理時間に上限があり、長時間処理や大容量データの変換には不向きです。
- ライブラリの制約:外部の npm パッケージや追加ライブラリは使用できず、組み込みの JavaScript 機能のみが利用可能です。
- リソース制限:Pub/Sub のクォータやレート制限の対象となり、過剰に複雑な処理を行うと配信遅延やエラーの原因になる場合があります。
Pub/Subに送られてくるデータの加工のまとめ
Pub/Sub の単一メッセージ変換(SMT)とユーザー定義関数(UDF)を活用することで、これまで外部サービスに頼っていたデータ加工を Pub/Sub 内で完結できます。
単一メッセージ変換 により、データマスキングやフォーマット変換、フィルタリングなどをシンプルに実現可能です。
さらに ユーザー定義関数 を使えば、JavaScript や SQL を用いた柔軟かつ高度な変換ロジックを組み込めます。ただし、ユーザー定義関数 には実行環境やライブラリに関する制約があるため、設計時の考慮が必要です。
これらを適切に組み合わせることで、効率的でシンプルなデータパイプラインの構築が可能になります。
Pub/Subサブスクリプションのベストプラクティス
Pub/Subは、スケーラブルで信頼性の高いメッセージングサービスですが、その真価を引き出すには、メッセージを受信する「サブスクライバー」を賢く設計することが不可欠です。
ここでは、Pub/Subを本番環境で安定して運用するために、すべての開発者が知っておくべきサブスクライバーのベストプラクティスを紹介します。
1. フロー制御で過負荷を防ぐ
トラフィックが急増した際、サブスクライバーが処理能力を超える大量のメッセージを一度に受信しようとすると、CPUやメモリを使い果たしてクラッシュする可能性があります。
これを防ぐのがフロー制御です。Pub/Subのクライアントライブラリには、サブスクライバーが一度に処理するメッセージの最大数や、メモリ上にバッファリングするデータの合計サイズ を制限する機能が備わっています。これらの値を適切に設定することで、サブスクライバーは自身の処理能力に合わせてメッセージを受け取ることができ、システムの安定性が向上します。
2. エラー処理を確実に行う
メッセージの処理中にエラーが発生することは避けられません。重要なのは、エラーが発生した際にメッセージが失われないようにすることです。
- 確認応答 (Ack) は処理の最後に実施する:メッセージの処理が完全に成功した後でのみ、Pub/Subに確認応答 (Ack) を返してください。処理の開始直後にAckを返してしまうと、その後の処理でエラーが発生した場合にメッセージが失われてしまいます。
- 失敗したら否定応答 (Nack) を返す:一時的なエラー(例: 外部APIへの接続失敗)で処理に失敗した場合は、明示的に否定応答 (Nack) を返すか、あるいはAckを返さずに応答期限をタイムアウトさせましょう。これにより、Pub/Subはそのメッセージを再配信します。
- 補足:Nackを多用すると意図せず再配信が頻発することがあります。サブスクリプションの再試行ポリシー(リトライポリシー)でエクスポネンシャルバックオフを設定し、無駄なリトライでシステムに負荷をかけるのを避けることも重要です。
- デッドレター トピック (DLT) を活用する:何度再配信しても処理に失敗する「ポイズンピル」のようなメッセージは、メインの処理キューをブロックしてしまいます。このようなメッセージを隔離するために、デッドレター トピック (DLT) を設定してください。指定回数以上処理に失敗したメッセージは自動的にDLTに転送され、後から原因を調査できます。
- 重要:DLTにメッセージが溜まったことを検知するための監視とアラートを設定することは、障害を早期に発見するために不可欠です。
3. 冪等 (べきとう) な処理を実装する
Pub/Subは「少なくとも1回 (at-least-once)」のメッセージ配信を保証します。これは、ネットワークの問題などにより、稀に同じメッセージが複数回配信される可能性があることを意味します。 そのため、サブスクライバーの処理は何度実行しても結果が同じになる「冪等性」を持つように設計する必要があります。
例えば、以下のような工夫が有効です。
- データベースに書き込む際に、メッセージ固有のIDを主キーやユニークキーとして利用し、重複した書き込みをデータベース層で防ぐ。
- 処理済みのメッセージIDをキャッシュ(例:Redis)に一定時間保存しておき、処理の開始前にIDをチェックして重複実行をスキップする。
4. シャットダウン処理を丁寧に行う
アプリケーションをデプロイやメンテナンスのために停止する際、処理中のメッセージを中断してしまうと、データ不整合の原因になります。
アプリケーションを終了する際には、必ずクライアントライブラリが提供する安全なシャットダウン用のメソッドを呼び出しましょう。これにより、新たなメッセージの受信を停止し、現在処理中のメッセージが完了してAckを返すのを待ってから、プロセスが安全に終了します。この「Graceful Shutdown」の実装は、データの整合性を保つ上で非常に重要です。Graceful Shutdown(グレースフル・シャットダウン)とは、システムやアプリケーションを終了させる際に、現在処理中の処理を適切に完了させ、データの一貫性や整合性を保ちながら安全に停止させるプロセスです。
Pub/Subサブスクリプションのベストプラクティス
Pub/Subを安定して運用するには、サブスクライバーの設計が重要です。フロー制御で過負荷を防ぎ、Ack/Nackやデッドレタートピックを活用した堅牢なエラー処理でメッセージ損失を防止することが不可欠です。さらに、冪等性を担保することで重複メッセージにも安全に対応でき、丁寧なシャットダウン処理がデータ整合性を守る最後の砦となります。
まとめ
今回は、下記3点について説明しました。
- Pub/Subの主要な4つのサブスクリプションタイプ
- Pub/Subに送られてくるデータの加工
- Pub/Subトピックのベストプラクティス
Pub/Subは、柔軟で信頼性の高いメッセージング基盤を実現します。
サブスクリプションタイプはPull・Push・BigQuery・Cloud Storageの4種類があり、ユースケースに応じた選択が重要です。さらに、SMTやUDFを活用すれば、Pub/Sub内で効率的にデータ加工を行うことができます。安定運用のためには、フロー制御・エラー処理・冪等性・シャットダウン処理といったベストプラクティスを取り入れることが不可欠です。
これらを組み合わせることで、拡張性が高く、運用しやすいデータ処理基盤を構築できます。
これからも、Macのシステムエンジニアとして、日々、習得した知識や経験を発信していきますので、是非、ブックマーク登録してくれると嬉しいです!
それでは、次回のブログで!