機能
リアルタイムの難しいところは、すでに動いている
リアルタイム機能とは、わずかなプロダクトコードの下に横たわる大量の配信機構のことです。誰が subscribe しているか、誰に権限があるか、誰がまだそこにいるか。PushCaster はその後半部分です。
Channel
4 種類、そして接頭辞が契約そのもの
チャンネルの名前がその振る舞いを決めます。接頭辞はライブラリに、サーバーへ認可を求めるべきか、メンバー一覧を期待すべきか、暗号化すべきかを伝えます。
| 接頭辞 | 誰が subscribe できるか | 何のためのものか | 認可 |
|---|---|---|---|
| public | app key を持っている人なら誰でも。 | ビルドの状態、ライブスコア、公開フィード。 | 不要 |
| private- | あなたのサーバーがサブスクライバーごとに判断します。 | アカウントやリソースに範囲を限ったものすべて。 | 署名 |
| presence- | 認可が必要で、メンバー一覧も伴います。 | メンバーシップそのものが機能になるルームやセッション。 | 署名 |
| private-encrypted- | 認可が必要。ペイロードはあなたのクライアントが暗号化します。 | 当社にも読ませたくないペイロード。 | 署名 |
cache- チャンネルはライブのイベントを配信しますが、保存された状態を再生はしません。参照: 既知の相違点.
認可
権限はあなたのサーバーに残る
private と presence のサブスクリプションを許可するのは当社ではありません。あなたのアプリケーションが許可し、その答えをあなたの app シークレットで署名します。当社は署名を検証するだけで、それ以上のことはしません。
- エンドポイントは一つPOST /pusher/auth はリクエストとレスポンスの形をそのまま保ちます。
- ルールはあなたのものこのソケットがこのチャンネルに参加してよいかは、あなたにしか答えられない問いです。
- presence における身元同じ呼び出しがメンバー id と、他のメンバーに見せるべき情報を返します。
import Pusher from 'pusher'const pusher = new Pusher({ appId: process.env.PUSHCASTER_APP_ID, key: process.env.PUSHCASTER_KEY, secret: process.env.PUSHCASTER_SECRET, host: 'api-eu1.pushcaster.io', useTLS: true,})// Called by the client library whenever it subscribes to a// private-, presence- or private-encrypted- channel.app.post('/pusher/auth', (req, res) => { const { socket_id, channel_name } = req.body const user = req.session.user if (!user || !mayJoin(user, channel_name)) { return res.sendStatus(403) } res.send( pusher.authorizeChannel(socket_id, channel_name, { user_id: String(user.id), user_info: { name: user.name }, }), )})Webhook
ソケット層が見ているものを、バックエンドが聞く
在室状況とメンバーシップは接続のところでしか見えません。Webhook がそれを署名付きで返すので、最初の見る人が来たら処理を始め、最後の一人が去ったら止められます。
| Event | 発火する条件 |
|---|---|
| channel_occupied | 空のチャンネルに最初のサブスクライバーが参加した。 |
| channel_vacated | 最後のサブスクライバーが離脱した。 |
| member_added | 誰かが presence チャンネルに参加した。 |
| member_removed | 誰かが presence チャンネルから離脱した。 |
| client_event | クライアントがチャンネルへ直接イベントを送った。 |
| cache_miss | cache チャンネルが、持っていない状態を求められた。 |
app.post('/pushcaster/webhooks', (req, res) => { const hook = pusher.webhook({ headers: req.headers, rawBody: req.rawBody }) // The signature is computed with your app secret, so an // unsigned or mismatched delivery never reaches your logic. if (!hook.isValid()) return res.sendStatus(401) for (const event of hook.getEvents()) { if (event.name === 'channel_occupied') startFeed(event.channel) if (event.name === 'channel_vacated') stopFeed(event.channel) } res.sendStatus(200)})ライブラリ
PushCaster の SDK はありません。意図的に。
PushCaster は回線上で Pusher Channels プロトコルを話すので、公式ライブラリは手を加えずにそのまま動きます。追加する当社のパッケージはなく、当社がリリースしたときに壊れる当社のものもありません。
- pusher-js
- Laravel Echo
- pusher/pusher-php-server
- pusher-http-node
- Python
- Go
- Ruby
- Java
- Android
- iOS
- Flutter
- Unity
インストールコマンドの全文: npm i pusher-js.
インフラ
2 つの層と、あなたが選ぶクラスター
配信は課金や設定とは別の層で動くので、control plane の障害はダッシュボードを劣化させても配信は止めません。
現在稼働中
- eu1西ヨーロッパ
- eu2中央ヨーロッパ
クラスターはメッセージ配信については高可用ですが、presence についてはそうではありません。presence の保管庫が失われると presence と在室数は劣化し、その間も public と private のチャンネルは配信を続けます。後で気づくより、ここで読んでおくほうがましです。
publish がたどる道を見る