---
title: "Cloud Pub/Subとは？トピックとサブスクリプションの仕組み・料金・Pythonでの送受信を実装者目線で解説"
url: "https://www.issoh.co.jp/tech/details/12385/"
published: 2026-06-05
updated: 2026-10-09
categories: ["Google Cloud"]
publisher: "株式会社一創"
---

# Cloud Pub/Subとは？トピックとサブスクリプションの仕組み・料金・Pythonでの送受信を実装者目線で解説

Cloud Pub/Sub（Google Cloud Pub/Sub）は、メッセージを送る側（パブリッシャー）と受け取る側（サブスクライバー）を切り離す、Google Cloudのフルマネージドなメッセージングサービスです。名前の「Pub/Sub」は publisher / subscriber の略で、送り手が宛先を知らずに「トピック」へ投げ、受け手は「サブスクリプション」から取り出すという設計パターンそのものを指します。この記事では、Google Cloudの製品としてのPub/Subについて、仕組み・配信方式の選び方・Pythonでの送受信コード・料金の計算方法・Cloud TasksやKafkaとの使い分けを、公式ドキュメントとローカルのエミュレータで動かした結果をもとに解説します。

## まとめ：Cloud Pub/Subの要点

- 送信先は**トピック**、受信元は**サブスクリプション**。1トピックに複数のサブスクリプションを付けると各サブスクリプションに同じメッセージが複製され、1サブスクリプションに複数のワーカーを付けるとメッセージが分散されます。
- 配信は既定で**at-least-once（少なくとも1回）**。ACK期限（既定10秒・最大600秒）内に確認応答が無いと再配信されるため、受信処理は重複しても壊れない作りにします。
- 配信方式は pull（StreamingPull含む）・push・エクスポート（BigQuery／Cloud Storage）の3系統。exactly-once配信が使えるのは pull だけです。
- 料金は月10GiBまで無料、超過分は1TiBあたり40ドル。1リクエストあたり最低1KBで計算されるため、小さなメッセージは1件ずつ送らずバッチにまとめます。
- 実行時刻の指定や宛先ごとの流量制御が必要ならCloud Tasks、長期間のログ再生とパーティション単位の処理が中心ならKafkaが候補です。Pub/Sub Liteは2027年1月31日に提供終了します。

以下、仕組み→実装→料金→使い分けの順に、判断の根拠となる仕様を示します。

## トピックとサブスクリプションの関係

まず押さえる基本要素は、メッセージ・トピック・サブスクリプションの3つです。パブリッシャーはトピック名だけを指定して送信し、誰が受け取るかは知りません。受け取る側はトピックに紐づくサブスクリプションを作り、そこからメッセージを取り出します。

### ファンアウト型とキュー型の切り替え

同じ仕組みで「全員に配る」と「1件を1人が処理する」の両方を作れるのがPub/Subの特徴です。違いはサブスクリプションの作り方だけです。

| 構成                  | 挙動                  | 典型例                |
| ------------------- | ------------------- | ------------------ |
| 1トピック × 複数サブスクリプション | 各サブスクリプションに全件が複製される | 注文イベントを在庫・通知・分析へ配る |
| 1サブスクリプション × 複数ワーカー | メッセージがワーカー間で分散される   | 画像変換ジョブを並列処理する     |

設計時に見落としやすいのが、**サブスクリプションを作る前にトピックへ送られたメッセージは受け取れない**という仕様です。公式ドキュメントも「サブスクリプション作成後にトピックへ発行されたメッセージだけがサブスクライバーから利用できる」と明記しています。新しい処理系を後から追加して過去分も欲しい場合は、トピック側でメッセージ保持（既定は無効、設定範囲10分〜31日）を有効にしておき、シークで巻き戻す必要があります。

### ACK期限と再配信の仕組み

サブスクライバーへ渡されたメッセージは、確認応答（ACK）が返るまで「未処理（outstanding）」として扱われます。サブスクリプションのACK期限は既定10秒で、10〜600秒の範囲で設定できます。期限内にACKが無いと、Pub/Subは同じメッセージを再配信します。

