Slide 1

Slide 1 text

FCMを使った 用途に合わせたPush通知設計 pixiv Inc. Koji OKADA 2019.2.7

Slide 2

Slide 2 text

自己紹介 ● ピクシブ株式会社 新技術プロジェクト エンジニア ● 岡田 康治 / Koji OKADA ● Twitter: @SuperSatoSan ● Android / バックエンド / フロントエンド / Unity ● 今日はAndroidエンジニアとして来ました 2

Slide 3

Slide 3 text

Push通知は様々な用途に使える ● 個別のユーザーに対するイベントが発生したことを通知する ● 多数のユーザーに対して新機能やキャンペーンがあることを通知する 3

Slide 4

Slide 4 text

考えなきゃいけない要件はたくさん ● どのくらいの頻度で送る? ● 送信対象ユーザーの規模は? ● どのぐらいの遅延が許される? ● 送信するメッセージの内容は? ● いつリリースする? ● 開発体制は? ● etc 4

Slide 5

Slide 5 text

Firebase Cloud Messaging(FCM) ● 各プラットフォームへのPush通知送信を統一出来る メッセージングソリューション ● ピクシブでも様々なプロダクトで活用されている ● 本セッションはFCMを使うことを前提に話をする 5

Slide 6

Slide 6 text

FCMでも全てを解決できる方法はない ● 100万ユーザーに同じ内容を一つずつ送ったら…… ● ユーザー固有の内容を全ユーザーにまとめて送ったら…… ● 用途に適した仕組み = 設計を考える必要がある 6

Slide 7

Slide 7 text

今日の内容 ● 設計する際に拠り所となる考え方 ● pixivアプリを例に何を考えて設計を決めていったか ● 明日使えるかも知れない技術的な知見 7

Slide 8

Slide 8 text

設計を考える拠り所 ● 制約を満たすように設計を考えると選択肢はほとんど無くなる ● FCMで出来ることは制約 ● 実現する機能の要件も制約 8

Slide 9

Slide 9 text

FCMに出来ること 9 サービスサーバー アプリ FCMサーバー 2. 通知の送信をリクエストする 3. 通知データを処理する 1. 通知対象をサーバーサイドで把握する ※: FCMサーバーとの区別のためサービスのためのAPIサーバーやバッチサーバーをまとめてサービスサーバーと呼ぶ

Slide 10

Slide 10 text

通知対象をサーバーサイドで把握する ● Push通知を送信する端末をサービスサーバーが認識する手段の選択肢 A. デバイストークンをサービスサーバーへ送信する B. トピックをSubscribeする ○ 少量の送信速度で劣る代わりに大量の通知の送信に向いている C. サービスサーバーでデバイスグループを作成する D. サービスサーバーでトピックにサブスクライブさせる ○ 対象端末のデバイストークンが必要 10

Slide 11

Slide 11 text

通知の送信をリクエストする ● サービスサーバーからFCMサーバーへPush通知を送る手段の選択肢 A. HTTP v1 API B. レガシーHTTPサーバー ○ 現在はHTTP v1 APIの利用が推奨されている C. レガシーXMPPサーバー ○ HTTPと比べて非同期で複数の通知を連投出来るのがメリット D. FirebaseAdminSDK ○ Node, Java, Python, Goで使える ● 表示するメッセージ以外にアプリ側で処理するためのパラメータを送れる 11

Slide 12

Slide 12 text

FCMから通知されたデータを表示する ● FCMサーバーから届いたPush通知をユーザーに表示する手段の選択肢 A. 通知に設定されているタイトルや本文をそのまま表示 B. コールバックで独自にメッセージを組み立てることもできる ○ 通知に含めたパラメータを利用 ○ 通知ドット(バッジ)やアプリ固有の処理もこれでやる 12

Slide 13

Slide 13 text

設計の実例 13

Slide 14

Slide 14 text

● 創作に特化したライブ配信サービス ● 最大4人同時に配信可能 ● コミュニケーションしながら 創作活動を楽しめる ● pixivアプリはpixiv Sketch LIVEの 視聴機能を提供している 題材: pixiv Sketch LIVE 14

Slide 15

Slide 15 text

例にする通知機能 ● フォローユーザーがpixivSketch LIVEで配信を開始した通知 ● フォローしているユーザーが配信を開始したときにPush通知がくる ● 以降のスライドではライブ開始通知と呼ぶ 15 配信開始! ○○さんが ライブ中!

Slide 16

Slide 16 text

