はじめに
こんにちは。TIG DXチームの村瀬です。
Googleで「スロットリング」で検索するとパチスロのリングが沢山ヒットするんですね。
今回はその「SLOT リング」ではなく「throttling」関して記載します。
スロットリングとは
一定時間内に受信可能なリクエスト数を制限し、制限を上回るリクエストがなされた際には受信を拒否しエラーコードを返却すること。時間経過により再び受信可能となる仕組みです。
リクエスト数を制限することでシステムにかかる負荷を抑えたり、スパムメールの送信を防止するのに利用されます。
SaaSであれば有限のコンピューティングをみんなでシェアするのでより多くの人が快適に利用できるよう、一部のユーザからの大量リクエストを制限するのに利用されます。もし無制限にリクエストを受け入れたとするとシステムに負荷がかかり、クライアントへのレスポンスに時間を要したり待たされた挙句にタイムアウトしてしまいます。
これは大人気の遊園地が入場制限することで、入場済みの来場者に快適に過ごしてもらうことに似ています。入場前の来場者にとっては好ましくありませんが。。。
受信拒否時の対応方法
リクエストする側としては受信拒否されないに越したことはありませんが、拒否された際には以下の対応をするとお行儀が良いです。
・少し待ってからリトライする。
・ユーザに対してしばらく経ってから再度アクセスするようにアナウンスする。
遊園地で入場制限がかかるとその日の入園は絶望的で遠方から訪れていると大変がっかりしますが、コンピュータの世界では極短時間です。システムにもよりますが数秒待ってからリトライしてみましょう。一定回数リトライしてみてダメならユーザにしばらく経ってから再度アクセスするようにアナウンスしましょう。
リトライに一手間加えてスループットを向上させよう
一定時間待ってからリトライしようとすると同一タイミングで受信拒否されたアクセス数分一斉にアクセスすることになり再度受信拒否されてしまう可能性が高いです。
ここは工夫が必要です。
方法はいくつもあると思いますがExponential Backoff And Jitterのテクニックが効果的です。
詳細はAWS Solutions Architect ブログにまとめられているのでそちらをご覧ください。
少しだけ説明します。
Exponential Backoff
リトライの間隔を倍々に増加させてく手法
例えばリトライの度に1秒,2秒,4秒,8秒と待ち時間を増やしていく。
※あくまで例示ですので適切な時間を経過したらエラーであることをユーザにアナウンスしたほうがユーザーフレンドリーです。
Jitter
リトライの間隔にばらつきを持たせる手法
クライアント毎にランダムな秒数待ってからリトライする。
Exponential Backoff And Jitter
リトライの間隔を倍々に増加させた上でばらつかせる
上図は[AWS Solutions Architect ブログ](https://aws.typepad.com/sajp/2015/03/backoff.html)より引用これらのリトライ手法により単位時間あたりのアクセス数が低減でき、スロットリングの受信拒否が起きにくくなります。
受信拒否の回避方法
システムにより状況は異なると思われますが概ね以下のような対応が必要です。
・受信拒否される要因を分散させる。
送信元のメールアドレスやIPアドレス、APIキーが要因となりえます。
・適切にキューイングやWAITを入れ単位時間あたりのリクエスト数を制限する。
スロットリングを実装する場合
これまでスロットリングされているサービスを利用する側の視点で説明してきましたが、反対に自分のサービスにスロットリングを実装することを考えてみましょう。
単位時間あたりのリクエスト数を正確に計測しようとするとRDBMSを利用してリクエストの度にINSERTし、単位時間あたりのリクエスト数を確認する為にSELECTするなどが必要になります。スロットリング処理の割合が高くなり、本来行うべき処理に支障をきたすのでゆるい制御をすることをおすすめします。
簡易的に行うのであればリクエスト毎の同期処理で閾値判定処理をするのではなく非同期処理で閾値判定し超えていたら一定時間受信を拒否する仕組みが良いと思います。
簡易的なスロットリングの仕組み
APIキーを用いてスロットリングされるものとして説明します。
サービスプロセス
1.クライアントからサービスへAPIキーを付与してアクセスする
2.APIキーを含めたアクセスログを出力する
3.受信拒否するかどうかAPIキーに対応するロック状態を取得する
4.ロック状態により正常なレスポンスか受信拒否のレスポンスを返却する
スロットリング制御プロセス
1.定期的にアクセスログを取得する
2.直近の単位時間あたりのアクセス数をAPIキー毎にカウントし、閾値を超えている場合はロック、超えていない場合は非ロックの状態に変更する
これらにより重い処理はスロットリング制御プロセスが担い、サービスプロセスに負荷をかけずにスロットリング処理が実現できます。
まとめ
一部の利用者のせいでその他の利用者が不快な思いをしないようにする仕組みであるスロットリング。この仕組みのおかげで大多数の利用者が快適にサービスを利用できます。サービスを利用する場合でもサービスを提供する場合でも他の利用者のことを考慮し適切な対応を心掛けましょう。