処理が600秒を超える場合でも、公式のクライアントライブラリは期限の延長要求を自動で送り続けます。Pythonの `google-cloud-pubsub` 2.42.0 では `FlowControl` の `max_lease_duration` が既定3600秒で、この時間まではライブラリが期限を延ばします。ACK期限を最大値に上げるより、ライブラリの延長に任せたうえで処理そのものを短く分割するほうが、ワーカー停止時の再配信待ちが短く済みます。

未ACKのメッセージはサブスクリプションに既定7日（最大31日）保持され、それを過ぎると破棄されます。メッセージ1件の `data` は最大10MBです。

## pull・push・エクスポートの選び方

サブスクリプションを作るときは配信方式を1つ選びます。作成後に変更もできますが、受信側の実装が変わるため最初に決めておきます。

| 方式                  | 取得の主導    | exactly-once | 向く受信側                      |
| ------------------- | -------- | ------------ | -------------------------- |
| pull（StreamingPull） | サブスクライバー | 対応           | GKE・Compute Engine上の常駐ワーカー |
| push                | Pub/Sub  | 非対応          | Cloud RunなどのHTTPSエンドポイント   |
| BigQueryエクスポート      | Pub/Sub  | 非対応          | 受信コード不要でテーブルへ書き込む          |
| Cloud Storageエクスポート | Pub/Sub  | 非対応          | 受信コード不要でバケットへファイル出力        |

大量のメッセージを継続処理するならpullのStreamingPullが第一候補です。1本の接続を張ったままメッセージを流し込むため、リクエストごとの往復が発生せず、クライアントライブラリのフロー制御で同時処理数も絞れます。この他にBigtableへのエクスポート（プレビュー）もあります。

### pushサブスクリプションの応答コードと認証

pushでは、Pub/SubがメッセージをHTTPS POSTでエンドポイントへ送り、エンドポイントの応答コードがACKの代わりになります。ACK扱いになるのは `102`・`200`・`201`・`202`・`204` だけで、それ以外のコードは否定応答として再送の対象です。push配信ではメッセージ単位でACK期限を延長できず、処理時間の上限は10分です。

エンドポイントを公開URLにする場合は、push認証を有効にします。Pub/SubがJWTに署名して `Authorization` ヘッダに載せるので、受信側でそのトークンを検証すれば、第三者からの偽リクエストを弾けます。[Cloud Runのサーバーレスコンテナ](/tech/details/15435/)を受信側にする構成がこのパターンの典型です。

### エクスポートサブスクリプションと単一メッセージ変換

BigQuery／Cloud Storageサブスクリプションは、受信コードを書かずにメッセージをテーブルやバケットへ書き出します。単純な転送ならDataflowを挟む必要がなくなりますが、料金は1TiBあたり50ドルで、通常のスループットにある月10GiBの無料枠は適用されません。

書き出す前に項目を削る・形式を整える程度の加工は、2025年6月2日に一般提供となった単一メッセージ変換（SMT）でトピックやサブスクリプションに設定できます。結合や集計を伴う処理は[Apache Beamの実行基盤であるDataflow](/tech/details/15553/)の担当です。

## Pythonでの送受信手順（エミュレータで実行確認）

ここからのコードは、Pub/Subエミュレータ 0.8.36 と `google-cloud-pubsub` 2.42.0（PyPIの2026年10月1日公開版）、Python 3.12 で実行して出力を確認したものです。エミュレータに課金は発生しません。

### gcloud CLIによるトピックとサブスクリプションの作成

まず実環境での最小手順です。トピックを作り、サブスクリプションを紐づけ、1件送って取り出します。

```
gcloud pubsub topics create my-topic
gcloud pubsub subscriptions create my-sub --topic=my-topic
gcloud pubsub topics publish my-topic --message="hello"
gcloud pubsub subscriptions pull my-sub --auto-ack
```

開発中は、以下のPythonコードをローカルのエミュレータに向けると、実際のGoogle Cloudプロジェクトや認証情報なしで試せます。直前の `gcloud pubsub` コマンドはエミュレータに対応しません。`gcloud components install pubsub-emulator` で導入し、起動したら別ターミナルで環境変数を設定します。クライアントライブラリは `PUBSUB_EMULATOR_HOST` が設定されていれば自動でエミュレータへ接続します。

```
gcloud beta emulators pubsub start --project=demo-project
# 別ターミナルで
$(gcloud beta emulators pubsub env-init)
```

