試験の目標値はどこから来るのか
目標
4週間分の時間別トラフィックデータに、1日の総量・ピークの時間帯・安全係数・障害への余裕・成長率を順に適用して、負荷テストの目標RPSを導き出し、その目標を実際にかけて、この環境で出せるかまで確認します。
なぜ重要なのか
負荷テストの計画書で、最もよく空欄になっているのは、目標RPSの出どころです。「1秒あたり1,000件」がどこから出たのかを尋ねると、たいてい答えがなく、それではテストに合格しても、何を保証したのかを言えません。目標は、運用データから導き出す必要があります。1日の総量を86400で割った平均は、ほとんどいつも実際のピークより何倍も小さく、その平均で容量を決めると、ちょうどその倍率の分だけ足りなくなります。そこに、ピークでも容量を使い切らないためのヘッドルーム、ゾーン1つが抜けても耐えるための余裕、次の計画の周期までの成長率が、順に掛け合わされます。最後に、そうして決めた目標が実際にかけられるかを、一度確認する必要があります。かけられなかった負荷で得た合格は、合格ではありません。
ステップ
/opt/lab/lt/lt-capacity-target/traffic.tsvは、4週間分の時間別のリクエスト数です(ヘッダー1行のあと날짜 시각 요청수、プレースホルダーは日付、時刻、リクエスト数です)。日付ごとの合計を、/root/lt-capacity-target/daily.tsvに、タブで区切った2列<날짜> <하루 총 요청 수>で28行書き(プレースホルダーは日付と1日の総リクエスト数です)、/root/lt-capacity-target/01-peak-day.txtに、2行peak_date=とpeak_total=を書いてください。最も忙しかった1日です。- 最も忙しかった日の24時間のうち、最も忙しい1時間を探して、
/root/lt-capacity-target/02-peak-hour.txtに、3行peak_hour=(0..23の整数)・peak_hour_requests=(その1時間のリクエスト数)・peak_share=(その1時間がその日の総量に占める割合、小数第4位まで)を書いてください。 /root/lt-capacity-target/03-rps.txtに3行を書いてください。avg_rps=は、最も忙しかった日の総量を86400で割った値、peak_rps=は、最も忙しい1時間のリクエスト数を3600で割った値(どちらも小数第2位まで)、peak_over_avg=は、2つの比(小数第2位まで)です。- 運用の余裕(ヘッドルーム)を30%に取ります。ピークでも容量の70%だけを使うという意味です。
/root/lt-capacity-target/04-headroom.txtに、2行headroom=0.30とrps_after_headroom=を書いてください。後ろの値は、peak_rps ÷ (1 − headroom)を小数第2位まで書きます。 - サービスは4つのゾーンに均等に配置されていて、1つのゾーンがまるごと抜けても、ピークを受け止める必要があります。
/root/lt-capacity-target/05-nplus1.txtに、3行nodes=4・surviving=3・rps_after_nplus1=を書いてください。後ろの値は、rps_after_headroom × nodes ÷ survivingを小数第2位まで書きます。 - トラフィックが月8%ずつ増えていて、この容量で6か月を持ちこたえる必要があります。
/root/lt-capacity-target/06-growth.txtに、4行monthly_growth=0.08・months=6・growth_factor=(1.08の6乗、小数第4位まで)・rps_after_growth=(rps_after_nplus1 × growth_factor、小数第2位まで)を書いてください。 /root/lt-capacity-target/target.tsvを作成してください。ヘッダーなしで5行、各行はタブで区切った2列<단계> <RPS>です(プレースホルダーはステップ名とRPSです)。ステップ名は順にpeak・headroom・nplus1・growth・targetで、最初の4行は前のステップで書いた値を、最後のtargetの行は、rps_after_growthを切り上げた整数を書きます。そして/root/lt-capacity-target/07-note.txtに、2行test_target_rps=(その整数)とreason=(この目標がどこから出たかを60文字以上)を書いてください。/opt/lab/lt/lt-capacity-target/echo.pyをポート8095で起動し、ステップ7で決めた目標を、実際にかけてみてください。ワーカーは20個、ワーカーあたりのレート上限は올림(목표 ÷ 20)、リクエスト数は목표 × 5とし(プレースホルダーは切り上げと目標です)、元のCSVを/root/lt-capacity-target/run.csvに残します。そのあと/root/lt-capacity-target/08-run.txtに、5行target_rps=・workers=20・q_per_worker=・measured_rps=(run.csvから再計算した値、小数第2位)・reached=(measuredが目標の90%以上ならyes、そうでなければno)と、50文字以上のnote=を書いてください。
参考
- 作業ディレクトリは
/root/lt-capacity-targetです。なければ先に作成してください。 - データと負荷対象は
/opt/lab/lt/lt-capacity-target/にあります。traffic.tsv(4週間 × 24時間)、そのデータを作ったgen_traffic.py(シード固定)、そしてステップ8で使うecho.pyです。 - 丸めの約束: 比率は小数第4位、RPSは小数第2位、最後の目標だけが切り上げた整数です。採点ツールは、データから同じ計算をやり直して突き合わせます。
- よくある間違い: ヘッドルームを掛け算で適用してしまうこと。30%の余裕は、
× 0.7ではなく÷ 0.7です。 - よくある間違い: 成長率を単利で計算してしまうこと。月8%で6か月なら、1.48ではなく1.08の6乗です。
- Google SRE Workbook — Managing Load・SRE Book — Software Engineering in SRE (需要予測)・hey: オプション-n・-c・-qの定義・k6: scenariosと到着率・USE Method
まず1日の総量を数える
/opt/lab/lt/lt-capacity-target/traffic.tsvは、4週間分の時間別のリクエスト数です(ヘッダー1行のあと날짜 시각 요청수、プレースホルダーは日付、時刻、リクエスト数です)。日付ごとの合計を、/root/lt-capacity-target/daily.tsvに、タブで区切った2列<날짜> <하루 총 요청 수>で28行書き(プレースホルダーは日付と1日の総リクエスト数です)、/root/lt-capacity-target/01-peak-day.txtに、2行peak_date=とpeak_total=を書いてください。最も忙しかった1日です。
awk -F'\t'で、3列目を日付ごとに足せばよいのです。ヘッダーの1行は飛ばしてください。容量計画の基準は平均ではなく、最も忙しかった日です。平均で決めると、その日に崩れます。
その1日の中で、いつが最も忙しかったか
最も忙しかった日の24時間のうち、最も忙しい1時間を探して、/root/lt-capacity-target/02-peak-hour.txtに、3行peak_hour=(0..23の整数)・peak_hour_requests=(その1時間のリクエスト数)・peak_share=(その1時間がその日の総量に占める割合、小数第4位まで)を書いてください。
24時間が均等なら、1時間の取り分は1 ÷ 24 = 0.0417です。実際の値がその何倍かが、このステップの要点です。その倍率が、そのまま「平均で計画するとどれだけ足りないか」です。
平均で割った値は、何倍足りないか
/root/lt-capacity-target/03-rps.txtに3行を書いてください。avg_rps=は、最も忙しかった日の総量を86400で割った値、peak_rps=は、最も忙しい1時間のリクエスト数を3600で割った値(どちらも小数第2位まで)、peak_over_avg=は、2つの比(小数第2位まで)です。
1日の総量 ÷ 86400は、「その日が24時間ずっと同じように忙しかったなら」の値です。実際のピークは、それよりはるかに大きいのです。この倍率を知らずに、平均で容量を決めると、ピークの時間帯に、ちょうどこの倍率の分だけ足りません。
余裕を残して、目標を上げる
運用の余裕(ヘッドルーム)を30%に取ります。ピークでも容量の70%だけを使うという意味です。/root/lt-capacity-target/04-headroom.txtに、2行headroom=0.30とrps_after_headroom=を書いてください。後ろの値は、peak_rps ÷ (1 − headroom)を小数第2位まで書きます。
ピークで容量を100%使うと、キューがたまり始める地点に、すでに乗っていることになります。待ち行列理論では、利用率が1に近づくほど、待ち時間が急激に増えます。そのため、目標はピークより上に取ります。割り算です。0.7を掛けるのではありません。
1つのゾーンが抜けても耐えられるようにする
サービスは4つのゾーンに均等に配置されていて、1つのゾーンがまるごと抜けても、ピークを受け止める必要があります。/root/lt-capacity-target/05-nplus1.txtに、3行nodes=4・surviving=3・rps_after_nplus1=を書いてください。後ろの値は、rps_after_headroom × nodes ÷ survivingを小数第2位まで書きます。
4つのゾーンが3つだけ残っても、同じ負荷を受けるには、全体が4/3倍の容量を持っている必要があります。そのため、テストで確認すべき負荷も、その分だけ上がります。この係数を抜かすと、平常時は問題なく、ゾーン1つが抜ける日にだけ崩れます。最も悪い失敗の仕方です。
半年後にも使える目標か
トラフィックが月8%ずつ増えていて、この容量で6か月を持ちこたえる必要があります。/root/lt-capacity-target/06-growth.txtに、4行monthly_growth=0.08・months=6・growth_factor=(1.08の6乗、小数第4位まで)・rps_after_growth=(rps_after_nplus1 × growth_factor、小数第2位まで)を書いてください。
複利です。8% × 6 = 48%ではなく、1.08の6乗です。2つの差が、目標の数値を何パーセント変えるかを、自分で計算してみてください。成長率はデータから推定するのが原則ですが、このステップでは、製品計画から受け取った値のままにして、計算方法に集中します。
目標がどこから出たかを、1つのファイルに残す
/root/lt-capacity-target/target.tsvを作成してください。ヘッダーなしで5行、各行はタブで区切った2列<단계> <RPS>です(プレースホルダーはステップ名とRPSです)。ステップ名は順にpeak・headroom・nplus1・growth・targetで、最初の4行は前のステップで書いた値を、最後のtargetの行は、rps_after_growthを切り上げた整数を書きます。そして/root/lt-capacity-target/07-note.txtに、2行test_target_rps=(その整数)とreason=(この目標がどこから出たかを60文字以上)を書いてください。
この表1枚が、「1秒あたり1,000件はどこから出たのですか」という質問への答えです。4行を見れば、どの仮定を変えると目標がどれだけ動くかも、ひと目でわかります。ヘッドルームを20%に下げると、目標がいくつになるかを、頭の中で計算してみてください。
その目標は、この環境でかけられるのか
/opt/lab/lt/lt-capacity-target/echo.pyをポート8095で起動し、ステップ7で決めた目標を、実際にかけてみてください。ワーカーは20個、ワーカーあたりのレート上限は올림(목표 ÷ 20)、リクエスト数は목표 × 5とし(プレースホルダーは切り上げと目標です)、元のCSVを/root/lt-capacity-target/run.csvに残します。そのあと/root/lt-capacity-target/08-run.txtに、5行target_rps=・workers=20・q_per_worker=・measured_rps=(run.csvから再計算した値、小数第2位)・reached=(measuredが目標の90%以上ならyes、そうでなければno)と、50文字以上のnote=を書いてください。
総RPSは、요청 수 ÷ (max(offset + response-time) − min(offset))です(プレースホルダーはリクエスト数です)。目標をかけられなかったなら、それはサーバーの結論ではなく、負荷ジェネレーターの限界で、レポートにその事実を書く必要があります。書かないと、次の人がこの数字を、サーバーの能力として読みます。