Slide 1

Slide 1 text

Realtime Messaging with Firebase PHP Conference Tokyo 2017 @sota1235

Slide 2

Slide 2 text

悲報

Slide 3

Slide 3 text

Cloud Firestore launched! https://firebase.googleblog.com/2017/10/introducing-cloud-firestore.html

Slide 4

Slide 4 text

要約 Realtime Databaseの 次世代版が出たよ

Slide 5

Slide 5 text

今⽇日 10/8 ブログポスト 10/3

Slide 6

Slide 6 text

But Realtime Database is not dead https://firebase.googleblog.com/2017/10/introducing-cloud-firestore.html

Slide 7

Slide 7 text

But Realtime Database is not dead https://firebase.googleblog.com/2017/10/introducing-cloud-firestore.html

Slide 8

Slide 8 text

今⽇日の⽅方向性 • Cloud FirestoreとRealtime Databaseの違いを 最後に話します • Cloud Firestoreを使うとしても役に⽴立つ知⾒見見 に寄せました

Slide 9

Slide 9 text

Realtime Messaging with Firebase PHP Conference Tokyo 2017 @sota1235

Slide 10

Slide 10 text

About me • Sota Sugiura • @sota1235 • Mercari, Inc.

Slide 11

Slide 11 text

突然ですが…

Slide 12

Slide 12 text

こんな画⾯面 ⾒見見たことある⼈人

Slide 13

Slide 13 text

メルカリチャンネル • 今年年7⽉月にローンチした Liveコマース機能 • メルカリの⼀一機能 • 動画で売れる/買える https://www.mercari.com/jp/mercari-channel/

Slide 14

Slide 14 text

気になる⼈人はggってください 今⽇日は宣伝に来たわけではないので…

Slide 15

Slide 15 text

4⽉月下旬のこと P 「Liveコマース出したいんだよね」 ⋵

Slide 16

Slide 16 text

4⽉月下旬のこと P 「Liveコマース出したいんだよね」 ⋵ 「なるほど」

Slide 17

Slide 17 text

4⽉月下旬のこと P 「Liveコマース出したいんだよね」 ⋵ 「なるほど」 P 「7⽉月にリリースしたいんだよね」

Slide 18

Slide 18 text

4⽉月下旬のこと P 「Liveコマース出したいんだよね」 ⋵ 「なるほど」 P 「7⽉月にリリースしたいんだよね」 ⋵ 「なるほど???」

Slide 19

Slide 19 text

サービスとして求められていたこと w ڝ߹ΑΓૣ͘ग़͢ w ཁ݅ఆٛɺ։ൃɺ2"ɺϦϦʔε ·ͰΛϲ݄Ͱ࣮ݱ͢Δ ① 7⽉月上旬のリリース w ੈք؍Λ࣮ݱ͢ΔΪϦΪϦΛ w ·ͣಈ͘΋ͷΛੈʹग़͢ ② 最⼩小機能で動くものを

Slide 20

Slide 20 text

サービスとして求められていたこと w ڝ߹ΑΓૣ͘ग़͢ w ཁ݅ఆٛɺ։ൃɺ2"ɺϦϦʔε ·ͰΛϲ݄Ͱ࣮ݱ͢Δ ① 7⽉月上旬のリリース w ੈք؍Λ࣮ݱ͢ΔΪϦΪϦΛ w ·ͣಈ͘΋ͷΛੈʹग़͢ ② 最⼩小機能で動くものを ʢສμ΢ϯϩʔυɺҰ೔ ສग़඼͞ΕΔτϥϑΟοΫ ͷΞϓϦͰ΋໰୊ͳ͘ʣ

Slide 21

Slide 21 text

技術的に求められていたこと ಈը഑৴ࢹௌػೳ αʔϏεͷ৺ଁͱ΋ ݴ͑Δػೳ

Slide 22

Slide 22 text

技術的に求められていたこと ಈը഑৴ࢹௌػೳ ϦΞϧλΠϜ௨৴ ϥΠϒײΛ͓٬͞·ʹ ͓ಧ͚͢Δ

Slide 23

Slide 23 text

技術的に求められていたこと ಈը഑৴ࢹௌػೳ ϦΞϧλΠϜ௨৴ ଱ߴෛՙ αʔϏεͷεέʔϧͱ Մ༻ੑΛݟਾ͑Δ