### Pythonでの作成と送信（バッチ設定と属性）

Python 3.12の仮想環境で `python -m pip install google-cloud-pubsub==2.42.0` を実行してから、以下のコードを順に実行します。トピックとサブスクリプションの作成はクライアントライブラリからも行えます。ACK期限はここで60秒に設定しています。

```
from google.cloud import pubsub_v1

project_id = "demo-project"
publisher = pubsub_v1.PublisherClient()
subscriber = pubsub_v1.SubscriberClient()

topic_path = publisher.topic_path(project_id, "orders")
sub_path = subscriber.subscription_path(project_id, "orders-worker")

publisher.create_topic(request={"name": topic_path})
subscriber.create_subscription(
    request={
        "name": sub_path,
        "topic": topic_path,
        "ack_deadline_seconds": 60,
    }
)
print("created:", topic_path, sub_path)
```

送信側では `BatchSettings` でバッチの区切りを決めます。Python版の既定は100件・1,000,000バイト・0.01秒で、下の例は待ち時間だけ0.05秒に延ばしています。`publish()` は即座にFutureを返し、`result()` でサーバーが採番した `message_id` を受け取れます。

```
import json
from google.cloud import pubsub_v1

project_id = "demo-project"
batch = pubsub_v1.types.BatchSettings(
    max_messages=100,       # 100件たまったら送信
    max_bytes=1_000_000,    # 約1MBに達したら送信
    max_latency=0.05,       # 最大50ミリ秒待って送信
)
publisher = pubsub_v1.PublisherClient(batch_settings=batch)
topic_path = publisher.topic_path(project_id, "orders")

futures = []
for i in range(3):
    data = json.dumps({"order_id": f"A-{i:04d}", "amount": 1200}).encode("utf-8")
    # 属性は文字列のみ。サブスクリプションのフィルタに使える
    futures.append(publisher.publish(topic_path, data, event_type="order.created"))

for f in futures:
    print("message_id:", f.result(timeout=30))
```

属性（ここでは `event_type`）は本文と別に運ばれるキーと値の組で、サブスクリプションのフィルタ条件に使えます。本文をJSONで解析しなくても振り分けられるので、イベント種別のように受信側が分岐に使う値は属性に置きます。

### StreamingPullでの受信とフロー制御

受信側は `subscribe()` にコールバックを渡します。内部ではStreamingPullの接続が張られ、メッセージが届くたびに別スレッドでコールバックが呼ばれます。

```
import json
from concurrent.futures import TimeoutError
from threading import Lock
from google.cloud import pubsub_v1

project_id = "demo-project"
subscriber = pubsub_v1.SubscriberClient()
sub_path = subscriber.subscription_path(project_id, "orders-worker")
processed = set()  # 本番ではDBの一意制約などで重複を弾く
callback_lock = Lock()  # コールバックは複数スレッドから同時に呼ばれる

def callback(message: pubsub_v1.subscriber.message.Message) -> None:
    with callback_lock:
        _handle_message(message)

def _handle_message(message: pubsub_v1.subscriber.message.Message) -> None:
    body = json.loads(message.data)
    key = body["order_id"]
    if key in processed:
        message.ack()  # 再配信された重複は処理せずACKだけ返す
        return
    print(key, message.attributes.get("event_type"), "attempt:", message.delivery_attempt)
    processed.add(key)
    message.ack()

flow = pubsub_v1.types.FlowControl(max_messages=10)
future = subscriber.subscribe(sub_path, callback=callback, flow_control=flow)
with subscriber:
    try:
        future.result(timeout=10)
    except TimeoutError:
        future.cancel()
        future.result()
```

エミュレータでの出力は次のとおりです。

```
A-0000 order.created attempt: None
A-0001 order.created attempt: None
A-0002 order.created attempt: None
```

`FlowControl(max_messages=10)` は「ACKしていないメッセージを同時に10件までしか抱えない」という上限です。既定は1,000件なので、1件の処理が重いワーカーで既定のまま動かすと、メモリを使い切るか、抱えたメッセージのACK期限延長が追いつかなくなります。このサンプルはコールバック全体をロックで直列化しているため、複数スレッドで並行処理する利点はありません。本番では重複判定をDBの一意制約に任せ、ロックを外して並行に処理させます。`delivery_attempt` が `None` になっているのは、配信回数がデッドレタートピックを設定したサブスクリプションでしか数えられないためです（後述）。

