WebSocketとポーリング、ロングポーリングの違い【非同期通信と双方向通信】
前説
非同期通信
非同期通信とは、2人以上のユーザーがそれぞれ自分たちの都合のいいタイミングでデータを受信し、通信をすることである。
同期通信とは、リクエストを送信した後、レスポンスを受け取るまで何もできない。
非同期通信ではリクエスト送信をJavaScriptに任せることで、リクエスト送信後からレスポンスを受け取るまでに、続けて処理を行うことができる。
この非同期通信を行うために使用する技術がAjaxであり、その根幹を成しているのがXMLHttpRequestである。
- 参照1: https://developer.mozilla.org/ja/docs/Glossary/Asynchronous
- 参照2: https://atmarkit.itmedia.co.jp/aig/07wcr/hidouki.html
- 参照3: https://ja.wikipedia.org/wiki/XMLHttpRequest
双方向通信
非同期通信を利用することで、ユーザーが続けて連続してリクエストを送信することができるようになった。
だが、Ajaxは従来のHTTPプロトコルに倣って作られたものであり、リクエストが来なければ、サーバーはレスポンスを返すことができない。
よって、任意のタイミングでデータを更新させ続けるには、
- 常にリクエストとレスポンスを繰り返し続ける(ポーリング)
- リクエストを受け取った後、一定期間サーバー内でレスポンスを返さない(ロングポーリング、Comet)
ようにする必要がある。
いずれの方法も、簡易に実装できるメリットがあるが、データの更新がなければ、無駄なリクエストとレスポンスが送信されてしまう。
結果的にそれはサーバーの負担に繋がる。この問題はHTTPの構造に起因するため、プロトコル単位での改定が求められた。
そして生まれたのが、WebSocketである。
WebSocketは双方向通信が可能な、HTTPとは全く別のプロトコルである。
WebSocketは通信経路を確立させるため、前もってHTTP通信を行う必要がある。しかし、一度でも通信経路を確立させてしまえば、通信にかかるコストを非常に小さく抑えることができる。
また、WebSocketでは、サーバー側が能動的にクライアントサイドに通信(Push通信)を行うことが可能なため、データの変化を検知し、即座にクライアントに反映される。
そのため、ポーリングやロングポーリングと違って、無駄なリクエストが発生することはない。
このWebSocketの双方向通信により、遥かに低コストで、チャットサイトやメッセンジャーアプリの運用が可能になる。
- 参照4: https://ja.wikipedia.org/wiki/Comet
- 参照5: https://ja.wikipedia.org/wiki/Push%E6%8A%80%E8%A1%93#Long_polling
- 参照6: https://ja.wikipedia.org/wiki/WebSocket
比較早見表
各技術の比較をする。サーバーの負担はコストと比例するので、『高負担=高コスト』と解釈しても良いだろう。
技術 | WEBサーバーの負担 | DBサーバーの負担 | 即応性 | 実装難易度 |
---|---|---|---|---|
ポーリング | とても高い | 高い | 1秒~3秒程度のラグがある | 簡単 |
ロングポーリング | 高い | とても高い | 1秒ほどのラグがある | やや難しい |
WebSocket | 低い | 低い | リアルタイム | とても難しい |
djangoでWebSocketを動かす。
下記では、実際にdjangoでWebSocketを使い、チャットサイトを作っている。