🥝

GCPのメッセージングサービス『Pub/Sub』をやさしく、完全に理解する

2023/03/20に公開

概要

うちの会社のインフラはほぼGCP系なんですが、定期バッチ処理系などなどの開発をしていると結構設計段階から話のなかで出てくるのがPub/Subというサービスです。

既に他の機能開発で使われてたりして、設定の雛形とかもなんとなくわかっちゃいるので、雰囲気で設定をしてみたことなら何度かあったのですが、よくよく考えて見れば

  • そもそもPub/Subってなんで挟んでるんだ?
  • topic?subscription?subscriber?なんだっけ?
  • pull?push?何が?誰を?どこで?誰に?

みたいな感じで漠然とした疑問が諸々ありまして、全然人に説明できないなと思った(そしてPub/Subの開発に何件か関わったので、微妙に人に聞きづらくもなってきた…)ので、思い切って調べてまとめてみることにしました。

この記事のゴールはGCP公式のPub/Sub詳解ページに書かれている基本的なPub/Subの機能を理解できるレベルとなっております!理解をしやすいように例を使ってなるべく平易に書いたつもりなので、同じような漠然とした「なんかよくわからない」を感じている方は、ぜひ読んでいってください!

メッセージングサービスとは

ということで気合いを入れて、公式サイトを上から読んでみましょう!

Pub/Sub は、メッセージを生成するサービスを、それらのメッセージを処理するサービスと切り離す、非同期のスケーラブルなメッセージング サービスです。

……。
……正直、ちょっといきなり何を言っているのかわからない。

ただ、主語と述語だけ引っ張ってみれば、「Pub/Subとは、メッセージングサービスである」ということですよね。
で、そもそも私はこの一文の時点で「メッセージングサービスってなんだっけ?」と思ったので、まずはメッセージングサービスについて、概要・メリットを簡単に解説していきます。

概要

メッセージングサービスの概念自体はそんなに難しいものではなく、その名の通り複数のアプリケーション間でメッセージをやりとりすることです。

メッセージングサービスには複数のパターンというか、型みたいなものがあるみたいなのですが、まずどういったものか大枠を超ざっくりおさえようとした時には、郵便局を思い浮かべるのが早いです。

メッセージングサービスとは

今では携帯メールすらあまり使わない時代になっちゃってるので、ちょっと古風な例ではあるのですが、人に手紙を送ることを考えてみてください。

私たちは通常手紙を届ける場合、直接自分が相手の家へ赴いて届けることはありませんよね?

郵便局が指定するフォーマットに沿って住所や宛名を記載し、郵便ポストという受け口に投函するだけです。
すると定期的に郵便局員さんが手紙を回収し、仕分けし、指定した宛先に手紙を届けてくれます。

私たちは直接その人の元へ足を運ぶことなく、お気持ちを届けられるということです。

メッセージングサービスとは、まさにこのようなサービスです。

システムAがシステムBへ情報を連携する際に、直接システムBのシステムに何かを処理しにいくのではなく、メッセージングサービスに情報を渡すと、メッセージングサービスはシステムBによしなに情報を届けてくれます。

メリット

と、ここで素朴な疑問が1つ浮かびます。

「いやいや、相手の家さえ知ってれば、直接歩いて手紙を届けに行けば良いじゃん」
「いやいや、システムAが直接システムBのエンドポイントとか叩けば良いじゃん」

とまあ、こんな感じでございますよね!

で、結論からいうとぶっちゃけその通りで、メッセージングサービスって、別に無理して使わなくても良いです(笑) うちの会社のシステムやっててもなんか当たり前のように「Pub/Subで」みたいな会話が飛び交っているから、ついつい普通に使ってますが、いいんです使わなくても

ではなぜ使うのかというと、直接やりとりしていたら何か不都合な時が出てくるからです。

ふたたび郵便局に例えてみましょう、こんな場合を考えてみてください。

  • あなたは直接相手の家へ手紙を渡しにいきます。つまりその間、移動しなければならないので、なにも出来ません!(スマホ触るくらいです)
  • 直接手紙を届けるのであれば、手紙の形はなんでも構いません。別に住所を書かなくてもA4ルーズリーフ使っても良いし、もはや紙に書かなくても良いんです。相手に届けば良いので。数人なら良いですが、もしあなたが人気者だったら、大勢とやりとりしていくに従って混乱していきそうです。「あれ…Zちゃんとはどんな感じのやりとりしてたっけ…」
  • もしあなたが手紙を送りたい人はすごく人気者だったとしたら、あなたはその人の家の玄関で、同じようにその人に手紙を渡しにきた人の列に入って、人気者が受け取ってくれるのを待たなきゃいけません。
  • ピンポン押してみるけど、もしも、その人が今は家にいなかったらどうなりますか? とりあえず、待ちぼうけですよね。