## 重複・順序・処理失敗への備え

Pub/Subの受信処理で備えるべき事象は、「同じメッセージが2回来る」「順番が入れ替わる」「処理できないメッセージが保持期間中に繰り返し再送される」の3つです。対策はいずれもサブスクリプションの設定と受信コードの組み合わせで決まります。

### at-least-once配信と冪等な受信処理

既定の配信保証は少なくとも1回で、ACKがPub/Subに届く前にワーカーが落ちれば同じメッセージがもう一度届きます。受信処理は、同じメッセージを2回処理しても結果が変わらない（冪等）ように作ります。実務では、イベントを一意に識別するキーにDBの一意制約を設け、処理済み記録と業務データの更新を同一トランザクションで確定します。外部APIへの副作用には、そのAPIの冪等性キーなどで別途対処します。上のコードの `processed` はその考え方を最小化したものです。

exactly-once配信を有効にすれば重複配信はPub/Sub側で抑えられますが、条件が厳しめです。対応するのはpullサブスクリプション（StreamingPull含む）だけで、pushとエクスポートは非対応です。保証はサブスクライバーが同じリージョンのサービスへ接続している場合に限られ、複数リージョンに分散したワーカーでは重複が起こり得ます。順序指定と併用するとスループットは毎秒数千件程度に制限されます。この制約を踏まえると、**exactly-onceを有効にしても受信側の冪等化は省略しない**のが安全な設計です。

### 順序指定キーでの順序保証

Pub/Subは既定では配信順を保証しません。同じユーザーの「作成→更新→削除」のように順番が意味を持つ場合は、順序指定キー（ordering key）を使います。設定はパブリッシャー側とサブスクリプション側の両方に必要です。

```
from google.cloud import pubsub_v1

project_id = "demo-project"
publisher = pubsub_v1.PublisherClient(
    publisher_options=pubsub_v1.types.PublisherOptions(enable_message_ordering=True)
)
subscriber = pubsub_v1.SubscriberClient()
topic = publisher.topic_path(project_id, "user-events")
sub = subscriber.subscription_path(project_id, "user-events-ordered")
publisher.create_topic(request={"name": topic})
subscriber.create_subscription(request={"name": sub, "topic": topic, "enable_message_ordering": True})
for step in ["created", "updated", "deleted"]:
    publisher.publish(topic, step.encode(), ordering_key="user-42").result()
r = subscriber.pull(request={"subscription": sub, "max_messages": 10}, timeout=5)
print([m.message.data.decode() for m in r.received_messages])
if r.received_messages:
    subscriber.acknowledge(request={
        "subscription": sub,
        "ack_ids": [m.ack_id for m in r.received_messages],
    })
```

エミュレータでは `['created', 'updated', 'deleted']` の順で取り出せました。順序が保証されるのは同じ順序指定キーかつ同じリージョンに発行されたメッセージだけで、1つのキーあたりの発行スループットは1MBpsに制限されます。キーを「全体で1つ」にすると全メッセージがこの上限に縛られるため、ユーザーIDや注文IDのように順序が必要な単位でキーを細かく切ります。

### デッドレタートピックへの処理不能メッセージの退避

形式が壊れたメッセージのように何度試しても処理できないものは、放置するとACK期限切れと再配信を繰り返し続けます。デッドレタートピックを設定すると、配信回数が上限に達したメッセージを別トピックへ移せます。上限は5〜100回で、既定は5回です。