Slide 24

Slide 24 text

ロードマップ ཁ݅ఆٛ ݟੵ΋ΓείʔϓܾΊ 5⽉月 5⽉月中旬 7⽉月 ։ൃ ಈըपΓϦΞϧλΠϜ௨৴ 2" ϦϦʔε

Slide 25

Slide 25 text

ロードマップ ཁ݅ఆٛ ݟੵ΋ΓείʔϓܾΊ 5⽉月 5⽉月中旬 7⽉月 ։ൃ ಈըपΓ1VTI௨৴ 2" ϦϦʔε スケジュールがかなりタイト

Slide 26

Slide 26 text

締切 vs ⼯工数 • チームにはAPIエンジニア2⼈人、iOS/Android1⼈人 ずつ • 動画基盤やサーバPush基盤のノウハウは0 • 1から全部完成させようと思ったらとても2ヶ⽉月で は厳しい • しかしこのサービスは早く出すことに何よりの意 味があった

Slide 27

Slide 27 text

どう実現するか

Slide 28

Slide 28 text

なるべく作らない • 使えるもの(クラウドサービス)を使い倒す • Microserviceとして作らない • 既に持っている資産を再利利⽤用する • スコープを削れるだけ削る • サービスコンセプトを追求する

Slide 29

Slide 29 text

利利⽤用したクラウドサービス ಈը഑৴ࢹௌػೳ ϦΞϧλΠϜ௨৴ ଱ߴෛՙ ċ 㡿ކ

Slide 30

Slide 30 text

利利⽤用したクラウドサービス ಈը഑৴ࢹௌػೳ ϦΞϧλΠϜ௨৴ ଱ߴෛՙ ċ 㡿ކ 今⽇日のお話

Slide 31

Slide 31 text

About Firebase Realtime Database

Slide 32

Slide 32 text

Firebaseとは • Googleの提供するBaaS • モバイルに⾮非常に特化している https://firebase.google.com/?hl=ja

Slide 33

Slide 33 text

Firebase Realtime Database • Firebaseの機能の1つ • JSON形式のデータの永続化 • ClientからリアルタイムにデータをSubscribeできる • ⼤大量量のClientにも対応 • 10万接続 / 秒間1000回の書き込み

Slide 34

Slide 34 text

Subscribe Data { "messages": { "1": { "text": "hello, firebsae", "user": "sota1235" } } }

Slide 35

Slide 35 text

Subscribe Data Subscribe /messages { "messages": { "1": { "text": "hello, firebsae", "user": "sota1235" } } }

Slide 36

Slide 36 text

Subscribe Data { "messages": { "1": { "text": "hello, firebase", "user": "sota1235" }, "2": { "text": "hello, phpcon", "user": "phper" } } } Subscribe /messages New data

Slide 37

Slide 37 text

Subscribe Data { "messages": { "1": { "text": "hello, firebase", "user": "sota1235" }, "2": { "text": "hello, phpcon", "user": "phper" } } } Subscribe /messages New data New data

Slide 38

Slide 38 text

Even if many clients { "messages": { "1": { "text": "hello, firebase", "user": "sota1235" }, "2": { "text": "hello, phpcon", "user": "phper" } } }

Slide 39

Slide 39 text

Not Only Database feature • 認証機能 • Facebook, Twitter, Custom Auth, etc… • Rule for each tree • Permission • Validation

Slide 40

Slide 40 text

Rule • JSON形式で定義できる • JSON treeに対して細やかな制御ができる • Read/Write Permission • Validation • Adminユーザは全Ruleを無視できるので注意

Slide 41

Slide 41 text

{ "rooms": { "1": { "messages": { "1": { "text": "hello, php", "user": "sota1235" } } } } } 例例えばこんなJSON

Slide 42

Slide 42 text

{ "rooms": { "1": { "messages": { "1": { "text": "hello, php", "user": "sota1235" } } } } } 例例えばこんなJSON νϟοτϧʔϜΛදݱ

Slide 43

Slide 43 text

{ "rooms": { "1": { "messages": { "1": { "text": "hello, php", "user": "sota1235" } } } } } 例例えばこんなJSON ෦԰͝ͱͷVOJRVFͳ*%

