チャットシステムを作っていて、「新規メッセージが投稿された!」というイベントを、多数のユーザーに知らせるような仕組みが欲しい。 この記事ではこのような仕組みを実装するにあってFirebaseあるいはPusherを使う場合のそれぞれの長所短所、その他留意点について記述する。
基本的にはユーザーへの通知なのだけれど、実は1つのソリューションだけでは解決できない気がする。というのも、ユーザーへの通知と一言に言っても
の2つが欲しい気がする。今回は1をMust、2をWantぐらいで考えている。とはいえ、プッシュ通知の仕組みも使えると嬉しい。
FirebaseはMBaaSと呼ばれるもので、「モバイルアプリを作るためのバックエンドシステムを一通り揃えたサービス」である。サーバレス関数・ファイルストレージ・ドキュメント指向DB等がある。
Firebase Cloud Firestoreはドキュメント指向のリアルタイムDBである。 データが追加・更新・削除すると、そのコレクションおよびドキュメントを購読しているすべてのブラウザにリアルタイムで更新イベントが送信される。
Firebaseには Firestoreと似た性質のFirebase Realtime Databaseというものが存在する。これもFirestoreと同様、ドキュメント指向のリアルタイムDBだが、仕様がところどころFirestoreと異なる。要点だけ書くと
という感じ。Firestoreのほうが後発なため利点が多い。 より低レイテンシを求めるならRealtimeDatabaseになるが、今回はmsレベルのシビアなレイテンシを求めているわけではないのでFirestoreで十分。
「チャンネルについてのイベントは、そのグループのユーザのみが受けられるようにしたい」ということがあると思う。これはFirebase Authenticationでユーザー認証がされていれば出来る。 Firestoreは、ルール定義を作成することが出来、「ログインユーザーのメタ情報がxxx」の場合のみ閲覧可能というようなルールを作っておくと良さそうだ。
あまり知られていないが、FirebaseにはFirebase Cloud Messagingという通知機能を提供するサービスがある。 ServiceWorkerを使ったWebPushにも対応していて、なかなか使いやすい。 不思議なことに、この Firebase Cloud Messagingは、完全に無料で利用できる おそらく利用制限はあるだろうが、料金が発生しないというのは逆に不安になる。 また、利用制限の他にも仕様として1アプリにつき登録できるトピックは2000までやデバイスの最大同時接続2500台などの制約がある。 この制約は実装の工夫でどうにでもなりそうな気はするが、気をつけないといけない所ではある。
(というか、無料のサービスを信頼していいものだろうか...)
ともかく、Firebaseを使えばFirestoreとFCMを使うことで、ブラウザへのリアルタイム送信と、ユーザーのデバイスへのプッシュ通知が実現できそうだ。
Pusherはリアルタイム送信に関するソリューションのみを提供するクラウドサービスだ。
Pusherのサービスは、サーバーからクライアントアプリへの送信を実現するための[Channels]と デバイスへのプッシュ通知を実現するための[Beams]が存在する。 どちらも今回やりたい事に合致していそうだ。
Pusher Channelsは、いわゆるpub/subの仕組みを提供する。
const channel = pusher.subscribe('雑談'); channel.bind('my-event', function(data) { setMessage(data.message) });
こんな感じのコードで、"雑談"トピックを購読しておくと、雑談トピックのイベントを受け取ることが出来る。
イベントのpublishの仕方は
pusher.trigger("雑談", { "message": "こんにちは" });
これだけ。とても簡単。
当然ではあるが、ユーザー認証しないとsubscribe出来ないようにすることも出来る。
その仕様は少し変わっていて、「トピック名の頭にprivate-
をつけるとプライベートチャンネルとして扱われる」ということらしい。
「ログインしたうちの一部のユーザーのみが購読できるチャネル」を実現する機能はなさそう。 トピック名を一部のユーザーしか知れないような仕組みにするか、イベントにはプライベートな情報は含めないようにしたほうが良さそう。
料金体系が異なるので、2つのケースで見積もってみる。 月額費用を算出していく。
今回はpub/sub機能のみの比較。プッシュ通知については考えてない。
pub/sub比が0.25のケース。小規模チーム。
Pusher→無料(Sandboxプランの範囲に収まる。) ただし、同時接続は100に限定される。
Firestore→$48.42 書き込みが38万/日($0.684) 読み取りが155万/日($0.93) 無料枠超過分で計算、ネットワーク帯域・ストレージの利用については軽微なので計算に含めない
pub/sub比が0.005と、ちょっとしたエンタープライズ規模。
Pusher→$699 Growthプランなので、同時接続は15,000まで。
Firestore→$725.22 書き込みが 18万/日($0.324) 読み取りが3975万/日($23.85) 無料枠超過分で計算、ネットワーク帯域・ストレージの利用については軽微なので計算に含めない
あれ、意外といい勝負になった。
いいところ
悪いところ
いいところ
悪いところ
思ったよりいい勝負になっちゃったけど、今回はPusherを使おうと思う。 料金面ではそこまで大きな違いはなさそうだけど 1日の無料枠という見方をすると、Pusherのほうがお得なので、最初はPusherを使って、サービスのpub/sub比の平均が得られたら考えるのが良さそう。