```
import time
from google.cloud import pubsub_v1

project_id = "demo-project"
publisher = pubsub_v1.PublisherClient()
subscriber = pubsub_v1.SubscriberClient()
topic = publisher.topic_path(project_id, "jobs")
dead = publisher.topic_path(project_id, "jobs-dead")
sub = subscriber.subscription_path(project_id, "jobs-worker")
dsub = subscriber.subscription_path(project_id, "jobs-dead-sub")
for t in (topic, dead):
    publisher.create_topic(request={"name": t})
subscriber.create_subscription(request={"name": dsub, "topic": dead})
subscriber.create_subscription(
    request={
        "name": sub,
        "topic": topic,
        "dead_letter_policy": {"dead_letter_topic": dead, "max_delivery_attempts": 5},
        "retry_policy": {"minimum_backoff": {"seconds": 1}, "maximum_backoff": {"seconds": 2}},
    }
)
publisher.publish(topic, b"broken").result()
for _ in range(8):
    r = subscriber.pull(request={"subscription": sub, "max_messages": 1}, timeout=5)
    for m in r.received_messages:
        print("worker got attempt", m.delivery_attempt)
        # ACK期限0秒＝否定応答（すぐに再配信させる）
        subscriber.modify_ack_deadline(request={"subscription": sub, "ack_ids": [m.ack_id], "ack_deadline_seconds": 0})
    time.sleep(2.5)
r = subscriber.pull(request={"subscription": dsub, "max_messages": 1}, timeout=5)
print("dead letter:", [m.message.data for m in r.received_messages])
```

```
worker got attempt 1
worker got attempt 2
worker got attempt 3
worker got attempt 4
worker got attempt 5
dead letter: [b'broken']
```

5回目の否定応答の後、メッセージはデッドレタートピック側のサブスクリプションへ移りました。実環境では、Pub/Subのサービスエージェント（`service-プロジェクト番号@gcp-sa-pubsub.iam.gserviceaccount.com`）に、デッドレタートピックへのパブリッシャーロールと、元のサブスクリプションへのサブスクライバーロールを付与しないと転送されません。エミュレータでは権限が検査されないため、ここは本番環境で必ず確認します。公式ドキュメントは上限回数を「おおよそ」と表現しており、厳密に5回で止まる前提の業務ロジックは組まないようにします。

## 料金の計算方法と見落としやすい課金

通常のPub/Subの料金は、スループット・データ転送・ストレージの3要素が基本で、単一メッセージ変換（SMT）を使う場合はその処理料金が加わります。2026年10月時点の単価は次のとおりで、全リージョン共通です。

| 課金項目                            | 単価                   | 無料枠     |
| ------------------------------- | -------------------- | ------- |
| メッセージ配信（発行＋受信）                  | 40ドル／TiB             | 毎月10GiB |
| BigQuery・Cloud Storageサブスクリプション | 50ドル／TiB             | なし      |
| SMT（UDFによる変換）                   | 40ドル／TiB（変換前後の大きいほう） | －       |
| メッセージのストレージ                     | 0.27ドル／GiB・月         | なし      |
| リージョン間・インターネットへの転送              | 別途データ転送料金（ゾーン間は無料）   | なし      |