郵便局を利用することによって、これらの問題は(たぶん、ほぼ)すべて解決するのは、想像に難くないと思います。

これをそれっぽくシステムにたとえた時には、こんな表現になると思います。

  • メッセージングサービスは、システム間の連携を非同期に行います
  • メッセージングサービスを利用することで、決まったフォーマットの連携方法でシステム間が通信するようになるので、連携システム間の依存関係を減らすことができます
  • メッセージングサービスが負荷を分散してくれたり、簡単に複数のシステムを統合したりできるため、分散システムやロードバランシングといった役割をします
  • システム間はお互いの状況を知る必要がないため、片方に障害が起きても片方は正常に稼働し続けます。つまり、疎結合を実現します

Pub/Subとは

基本的なメッセージングサービスについては、理解できました!
ということで、改めて公式サイトの1番最初の文に戻ります。

Pub/Sub は、メッセージを生成するサービスを、それらのメッセージを処理するサービスと切り離す、非同期のスケーラブルなメッセージング サービスです。

…どうでしょう? スケーラブルというところ以外は、さっきよりもなんとなくわかってきた感じがしますよね🙂

一応最初にお伝えしておくと、Pub/Subはこれまでに説明させていただいたメッセージングサービスの形と、基本的な考え方は一緒ですがちょっと仕組みなどが違います。

もうちょっと複雑で、↑の文章の通りスケールするような作りになっています。このあたりはすこし理解がしにくく、混乱を招くポイントだったりするのかなと思っております。「メッセージングサービスと、ちょっと違う🥺」みたいな感じで!

概要

ということで、ここからは物理の郵便局ではなく、Pub/Subサービスを使って、「指定した相手のメールアドレスにメッセージを配信するサービス」について考えてみましょう。

  • あなたはシステムの画面上で、相手に「こんにちは、ピヨちゃん!」という文章を書いて、送信ボタンを押します。
  • メッセージを受理するシステムAはあなたから相手へのメッセージを作成し、Pub/Subに情報を送ります。
  • Pub/Subは受理システムAのメッセージを配信システムBに送ります。
  • 配信システムBがメッセージを元に実際の相手のメールアドレスへ送信します。

以下のような感じです!

sequenceDiagram
    participant あなた
    participant SystemA[Receiver]
    participant Pub/Sub
    participant SystemB[Sender]
    participant 相手(ピヨちゃん)

    あなた->>SystemA: 「こんにちは、ピヨちゃん!」というメールを送る
    SystemA->>Pub/Sub: "あなたからピヨちゃんに「こんにちは、ピヨちゃん!」を送る"というメッセージを送る
    Pub/Sub->>SystemB: "あなたからピヨちゃんに「こんにちは、ピヨちゃん!」を送る"というメッセージを受け付ける
    SystemB->>相手(ピヨちゃん): 送信元をあなたにして、相手(ピヨちゃん)に「こんにちは、ピヨちゃん!」とメッセージ送る

システム構成図

Pub/Subはメッセージングサービスなので、先ほどまでのメッセージングサービス概要をおさえていれば、なんとなく意味がわかると思います。

各用語と役割について

次にPub/Subの用語についてお伝えします!
そこそこさまざまな用語があり、これがまた私にとっては結構な混乱の元凶でした。

もちろん公式サイトでも詳解がされていますが、何がどれに当たるのかをまずはみていきます。

Pub/Subの主な登場人物は、とりあえず5名です。以下の通りの方々です!

Pub/Subの用語と解説

Message

送る情報それ自体を指します。

Publisher

SystemA(Receiver)を指します。情報を発行する(送る)側のアプリケーションです。

Subscriber

SystemB(Sender)を指します。情報を購読する(受け取る)側のアプリケーションです。

Topic

SystemA(Receiver)/Publisherが情報を渡す入れ物を指します。

Subscription

SystemB(Sender)/Subscriberへ情報を送る入れ物を指します。

pull/push型の違い

もう一つ、Pub/Subの設計をしようとすると出てくるのが、「pull型にする?push型にする?」系の話です。

pull/pushという言葉こそ馴染みはありますが、「何を?誰に?どこで?」みたいなのが把握できていない限り、理解するのが難しいです。

