サーバーがオーバーロードし、緑色で示されたバックエンドのレイテンシが平均 2 倍になったときに、赤色のトラフィックが定期的に急上昇しているのが見て取れると思います。これこそジッターを採用すべき指標なのです。しかもこのグラフは、サンプルの時間間隔を示しているため、トラフィックのピークがかなり小さく表示されています。
その後、私たちはプラス / マイナス 1 分(20 %)というランダムな要素を各レイテンシのリトライに追加しました。その結果、以下のようにトラフィックはすぐに平準化され、周期性もなくなりました。
これでバックエンドがオーバーロードすることもなくなりました。もちろん、すぐにここまでたどり着いたわけではありません。しばらくこうしたオーバーロードをやり過ごすため、新しいコードを書き、クライアントが新しい動きをするよう配信しなくてはなりませんでした。
ここで言っておくべきことがあります。もしユーザーが均等に分散されていたとしても、実際には使用量が均等に分散されることなどほとんどないということです。
システムのスケールに関係なく、ほとんどすべてのシステムはユーザーの仕事や睡眠などの習慣に合わせてピークや谷間を迎えます。多くの人は、寝るときには電話やコンピュータの電源を落とします。つまり、みんなが朝起きてこれらの電源が入ると、トラフィックは山場を迎えるのです。
したがって、リトライに加え、通常の同期間隔に少しジッターを(10 % 程度)持たせるとよいでしょう。これは、アプリケーションが最初に同期を始める際には特に重要なことです。これにより、日常の周期的なトラフィックの山場を平準化させ、システムに負荷がかかりすぎないようにすることができます。
3. リトライに番号を付ける
バックエンドが大規模な場合は、すべてが同時に回復することはありません。システムが徐々に回復してオンラインになる際に、全体の処理能力も徐々に増していくのです。
待ち構えているクライアントをすべて同時に使えるようにしようとして、この回復作業を台無しにしないように注意してください。指数バックオフとジッターを両方採用したとしても、回復時にはリクエストに優先順位を付けるべきです。
簡単で効率的な方法として、クライアントがリトライするごとに番号を付加する方法があります。数値が 0 であれば、そのリクエストは通常の同期であり、1 であれば最初のリトライといった具合です。こうすることで、バックエンド側でどのリクエストを優先的に処理し、通常の状態に戻る過程でどのリクエストを無視すればよいかがわかるようになります。たとえばリトライの回数が多いときは、ユーザーは長時間同期できていなかったことになるため、そちらを優先させるようにすればよいのです。
また、リトライによる負荷の総容量を、たとえば 10 % というように固定の比率に設定し、通常の同期を優先させつつリトライは 10 % で実施するという方法もあります。
リトライをどう扱うかは、自社の事業ニーズに応じて決めてください。大切なのは、リトライに番号を付けることでサービス回復時に賢明な決断ができるということなのです。
リトライの回数を観察することで、順調に回復できているかどうかを把握することも可能です。もし 6 分間の停止状態から回復しようとしているときは、いちばん古いリトライの番号は 3 となっているはずです。回復が進むにつれ、番号 3 が急激に減り、次に 2 が減るといった状況になっていきます。
このようにならない場合は(もしくはリトライの番号が上がっていった場合は)、まだ問題が解決できていないことがわかります。単に全体のリトライの回数を見ているだけでは、こうした状況は把握できません。
最後にひと言
システムの負荷を管理し、エラーから順調に回復することはとても深いテーマです。今後も連鎖的な障害や負荷制限など、重要なトピックに関する記事を執筆する予定です。とりあえず、今回の記事にある手法を取り入れていただければ、1 分間ネットワークが遮断されたとしても DDoS のような惨事が発生することはないでしょう。
* この投稿は米国時間 11 月 9 日、Director of Customer Reliability Engineering である Dave Rensin と、Site Reliability Engineering の Software Engineer である Adrian Hilton によって投稿されたもの(投稿はこちら)の抄訳です。
- Posted by Dave Rensin, Director of Customer Reliability Engineering, and Adrian Hilton, Software Engineer, Site Reliability Engineering