結論
当たり前のことですが、下記を特に注意して処理の実装をしていく必要があります。
- ポーリングを実行するためのAPI実行回数を極力減らす
- バックエンド側でのデータベースへの接続を極力減らす
背景
チャット機能を実装しようとしており、管理画面上でユーザーからの新着メッセージをチェックする機能の実装が必要となりました。
本来WebSocket等つかった非同期処理を実装することが考えられますが、弊社では実績がなく検証からリリースまで想定よりも時間がかかる見込みだったことや、ポーリングであれば過去実績があり、リリースまで最短で実装できそう、ということでポーリングの処理を実装する方針に確定しました。
実装①:一旦実装してみる
下記の仕様で機能を実装しました。
- 3秒に1回APIをリクエストするようにループする
- バックエンド側では新着メッセージがあるかをデータベースに接続してチェック、あればHTMLを生成して返却、なければそのまま処理を終了
実装①の課題:接続回数の上限を設けていないので永遠とAPIを投げ続ける
当たり前ですね。画面をずっと開いていると3秒に1回永遠とAPIを投げ続けます。流石に上限を設けました。
実装②:APIをリクエストするループ処理を5分間を上限にする
ループ処理の上限を画面を開いてから5分間としました。5分経過したらAPIリクエストはストップします。
実装②の課題:5分間とはいえ、(3秒に1回のため)100回APIリクエストする処理になっている
そもそも3回に一回APIリクエストを投げる仕様がきつい。3秒に1回APIリクエストする処理を、5秒に1回や、10秒に1回に変更してもよかったが、根本解決にならない。
実装③:バックエンド側で、3秒おきに100回、新着メッセージがあるかチェックする仕様に変更
クライアント側からのAPIリクエストを1回に減らすことができる。さらに、データベースへの接続回数も1回に減らすことができる。
最終的な仕様
その後いろいろなユーザー側の課題等が発生する度にPDCAを回し、最終的にはこのような仕様となりました
- クライアント側からは、1回APIリクエストを送る。
- バックエンド側で、3秒おきに20回(1分間)新着メッセージがあるかチェックする
- 1分後、APIリクエストが終了する。その1分間の間に、画面上の操作を何かしら行う(keydownやclick)と、再度APIリクエストを送る
- 1分以上画面上の操作を何もしない場合、APIリクエストを終了する
- 画面上の操作を何かしら行うと、APIリクエストを再開
- 2~5の繰り返し
という仕様となりました。
ただAPIを投げ続けるだけでなく、バックエンド側で一定期間繰り返し処理を行うことで「APIリクエスト数が増える」「データベース接続が増える」課題を解決しました。
ポーリングはその仕様上サーバーへの負荷がかかってしまいがちのため、このようにして負荷を極力減らしていくことが必要です。安易に実装をするのではなく、(もちろんユーザーの意見も取り入れつつ)サーバーへの負荷を減らすような対応をしていきましょう。