リアルタイムに表示が変わるウェブサイトの裏側で起きてること
ブラウザでアクセスした後、画面上の情報が何も操作していないのに自動で更新されていくサービスがだいぶ一般的になってきましたね
一般的に裏側でどんな処理をしているのか解説していきます
社内で開催する非エンジニアも対象にした勉強会用の記事です
ウェブサイトが表示されるまでの処理の流れ
リアルタイムに表示が変わるかどうかに関係なく初期表示までの流れは基本同じです
よく想像するのはこんな流れじゃないでしょうか?
一つのファイルだけじゃ表示できない
ただ、一つのファイルにすべての情報を記載することはアクセスしようとしてから表示されるまでの時間が遅くなってしまうので通常しません
最初に受け取ったファイルに追加で必要なファイルがリストアップされているので、ブラウザは続けてファイルを取りに行きます
追加でリクエストするファイル数はサイトによって異なりますが100件を超えることよくあります
ちなみにfindシステムは366リクエスト必要です
Googleの検索画面ですら40リクエスト必要です
爆速で表示できることで有名な阿部 寛のホームページは5リクエストのみです。。。すごい。。。
どうやってリアルタイムにデータを取ってきているのか?
1. ボタンを押したら取りに行くパターン
これは自動で取りに行ってないですが想像しやすいですね
更新ボタンがおいてあってそれを押すことで最新のデータをサーバーに取りに行く
シンプルな流れです
2. 定期的に取りに行くパターン
一定の間隔でサーバーに繰り返しリクエストを送ることで常に画面が最新の情報になるようにします
シンプルな作戦なので実装も簡単です
ただデータは更新してなくてもリクエストを送るので無駄なリクエストが増えてしまいます
3. 何かあるまでサーバーがレスポンスを返さないパターン
レスポンスはある程度遅くすることができます
そのためデータの変更があるまでレスポンスを保留することでリアルタイムにできます
ただレスポンスが来ると接続が終了してしまうので再度リクエストを送り待機します
ブラウザ側の実装はシンプルですがサーバー側が少し複雑ですね
またサーバーへの負荷も上がってきます
ブラウザがリクエストを受け付ける難しさ
「じゃぁ必要なタイミングでサーバがブラウザに更新のリクエストを送ればいいじゃん」ですって?
そうなんですよね
サーバーから必要なタイミングで情報を送り付けてもらえたら効率よさそうですよね
ただ、リクエストを受け付けるのって結構大変なんですよね
一般のご家庭であれば外部からのリクエストは攻撃以外にないので、通常どの機器も外部からのリクエストは遮断するようにしています
そのためサーバーからブラウザにリクエストを送るというのは結構難しかったりするんですよね
4. サーバーから送り付けるパターン
そんな中2011年にサーバーからもリクエストを送れるようにした通信規格が策定されました
それまでリクエストとレスポンスは必ずセットでしたが、新しい規格はブラウザからもサーバーからも好きにデータを送れるものでした
これを使ったリアルタイム更新はこんな流れになります
画面を表示するところからまとめるとこんな感じですね
じゃぁみんなこれにしているのか?
というとそうでもなかったりします
利便性もサーバーへの負荷も実装コストも1 < 2 < 3 < 4だからです
普段触っているサービスの通信を見る限りこんな感じのパターンのようです
パターン | サービス |
---|---|
2 | Gmail |
Googleカレンダー | |
X | |
3 | Box |
4 | |
Notion | |
Figma | |
Slack |
そこまでリアルタイムじゃなくていいなら2、リアルタイム性求めるなら4という違いがありそうですね
おまけ
- パターン2
- ポーリングと呼ばれる
- 間隔を短くしすぎるとDOS攻撃に見えなくもないのでせめて10秒以上は空ける
- パターン3
- ロングポーリングと呼ばれる
- エンジニア的にはなんかちょっとイケてない雰囲気を感じる
- パターン4
- これに使われる通信方法はWebSocket通信と呼ばれる
- チャットくらいリアルタイム性を求められるととりあえずこの方式を選ぶ
- リクエストを送るのにも通常一時的な通信確立のための処理が走るが、この方式はそれすらもないのでタイムラグがとても少ない
- 普通の通信と全然違うので実装も全然違ってくる
- AppSync
- こうしたサーバーを構築するためのAWSのサービス
- findではこれでAPIを構築している
- 普通のリクエストとレスポンスがセットの通信もWebSocket通信にも対応してる
Discussion