既存のPush通知基盤 ● 基盤がこの開発以前から存在していた ● 提供する通知機能 ○ 誰かにフォローされた ○ 自分の作品をすき!された ○ etc ● 一つのイベントで 一人への通知しか生じない ● まずはこの設計を紹介 16 サービスサーバー アプリ FCMサーバー ?

Slide 17

Slide 17 text

通知対象をサーバーサイドで把握する A. デバイストークンをサービスサーバーへ送信する B. トピックをサブスクライブする ○ ユーザー毎に自分専用のトピックをサブスクライブしている C. サービスサーバーでデバイスグループを作成する D. サービスサーバーでトピックにサブスクライブさせる 17

Slide 18

Slide 18 text

通知対象をサーバーサイドで把握する ● DBでデバイストークンを管理したくない ● Push通知の送信から大抵は数秒、遅くとも数分以内に受信できている ● 即時に通知を受信する必要のある状況では選択しにくい方法 ○ pixivアプリではそこまでクリティカルではない 18

Slide 19

Slide 19 text

通知の送信をリクエストする A. HTTP v1 API B. レガシーHTTPサーバー C. レガシーXMPPサーバー ○ 各種イベント等が発生したら通知キューに通知をためる ○ バッチサーバーで送信バッチを回して送信している ○ 深夜帯に送らない等のフィルタリングはサービスサーバーの責務 D. FirebaseAdminSDK 19

Slide 20

Slide 20 text

通知の送信をリクエストする ● pixivのサービスサーバーはPHPで実装されているのでSDKは選べない ● HTTP v1 API以前に実装されたのでレガシーHTTPかXMPPになる ● ユーザー起因のイベントで通知が発生する ○ 単位時間あたりの送信能力を高くしたい 20

Slide 21

Slide 21 text

通知されたデータを処理する A. 通知に設定されているタイトルや本文をそのまま表示 B. コールバックで独自にメッセージを組み立てる 21

Slide 22

Slide 22 text

通知されたデータを処理する ● Android・iOS共にPush通知の基本的な使い方 ● アプリのリリース無しで文言の改善が出来る 22

Slide 23

Slide 23 text

● アプリ ○ トピックのサブスクライブ ○ Push通知はそのまま表示 ○ 通知を受けたときの処理 アプリ・サービスサーバーの責務分担 23 ● サービスサーバー ○ 通知のキューイング ○ 通知メッセージの生成 ○ 通知のフィルタリング ● アプリは通知の種類ごとに必要な特別な処理を実装するだけ ● その分責務がサービスサーバーに寄せている ● 大抵はサービスサーバーだけでやれば良いので考えることが少ない

Slide 24

Slide 24 text

ライブ開始通知の設計 24 配信開始! ○○さんが ライブ中!

Slide 25

Slide 25 text

設計のために制約を整理する 25 ● 設計を絞り込むために制約を考える ○ どのくらいの頻度で送る? ○ 送信対象ユーザーの規模は? ○ どのぐらいの遅延が許される? ○ 送信するメッセージの内容は? ○ いつリリースする? ○ 開発体制は?

Slide 26

Slide 26 text

どのくらいの頻度で送る? ● ユーザーの配信開始タイミングは制御できない ● 最も増える夜の時間帯に毎分数人が開始することを想定 ● イベントが発生する頻度はこれまでと比べて大きな差はない 26 制約 ● 特になし

Slide 27

Slide 27 text

送信対象ユーザーの規模は? ● 最大クラスのユーザーになると数十万人に送信することになる ● これまでは1イベントあたり1件だったが、それが膨大な量に増える 27 制約 ● 一回のイベントあたりの通知件数が大幅に増加

Slide 28

Slide 28 text

どのぐらいの遅延が許される? ● 通知の数が膨大になることで遅延が無視できなくなってくる ● 最大クラスのユーザーに配信開始から15分程度で送信完了したい ● 10万フォロワー規模の配信を10分で捌くのをパフォーマンス目標に設定 28 制約 ● 許容出来る通知の遅延に限度がある

Slide 29

Slide 29 text

送信するメッセージの内容は? ● 全てのフォロワーに対して共通のメッセージが送信される ● これまでと同様の仕組みで問題なし ● 未対応バージョンのアプリにPush通知を送信すると タップしても何も反応しない通知が出る 29 制約 ● 未対応バージョンに影響しないように送信する

Slide 30

Slide 30 text

いつリリースする? ● 長くても3ヶ月程度でリリースしてほしい 30 制約 ● 長くて3ヶ月程度でできる仕様に留めないといけない

Slide 31

Slide 31 text