ですが、前述したPub/Subの登場人物たちを知っていれば、こちらも問題なく理解できます!

pull型とpush型の違い

pull型

情報を受け取るシステムであるSubscriberが、subscriptionに定期的にメッセージを取得しにいく方式です。

push型

subscruptionが、情報を受け取るシステムであるSubscriberに適宜メッセージを送る方式です。

大事なことは、pull/pushの違いは、Subscriber(情報を受け取る側のシステム)とsubscription(情報が格納されている入れ物)との情報の通信方法の違いを指している、ということです。これらの設定は入れ物であるsubscriptionで設定します。

pull型はsubscriberが定期的にメッセージをリクエストしにいくということなので、定期実行系の処理でよく利用されます。push型はリアルタイム性が必要な場合に便利そうですね!

たとえば先ほど例に出したメッセージ配信サービスでたとえるとすると…

pull型にした場合は、数分おきにSystemA(Sender)がsubscriptionから配信情報を取り出して、処理します。一方push型にした場合は、SystemA(Sender)は順次受け取った情報をもとに処理をします。

Pub/Subの特徴

Pub/Subについて紹介する最初に「最初に説明したメッセージングサービスとは違う」ということをお話しました。
それでは、ただのメッセージングサービス−−郵便局と、具体的にどこが違うのかについて、2つの特徴についてお伝えしていきたいと思います。

1) より疎結合

1つ目は、PublisherはSubscriberに関する情報を一切知る必要がないということです。

郵便局でいえば、あなたは手紙に対して宛先を書いてポストに入れなければいけません。そうしないと、郵便局員は仕分けができないんです。

Topicは郵便ポストに似た概念ですが、Topicにはメッセージだけが格納されます。

つまり、SystemA(Receiver)がTopicにに送る情報は以下のようになっています!

× To SystemA(Sender):あなたからピヨちゃんに「こんにちは、ピヨちゃん!」を送る」という情報を格納
◎ あなたからピヨちゃんに「こんにちは、ピヨちゃん!」を送る」という情報を格納

TopicはSubscriptionの設定にしたがって、紐づけられているSubscriptionに情報をコピーして格納します。あとは、そのSubscriptionがSubscriberと情報をやりとりしてくれるわけですね!

高い拡張性

しかし「疎結合なのはわかったが、で、じゃあこれは一体何が良いの?」というと、2つ目の特徴のお話になります。
2つ目は、1つのTopicに対して複数のSubscriptionを設定できるということです。

メール配信システムにおいて、以下2つの要件が追加になったとします。

  • メール配信情報のログを残したい。
  • メール配信数や内容によって従量課金制にしたい。

そして、このログ情報や配信内容は、先に設定したSystemA(Receiver)が送ったメッセージ情報をもとにごにょごにょ処理できるようになります。

Pub/Subの拡張性

Pub/Subはこんなパターンに備えて、TopicとSubscriptionを1対多で設定できるという特徴があります。なぜこれが実現できるかといえば、1つ目の特徴であるPublisherがTopicしか知る必要がないためですね。

つまりこんなことができるわけですね!

こうやってみるとたしかに、スケールしそうな感じがしてきましたね〜。

まとめ

以上これまでメッセージングサービスの大枠とPub/Subというサービスについて、少し丁寧にみてきました。
再度、しつこいですが公式サイトを読んでみます。

Pub/Sub は、メッセージを生成するサービスを、それらのメッセージを処理するサービスと切り離す、非同期のスケーラブルなメッセージング サービスです。
Pub/Sub を使用すると、サービスが 100 ミリ秒程度のレイテンシで非同期に通信できます。

ここまで読んだ上で、メッセージを生成するサービスを処理するサービスと切り離す非同期スケーラブルといったキーワードのニュアンスというか言いたいことというか、そのあたりについて、「なるほど、なんだか完全に理解した気がする!」と思ってもらえたら嬉しいです!

Pub/Subは特に有名なサービスだったりするので、ググればいろんなところで使い方が出てきたりします。

けれど、なんでもそうですが「どういう仕組みで何を解決するのか?」そのシステムの正体の基本を理解していないと、思わぬ落とし穴にはまったときに解決策がなかなか見いだせなかったり、実装の話をする時に人に説明できなかったり(最悪の場合なんか話の認識が合わなくなったり)しますよね…

ちゃんとこういうことは1つ1つ理解していきたいなと、調べながら改めて思いました!

ということで頑張ってみましたが、まだなにやらズレてたらぜひ教えてください。

Discussion