無料枠は請求先アカウント単位の月10GiBです。最新の単価は[Pub/Subの料金ページ](https://cloud.google.com/pubsub/pricing)で確認してください。

### 1リクエスト最低1KBの計算とバッチの効果

課金対象のデータ量は、`data`・属性・タイムスタンプ（20バイト）・`message_id` の合計です。さらに、1リクエストあたり最低1KBとして計算されるため、小さいメッセージを1件ずつ送ると実データより大きく課金されます。

属性・タイムスタンプ・message\_idを含む課金対象サイズが1件200バイトのメッセージを、月1億件発行する場合で比べます。1件ずつ送ると1億リクエスト×1KB＝1011バイト（約0.091TiB）で、発行側だけで約3.6ドルです。100件ずつまとめると1リクエストが2万バイトになり最低額にかからないため、2×1010バイト（約0.018TiB）で約0.73ドルに下がります（いずれも無料枠を引く前）。ただし、Pythonクライアントの既定は100件・1,000,000バイト・0.01秒のいずれかに達した時点で送信する設定です。発行頻度が低いと0.01秒の間に100件たまらず試算より小さなバッチになるため、まとめて送る効果を得たい場合は `BatchSettings` の `max_latency` を許容できる遅延まで延ばします。

### メッセージ保持とスナップショットのストレージ料金

ストレージ料金（0.27ドル／GiB・月）が発生するのは、次のいずれかの設定をしたときです。

- トピックでメッセージ保持を有効にした（保持期間中の全メッセージが対象）
- サブスクリプションでACK済みメッセージの保持を有効にした
- スナップショットを作成した（作成時点の未ACKバックログがあれば、7日分の保存料に相当する一時料金も発生）
- サブスクリプションの保持期間を1日超に設定し、1日より古いバックログが残っている（トピック側ですでに保持・課金されている期間には、サブスクリプション側の追加保存料は発生しない）

4つ目は設定だけでは課金されず、ワーカーが止まってバックログが1日を超えて溜まったときに初めて発生します。障害で受信が止まった期間の請求が膨らむのはこのためで、後述のバックログ監視が料金の監視も兼ねます。

## Cloud Tasks・Eventarc・Kafkaとの使い分け

非同期処理の候補はPub/Sub以外にもあります。Google Cloudの公式比較では、両者の違いを「暗黙的な呼び出しか、明示的な呼び出しか」で説明しています。Pub/Subは送信側が受信側を知らない設計で、Cloud Tasksは送信側が宛先と実行タイミングを指定します。

| 比較項目           | Pub/Sub                    | Cloud Tasks    |
| -------------- | -------------------------- | -------------- |
| 1メッセージを複数の受信者へ | 可能                         | 不可             |
| 実行時刻の指定        | 不可                         | 可能             |
| 作成時の重複排除       | 不可                         | 可能             |
| 順序付き配信         | 順序指定キーで可能                  | ベストエフォート       |
| 最大サイズ          | 10MB                       | 1MB            |
| 配信レート上限        | リージョンのクォータ内で上限なし           | 500QPS／キュー     |
| リソース数の上限       | サブスクリプション1万／プロジェクト（引き上げ不可） | キュー1,000／リージョン |

判断は単純で、「外部APIを毎秒10件までで叩きたい」「30分後に実行したい」のように宛先と実行を制御したいならCloud Tasks、1つの出来事を複数のシステムへ知らせたいならPub/Subです。Cloud StorageやCloud Audit Logsなど、Google Cloudのサービス側で起きたイベントを宛先のサービスへ振り分ける用途は[Eventarcのイベントルーティング](/tech/details/15748/)が受け持ちます。

Kafkaとの違いはデータの持ち方にあります。Kafkaはパーティションのログを保持し、コンシューマーがオフセットを自分で管理して何度でも読み直します。Pub/Subはメッセージ単位のACKで進捗を管理し、保持も最大31日です。数か月分のイベントを再生して集計し直す運用や、Kafka ConnectやKafka Streamsの資産を使う前提なら[Apache Kafka](/tech/details/7563/)を、クラスタ運用を持たずにイベントを配りたいならPub/Subを選びます。AWSで同じ役割を担うのはSNS（ファンアウト）と[Amazon SQS](/tech/details/17241/)（キュー）の組み合わせで、Pub/Subはこの2つを1つのサービスで兼ねています。

### Pub/Sub Liteの提供終了と移行先

容量を事前に確保して安く使う派生版のPub/Sub Liteは非推奨となり、**2027年1月31日に提供終了**します。2025年4月15日〜7月15日の90日間に利用実績が無いプロジェクトは、2025年7月15日以降すでにアクセスできません。新規利用の受付は2024年9月24日に終了しており、公式の移行先は通常のPub/SubとGoogle Cloud Managed Service for Apache Kafkaの2つです。

## Pub/Subを選ぶべきでない場面

Pub/Subはイベント配信の既定の選択肢ですが、次の条件に当てはまる場合は最初から別のサービスで設計したほうが手戻りが少なくなります。

- **10MBを超えるデータを運びたい**：本体はCloud Storageに置き、Pub/Subにはオブジェクトのパスだけを流します。大きな本文をそのまま流すと、上限エラーに加えて1件ごとの課金も膨らみます。
- **同期的な応答が必要**：画面操作の結果をその場で返す処理は、APIを直接呼ぶ設計にします。Pub/Subは「送ったら終わり」が前提で、受信側の処理結果を送信側へ返す仕組みを持ちません。
- **宛先ごとの流量制御や遅延実行が主目的**：前述のとおりCloud Tasksの領域です。Pub/Subでも受信側のフロー制御で絞れますが、送信側からは制御できません。
- **全メッセージの厳密な順序が必要**：順序はキー単位でしか保証されず、1キーあたり1MBpsが上限です。全体順序を1キーで実現すると、この上限がシステム全体の上限になります。

逆に、受信側を後から増やす可能性があるイベント（注文確定・会員登録・ファイル到着など）は、最初からPub/Subのトピックに載せておくと、新しい処理系をサブスクリプションの追加だけで足せます。

## バックログと配信失敗の監視

運用で最初に見るべき指標は、ACKされずに溜まっているメッセージの量と古さです。公式ドキュメントは、リージョン別の指標を使うよう案内しています。

| 指標                                                  | 見ること              |
| --------------------------------------------------- | ----------------- |
| `subscription/oldest_unacked_message_age_by_region` | 最古の未ACKメッセージの経過時間 |
| `subscription/num_unacked_messages_by_region`       | 未ACKメッセージの件数      |
| `subscription/expired_ack_deadlines_count`          | ACK期限切れの発生率（pull） |
| `subscription/dead_letter_message_count`            | デッドレターへ転送された件数    |

アラートの軸は最古メッセージの経過時間にします。件数はトラフィックの増減で上下するので閾値を決めにくいのに対し、経過時間の増加は、受信側の停止・処理能力不足に加え、一部の処理不能メッセージでも起こります。未ACK件数とログを併せて原因を切り分け、許容遅延や保持期限に基づいて対応します。`by_region` の付かない旧指標（`subscription/num_undelivered_messages` など）は公式が使わないよう注意しているため、古い手順書のダッシュボードは差し替えます。pushではACK期限切れの代わりに `subscription/push_request_count` を成功以外の応答コードで絞って監視します。アラートポリシーの作り方は[Cloud Monitoringの機能と設定](/column/details/2834/)の解説を参照してください。

## よくある質問

### Pub/Subとは何ですか？

Pub/Subは、送信者（パブリッシャー）がトピックへメッセージを送り、受信者（サブスクライバー）がサブスクリプションから受け取る通信パターンです。Google CloudのCloud Pub/Subはこのパターンを提供するフルマネージドサービスで、送信者と受信者が互いを知らずにやり取りできます。

### Pub/Subとメッセージキューの違いは何ですか？

メッセージキューは1件を1つの受信者が処理する方式で、Pub/Subは1件を複数の受信者へ配る方式です。Cloud Pub/Subは1つのサブスクリプションに複数のワーカーを付けるとキューとして、1つのトピックに複数のサブスクリプションを付けるとファンアウトとして動くため、両方を1つのサービスで作れます。

### Cloud Pub/Subは無料で使えますか？

メッセージの発行と受信のスループットは、請求先アカウントごとに毎月10GiBまで無料です。超過分は1TiBあたり40ドルです。ただしBigQuery・Cloud Storageサブスクリプションには無料枠が無く、メッセージ保持やスナップショットのストレージ料金も別にかかります。

### Pub/Subでメッセージの順番は保証されますか？

既定では保証されません。順序指定キーを付けて発行し、サブスクリプションでメッセージの順序指定を有効にすると、同じキーかつ同じリージョンのメッセージは受信した順に配信されます。1キーあたりの発行スループットは1MBpsが上限です。

### 同じメッセージが2回届くのはなぜですか？

Pub/Subの既定の配信保証がat-least-once（少なくとも1回）だからです。ACK期限内に確認応答が届かないと再配信されます。pullサブスクリプションならexactly-once配信を有効にできますが、同一リージョン接続などの条件があるため、受信処理は重複しても結果が変わらない冪等な作りにしておきます。

## 関連記事

- [Eventarcとは？Google Cloudのイベントルーティングの仕組み・Standard/Advancedと料金、EventBridgeとの違いを実装者目線で解説](/tech/details/15748/)
- [Cloud Dataflowとは？Apache Beamの実行基盤とストリーミング処理を実装者目線で解説](/tech/details/15553/)
- [Apache Kafkaとは？仕組み・ユースケースとKafka 4系のKRaft構成を実装視点で解説](/tech/details/7563/)
- [Amazon SQSとは？標準キューとFIFOの違い・可視性タイムアウトとDLQ設計を解説](/tech/details/17241/)
- [Cloud Runとは？GCPのサーバーレスコンテナの仕組み・料金とGKE/Cloud Functionsとの違いを実装者目線で解説](/tech/details/15435/)

---

出典: [Cloud Pub/Subとは？トピックとサブスクリプションの仕組み・料金・Pythonでの送受信を実装者目線で解説](<https://www.issoh.co.jp/tech/details/12385/>)（株式会社一創）