開発体制は? ● 専任する開発者は自分ひとり ● すでに個別ユーザーにpush通知を送信する基盤は存在する ● アプリ開発メンバーはpixiv Sketch LIVE自体の視聴機能に集中 ● アプリ側の対応も必要な場合は自分で行う必要あり 31 制約 ● 一人で開発完了できる仕様に留めないといけない

Slide 32

Slide 32 text

設計への影響のまとめ ● 一回のイベントあたりの通知件数が大幅に増加 ○ 送信の遅延が無視できなくなる ● 非対応バージョンのユーザーにPush通知を飛ばさないようにする ● アプリ・サーバーサイド含めて長くて一人で3ヶ月程度で完了できる 32

Slide 33

Slide 33 text

1. 通知の遅延が無視できない A. 送信バッチを並列化する ○ 現状の発展形で実現可能 B. フォロワー向けのトピックを作る ○ 新しいトピックをSubscribeする変更がアプリに必要 ○ 通知を出すかどうかの判断の責務がアプリ側に移る 33

Slide 34

Slide 34 text

送信バッチを並列化する ● 1デバイスずつ送信する設計は変えずに並列化 ● XMPPの送信能力的には並列化だけでも目標を達成できる 34 送信バッチ 送信バッチ 送信バッチ 送信バッチ FCMサーバー アプリ アプリ アプリ

Slide 35

Slide 35 text

フォロワー向けのトピックを作る ● 新しいトピックをSubscribeする変更がアプリに必要 ● 通知を出すかどうかの判断の責務がアプリ側に移る 35 FCMサーバー フォロワー向け トピック アプリ アプリ アプリ サービスサーバー 送信バッチ

Slide 36

Slide 36 text

並列化を選択 ● 理想は「フォロワー向けのトピックを作る」方式 ● ただし一部の通知だけが別のルールで設計されていると混乱する ● やるなら全部改修すべき ● 一人でサービスサーバーに加えて Android、iOSまで作業するのは時間がかかる 36

Slide 37

Slide 37 text

2. 非対応バージョンに通知を送らない 1. 最近使ったアプリのバージョンを DBに記録してフィルタリング 2. ログベースでBigQueryで送信する対象をフィルタリング 37

Slide 38

Slide 38 text

サービスサーバー アプリのバージョンをDBに記録する 38 FCMサーバー APIサーバー アプリ 送信バッチ サーバー DB フィルタリング時に バージョンも条件にする 使ってるアプリバージョンを 報告する

Slide 39

Slide 39 text

BigQueryでフィルタリング 39 BigQuery pixivのログ基盤 送信バッチ FCMサーバー 毎日一回 特定バージョン以上を使ってるユー ザーのリストを更新 送信前に問い合わせてフィルタリング

Slide 40

Slide 40 text

BigQueryでフィルタリング ● 費用は¥1000/月ぐらいで済んでいる ● 特定バージョン以上を使ってるユーザーのリストの更新が一番コストが高い ○ 前日までのリストと当日分のログを合成してコストダウン ○ ログから不要なデータを落としたテーブルにしている ● バッチ実行時の問い合わせは最小限のデータに対する SELECTなので安い 40

Slide 41

Slide 41 text

BigQueryフィルタリングを選択 ● 最近使ったバージョンの記録は作業時間がかさむと判断した ○ DBにテーブルを追加するためのスキーマレビュー ○ アプリを改修も必要 ○ すでにログに必要な情報があるのでメリットも薄い ● BigQuery方式はそのあたりの悩みどころを全部飛ばして実装出来るが魅力 ○ 金額的にも十分安い 41

Slide 42

Slide 42 text

最終的な責務分割 ● アプリ ○ トピックのサブスクライブ ○ Push通知はそのまま表示 ○ 通知を受けたときの処理 42 ● サービスサーバー ○ 通知のキューイング ○ 通知メッセージの生成 ○ 通知のフィルタリング 変更なし

Slide 43

Slide 43 text

次に改善するとしたら ● フォロワー向けの通知は大量の通知が発生して遅延する ● クライアントでフォロワー用トピックをサブスクライブするのが理想 ● 一部だけ別のルールの設計にならないように通知機能全体を改修したい 43 ● アプリ ○ トピックのサブスクライブ ○ Push通知はそのまま表示 ○ 通知を受けたときの処理 ○ 通知のフィルタリング ● サービスサーバー ○ 通知のキューイング ○ 通知メッセージの生成

Slide 44

Slide 44 text

まとめ ● あらゆる用途に最適な設計は存在しない ● 制約を満たすように設計を考えると自然と選択肢が絞られる ● 制約は開発する機能の仕様だけではない ● 開発体制の都合も含めて制約になる 44