Slide 44

Slide 44 text

{ "rooms": { "1": { "messages": { "1": { "text": "hello, php", "user": "sota1235" } } } } } 例例えばこんなJSON νϟοτϧʔϜ಺ͷ ίϝϯτҰཡ

Slide 45

Slide 45 text

Ruleを設定してみる

Slide 46

Slide 46 text

{ "rules": { ".write": true, ".read": true, ".validate": "validation rule" } } Ruleの基本⽂文法

Slide 47

Slide 47 text

{ "rules": { ".write": true, ".read": true, ".validate": "validation rule" } } Ruleの基本⽂文法 ① おまじない

Slide 48

Slide 48 text

{ "rules": { ".write": true, ".read": true, ".validate": "validation rule" } } Ruleの基本⽂文法 ① おまじない ② Read/Write 権限

Slide 49

Slide 49 text

{ "rules": { ".write": true, ".read": true, ".validate": "validation rule" } } Ruleの基本⽂文法 ① おまじない ② Read/Write 権限 ③ Validationルール

Slide 50

Slide 50 text

例例. 意図しないKeyの追加 { "rooms": { "1": { "messages": { "1": { "text": "hello, php", "user": "sota1235" } } } } } • 意図しないJSON key を追加させたくない • rootにはroomsだけ⽣生 えてて欲しい

Slide 51

Slide 51 text

例例. 意図しないKeyの追加 { "rooms": { "1": { "messages": { "1": { "text": "hello, php", "user": "sota1235" } } } }, "extra": { "msg": "pwned" } } • 意図しないJSON key を追加させたくない • rootにはroomsだけ⽣生 えてて欲しい • こういうのを追加させ ない

Slide 52

Slide 52 text

{ "rules": { ".write": false, "rooms": { ".write": true, ".read": true } } } 例例. 意図しないKeyの追加

Slide 53

Slide 53 text

{ "rules": { ".write": false, "rooms": { ".write": true, ".read": true } } } 例例. 意図しないKeyの追加 Tree最上部への書き込みを 許容しない

Slide 54

Slide 54 text

{ "rules": { ".write": false, "rooms": { ".write": true, ".read": true } } } 例例. 意図しないKeyの追加 Tree最上部への書き込みを 許容しない “rooms”配下への あらゆる書き込みを許可する

Slide 55

Slide 55 text

{ "rules": { ".write": false, "rooms": { ".write": true, ".read": true } } } 例例. 意図しないKeyの追加 Tree最上部への書き込みを 許容しない “rooms”配下への あらゆる書き込みを許可する ਌ͷ3VMFΑΓ΋5SFF಺ͷ3VMF༏ઌ͢Δ

Slide 56

Slide 56 text

Ruleの活⽤用例例 • 全Treeへの読み書き制御 • Validation処理理 • 認証/認可の制御 • 認証を管理理するTreeを⽤用意し、そこに存在し ないuser_idの書き込みを弾く、なんてこと もできる

Slide 57

Slide 57 text

Ruleの適⽤用 • GUI or REST APIで⾏行行う • REST APIでの管理理がおすすめ

Slide 58

Slide 58 text

Realtime Databaseを どこで使うか

Slide 59

Slide 59 text

サーバPush⽅方式のデータ全て

Slide 60

Slide 60 text

サーバPush⽅方式のデータ全て ↓ ライブ感を演出するもの全て

Slide 61

Slide 61 text

ライブ感を演出するもの ↓ 即反映されて欲しい情報

Slide 62

Slide 62 text

ライブ感を演出する要素 • コメント • いいね • 視聴者数の変動 • 商品周りのメッセージ

Slide 63

Slide 63 text

ライブ感を演出する要素 視聴者数 コメント いいね 商品リスト 更更新

Slide 64

Slide 64 text

ユーザに⾒見見せないもの • ライブ終了了通知 • 商品リスト更更新通知 • その他メタ情報

Slide 65

Slide 65 text

Architecture

Slide 66

Slide 66 text

アーキテクチャ

Slide 67

Slide 67 text

アーキテクチャ 順番に解説していきます

Slide 68

Slide 68 text

Step to use Realtime Database

Slide 69

Slide 69 text

Step 1. スキーマ設計 2. Rule設計 3. Read/Write実装 4. スケーリング

Slide 70

Slide 70 text

1. スキーマ設計

Slide 71

Slide 71 text

とにもかくにもスキーマ設計

Slide 72

Slide 72 text

スキーマ定義のコツ • Subscribe側を意識する • ⾮非正規化したほうが場⾯面もある • 後⽅方互換性を意識する • バージョンアップした時に困らない構成を

Slide 73

Slide 73 text

{ "lives": { "1": { "messages": { "1": { "user": "sota1235", "image": "hoge.png", "text": "hello" } }, "notifications": { "buy_item": { "text": “sota1235さんが商品を購⼊入したぞい" } } } }, "alive_lives": { "1": true, "2": false } } メルカリチャンネルの例例(⼀一部略略)

Slide 74

Slide 74 text

あれ?配列列がないけど… • Realtime DatabaseのJSONで配列列は扱えない • 特定のnodeにaddすると⾃自動でunique IDが振 られる messagesにaddして ⾃自動で振られたID

Slide 75

Slide 75 text

Q. スキーマレスだけど、   どうやってスキーマ縛るの? Aを Q&A

Slide 76

Slide 76 text

Q. スキーマレスだけど、   どうやってスキーマ縛るの? A. Ruleを使います Q&A

Slide 77

Slide 77 text

2. Rule設計

Slide 78

Slide 78 text

Ruleによるスキーマ定義 • Realtime Databaseにスキーマという概念はない • データは⼀一枚岩のJSON • ドキュメント等にスキーマを記録し、書き込み/ 読み込み時の実装を⾏行行う • スキーマの整合性はRuleで担保する

Slide 79

Slide 79 text

{ "lives": { "1": { "messages": { "1": { "user": "sota1235", "image": "hoge.png", "text": "hello" } }, "notifications": { "buy_item": { "text": “sota1235さんが商品を購⼊入したぞい" } } } }, "alive_lives": { "1": true, "2": false } } メルカリチャンネルスキーマ(再掲)

Slide 80

Slide 80 text

まずは追加できるkeyを縛る • あらかじめ決めたスキーマのkeyのみ書き込み を許可する • それ以外は許可しない • コメント等、データを丸ごと追加するものは それに含むkeyに対してvalidationをかける

Slide 81

Slide 81 text

{ "rules": { ".write": false, "lives": { "$live_id": { "messages": { "$message_id": { ".validate": "newData.hasChildren(['user', 'image', 'text'])" } }, "notifications": { "buy_item": { ".validate": "newData.hasChildren(['text'])" } } } }, "alive_lives": { ".write": false, ".read": false } } } Rule

Slide 82

Slide 82 text

{ "rules": { ".write": false, "lives": { "$live_id": { "messages": { "$message_id": { ".validate": "newData.hasChildren(['user', 'image', 'text'])" } }, "notifications": { "buy_item": { ".validate": "newData.hasChildren(['text'])" } } } }, "alive_lives": { ".write": false, ".read": false } } } Rule +40/SPPUʹॻ͖ࠐΈΛڐՄ͠ͳ͍

Slide 83

Slide 83 text

{ "rules": { ".write": false, "lives": { "$live_id": { "messages": { "$message_id": { ".validate": "newData.hasChildren(['user', 'image', 'text'])" } }, "notifications": { "buy_item": { ".validate": "newData.hasChildren(['text'])" } } } }, "alive_lives": { ".write": false, ".read": false } } } Rule NFTTBHFT഑Լͷ৽σʔλʹ VTFS JNBHF UFYULFZΛڧ੍͢Δ

Slide 84

Slide 84 text

{ "rules": { ".write": false, "lives": { "$live_id": { "messages": { "$message_id": { ".validate": "newData.hasChildren(['user', 'image', 'text'])" } }, "notifications": { "buy_item": { ".validate": "newData.hasChildren(['text'])" } } } }, "alive_lives": { ".write": false, ".read": false } } } Rule ʁʁʁ

Slide 85

Slide 85 text

データ読み込みの動的制御 • ライブ放送中はデータ読み取りを許可する • 放送後はデータを読み込ませない

Slide 86

Slide 86 text

データ読み込みの動的制御 • ライブ放送中はデータ読み取りを許可する • 放送後はデータを読み込ませない • 特定のライブIDが放送中かどうかのフラグを 管理理し、動的に変更更する

Slide 87

Slide 87 text

{ "rules": { ".write": false, "lives": { "$live_id": { "messages": { "$message_id": { ".validate": "newData.hasChildren(['user', 'image', 'text'])" } }, "notifications": { "buy_item": { ".validate": "newData.hasChildren(['text'])" } } } }, "alive_lives": { ".write": false, ".read": false } } } Rule ͜ΕΛ࢖͏

Slide 88

Slide 88 text

{ "rules": { ".write": false, "lives": { "$live_id": { "messages": { "$message_id": { ".validate": "newData.hasChildren(['user', 'image', 'text'])" } }, "notifications": { "buy_item": { ".validate": "newData.hasChildren(['text'])" } } } }, "alive_lives": { ".write": false, ".read": false } } } Rule "alive_lives": { ".write": false, ".read": false } ΫϥΠΞϯτ͔Β͸ ಡΈॻ͖ΛҰ੾ͤ͞ͳ͍

Slide 89

Slide 89 text

{ "rules": { ".write": false, "lives": { "$live_id": { ".read": "root.child('alive_lives').child($live_id).val() === true", "messages": { "$message_id": { ".validate": "newData.hasChildren(['user', 'image', 'text'])" } }, "notifications": { "buy_item": { ".validate": "newData.hasChildren(['text'])" } } } }, "alive_lives": { ".write": false, ".read": false } } } Rule

Slide 90

Slide 90 text

".read": "root.child('alive_lives').child($live_id).val() === true", Rule

Slide 91

Slide 91 text

".read": "root.child('alive_lives').child($live_id).val() === true", Rule JSONのrootから alive_channels.$live_idの値を 参照する

Slide 92

Slide 92 text

".read": "root.child('alive_lives').child($live_id).val() === true", Rule 該当のIDの値が alive_lives配下でtrueの時のみ 読み取り可

Slide 93

Slide 93 text

{ "lives": { "1": { ... }, "2": { ... } }, "alive_lives": { "1": true, "2": false } } つまり alive_lives[“1”]がtrueなので 読み取り可能

Slide 94

Slide 94 text

{ "lives": { "1": { ... }, "2": { ... } }, "alive_lives": { "1": true, "2": false } } つまり alive_lives[“2”]がfalseなので 読み取り不不可

Slide 95

Slide 95 text

{ "lives": { "1": { ... }, "2": { ... } }, "alive_lives": { "1": true, "2": false } } つまり ライブ放送開始/終了了時に ここのフラグを編集する

Slide 96

Slide 96 text

ちなみに • メルカリチャンネルではクライアントからの 書き込みを⼀一切許容していない • ⼯工数節約のため • APIの負担を減らすなら必ずやるべき • その際はより細やかなRule設定が重要

Slide 97

Slide 97 text

3. Read/Write実装

Slide 98

Slide 98 text

アーキテクチャ(再掲)

Slide 99

Slide 99 text

アーキテクチャ(再掲) Read Write

Slide 100

Slide 100 text

How to write data? Read Write

Slide 101

Slide 101 text

Write戦略略 • データの書き込みをメルカリ側のAPIか らのみ⾏行行う • データの書き込みは複雑なロジックが多 い • 認証/NG判定/攻撃検知 • こういった処理理をAPI側で担う • 認証はFirebase側でも可能 • それ以上はCloud Functionで Write

Slide 102

Slide 102 text

{ "rules": { ".write": false, "lives": { "$live_id": { ".read": "root.child('alive_lives').child($live_id).val() === true", "messages": { "$message_id": { ".validate": "newData.hasChildren(['user', 'image', 'text'])" } }, "notifications": { "buy_item": { ".validate": "newData.hasChildren(['text'])" } } } }, "alive_lives": { ".write": false, ".read": false } } } Rule(再掲) Adminユーザ以外に ⼀一切の書き込みを許容しない

Slide 103

Slide 103 text

書き込み処理理の流れ

Slide 104

Slide 104 text

書き込み処理理の流れ ① APIでリクエストを受ける ② Firebaseへのリクエストを   Enqueue ③ Worker processでJobを   Dequeue, Firebaseへ書き込み

Slide 105

Slide 105 text

書き込み処理理の流れ ② Firebaseへのリクエストを   Enqueue ③ Worker processでJobを   Dequeue, Firebaseへ書き込み

Slide 106

Slide 106 text

① APIでリクエストを受ける • クライアントからデータを 受け取る • 認証、DB保存、NG判定等 • Firebaseにデータを送る場 合はリクエストJobを Enqueueする

Slide 107

Slide 107 text

全てのDataをFirebaseに送る? • 送らない • 多すぎる書き込みはパフォーマンス低下を招く • ユーザ体験を損なわないものは間引く • いいね数は0.1秒に⼀一度しか送信しない • 間引くものと間引かないものを分ける

Slide 108

Slide 108 text

書き込み回数の計算 • 秒間あたりFirebaseに1000回まで許容する • いいね数を0.1秒に1回、視聴者数1秒に1回 • するとコメント他メッセージは秒間989回ま で送れる

Slide 109

Slide 109 text

② FirebaseへのリクエストをEnqueue • Firebaseへのリクエストは APIでやらない • Don’t trust each other • FirebaseをSPOFにしない

Slide 110

Slide 110 text

• メルカリAPIで利利⽤用しているqueueシステム • MySQLで動いている • 詳しくは[検索] [Q4M] Q4M Enqueue Dequeue

Slide 111

Slide 111 text

③ Firebaseへリクエスト • WorkerからFirebaseへリ クエスト • Firebase REST APIを叩く • kreait/firebase-phpを利利⽤用 • 公式で紹介されてる2つ のうち、こちらのほうが 質がいい

Slide 112

Slide 112 text

クライアントからFirebaseまで

Slide 113

Slide 113 text

クライアントからFirebaseまで ①データを送信

Slide 114

Slide 114 text

クライアントからFirebaseまで ͜͜Ͱ'JSFCBTFʹૹΔ͔ Ͳ͏͔൑அ͢Δ ①データを送信

Slide 115

Slide 115 text

クライアントからFirebaseまで ①データを送信 ②Queueを通じて リクエストJobを渡す

Slide 116

Slide 116 text

クライアントからFirebaseまで ①データを送信 ②Queueを通じて リクエストJobを渡す ③REST APIを叩く

Slide 117

Slide 117 text

How to read data? Read Write

Slide 118

Slide 118 text

Read戦略略 • クライアントは受け取った データを表示するだけ • 細かい制御はしない • 終了了済みのLiveデータは読 み取れなくする

Slide 119

Slide 119 text

Firebase接続の流れ GET channel Connect information Connect to Firebase Data publish

Slide 120

Slide 120 text

クライアント実装 • 公式SDKを利利⽤用する • iOS/Android/JavaScript • 普通に使う分には特に難しいポイントはない

Slide 121

Slide 121 text

Subscribe data • SDKのInterfaceはQuery形式で書けない • dataをsubscribeすると接続時点の過去のデータも取得される • 「視聴した瞬間からのコメントのみ取得」といったInterfaceは SDKにはない firebase.database() .ref(‘live/1235/messages') .on('child_added', (snapshot) => { console.log(snapshot.val()); });

Slide 122

Slide 122 text

Timestamp • データにtimestampを付与し ておく • このtimestampと現在時刻を ⽐比較して表示するかどうか判 定する { "text": “old", "timestamp": 1507226243 } { "text": “still old", "timestamp": 1507226300 } { "text": “new", "timestamp": 1507228000 } 視聴開始

Slide 123

Slide 123 text

Switch Firebase Instance • 複数のFirebase Realtime Databaseをつなぎ かえる場合はSDKのインスタンスを使いまわ せない • ⼀一意なkeyと⼀一緒にインスタンス⽣生成する必要 がある • 複数インスタンスの運⽤用については次から

Slide 124

Slide 124 text

4. スケーリング

Slide 125

Slide 125 text

スケールアップしない問題 • Realtime Databaseはスケールアップできない • ⾃自動でスケールアウトすることもない • 事前に負荷を計算し、場合によってはシャー ディング構成を取る必要がある

Slide 126

Slide 126 text

Single instance subscribe live ID

Slide 127

Slide 127 text

インスタンスを複数台⽴立てる • ある程度のtrafficに耐えるため • 負荷の低いインスタンスに順番に配信IDを 振っていく • 垂直分割しても⼤大丈夫なスキーマにしておく

Slide 128

Slide 128 text

計算する • Realtime Databaseの⼀一台のスペック • 同時接続10万 / 秒間書き込み1000回 • 実際の負荷がこの30%程度に留留まるよう台数 を検討する

Slide 129

Slide 129 text

Sharding subscribe live ID

Slide 130

Slide 130 text

イレギュラーを考える • メルカリチャンネルは最初の⼀一ヶ⽉月間、芸能 ⼈人やインフルエンサーの放送があった • 局所的にFirebaseへのアクセスが跳ねること が予想できた 通常のお客さまがその影響を受けないよう 常⽤用インスタンスと⾼高Traffic専⽤用インスタンスを分けた

Slide 131

Slide 131 text

⾼高traffic⽤用インスタンス

Slide 132

Slide 132 text

⾼高traffic⽤用インスタンス 通常インスタンス ⾼高traffic⽤用 インスタンス

Slide 133

Slide 133 text

⾼高traffic⽤用インスタンス 通常インスタンス ⾼高traffic⽤用 インスタンス live ID

Slide 134

Slide 134 text

⾼高traffic⽤用インスタンス live ID

Slide 135

Slide 135 text

⾼高traffic⽤用インスタンス live ID

Slide 136

Slide 136 text

⾼高traffic⽤用インスタンス live ID

Slide 137

Slide 137 text

⾼高traffic⽤用インスタンス live ID

Slide 138

Slide 138 text

⾼高traffic⽤用インスタンス live ID

Slide 139

Slide 139 text

料料⾦金金体系 • Firebase Realtime Databaseは従量量課⾦金金 • 何台インスタンスを追加してもTrafficが無けれ ばタダ

Slide 140

Slide 140 text

インスタンス管理理 • Firebase ProjectとGCP Projectは必ず1対1 • ただしGCP ProjectをGUI以外で作る⽅方法がな い… • Project作成、Rule設定、Auth情報ダウンロー ド等全てマニュアルでやらなければいけない

Slide 141

Slide 141 text

Realtime Databaseを 導⼊入してみて

Slide 142

Slide 142 text

リリース後の様⼦子 • キャンペーン期間の芸能⼈人による配信の際にも問題な く稼働した • Latencyが少ない • ⼈人の感覚ではほぼ同時 • 相当なコメント量量も問題なく捌いている • ボタン1つで10万接続耐えるインスタンスが作れるの は便便利利

Slide 143

Slide 143 text

課題点 • スケールアウトがめんどくさい • GUI以外でのFirebaseプロジェクトの追加⽅方法 が無い • 現状スケールアウト = マニュアル操作 • 10万を越える接続に対応できない • 本番QAが⾯面倒くさい

Slide 144

Slide 144 text

余談: Cloud Firestore

Slide 145

Slide 145 text

Cloud Firestoreで変わった点 • ⾃自動スケールアウトするようになった • SDKのI/Fがよくなった • いわゆるQueryが使える • Latencyが伸びる可能性がある • 肌感覚的には誤差とのこと(要検証)

Slide 146

Slide 146 text

Realtime Database vs Cloud Firestore • 新規プロダクトは基本Cloud Firestoreでよい • Cloud FirestoreはRealtime Databaseの課題 を解決する形で実装されている

Slide 147

Slide 147 text

Realtime Database vs Cloud Firestore • ただし以下の場合はRealtime Databaseを検討 すべし • Read/Writeオペレーションが⼤大量量に発⽣生する • 10milli sec単位でもLatencyを速くしたい

Slide 148

Slide 148 text

Firebase Dev Summit • オランダで開催されるFirebaseのカンファレ ンス • Cloud Firestoreに関する発表が聞けそう

Slide 149

Slide 149 text

最後に

Slide 150

Slide 150 text

何がよかったか • 守りたいものを守りながら実装をできたこと • ライブ感というユーザ体験 • シンプルなアーキテクチャ • これらを捨てずに短期開発リリースを実現

Slide 151

Slide 151 text

Thank you