はじめに
先週に引き続いて、櫻井です。社内の仕入れシステムSUPPLIER by RENOSYの開発を行なっております。 ついに入社して1年が経ちました。
先月末はハロウィンでしたが、如何お過ごしでしたでしょうか。 弊社で日本最大級のハロウィンイベント「カワサキ ハロウィン」にボランティアとして参加しました。 よければ以下の記事もご覧ください!
個人的には業務用Slackのアイコンを自身のピカチュウコスプレに変え、ささやかなハロウィン気分を楽しんでおりました。
前置きはここまでにして、今回は「サーバーの負荷が高い原因を探る〜初心者編〜」ということで、説明したいと思います。
経緯
今回この記事を書こうと思い立った理由が、先日行われたTGIFという、エンジニア全体ミーティングの中での、「オススメの本を発表しよう!」というコーナーでした。
(TGIFについては以下参照)
その中で私が発表したのが以下の本でした。
https://www.amazon.co.jp/dp/B07JHRVXGT
というのも、数ヶ月前に私が担当するシステムでサーバーが重くなり、そのボトルネックを探る際に非常に参考になったためです。
弊社には(素晴らしく頼りになる)SREチームがあるのですが、常に各システムに張り付いて見てもらう訳には行かないので、担当のサーバーサイドエンジニアとしてある程度の確認ができる知識は必要です。
この本の第4章で、その点しっかりとまとまっていたので、今回は復習の意味も込めて、この内容のまとめ+αを説明したいと思います。
似たような記事もあるとは思いますが、参考になると幸いです。
全体像
まず、全体のステップを説明します
ロードアベレージが高くなっているか確認
ロードアベレージが低い場合
- ソフトウェアの設定や不具合、ネットワーク、リモートホストを確認
ロードアベレージが高い場合
CPU・I/Oのいずれがボトルネックかを探る
CPUに原因がある場合
- ユーザープログラム・システムプログラムのいずれが原因かを探る
- 原因となっているプロセスを特定する
I/Oに原因がある場合
- スワップが発生していないか、確認する * 原因となっているプロセスを特定する
それでは、ステップ毎に見ていきましょう
ロードアベレージを確認する
ロードアベレージとは?
ロードアベレージはシステム全体の負荷状況を示す指標です。
topやuptimeコマンドで確認できます。
uptimeはロードアベレージだけを確認
topはメモリ・プロセス・CPUなど、幅広い情報を確認できます。
左から1分、5分、15分の平均値です。
簡単に言うと、平均的にどれだけのタスク(ほぼプロセスと同義)が実行待ちとなっているかと言うことを表します。
ここでの実行待ちとは、以下の2つが該当します。
CPUの実行権限が与えられているのを待っているタスク
ディスクI/Oが完了するのを待っているタスク
ロードアベレージの基準値
では、このロードアベレージがどれくらいであれば良いのでしょうか?
ロードアベレージが適切か確認する基準として、「CPUのコア数が1の場合、1.00以下であれば問題がない」と言われています。
平均した実行待ちプロセスが1つ以下で存在している状態ですね。
ここでCPUのコア数が1の場合、といったことには理由があり、
ロードアベレージは、システム全体の実行待ちのタスク数でしか計算されません。
つまりCPUのコア数が2つの場合、ロードアベレージが2であれば、各CPUに1つずつ待ちタスクを持っている状態なので、上記コア数1の場合の、1.00とほぼ同義と考えられます。
結論としては、ロードアベレージは基本的にCPUのコア数よりも低ければ、問題ないレベルと言えるでしょう。
(ちなみにコア数は以下のコマンドで確認できます)
$grep cpu.cores /proc/cpuinfo | sort -u cpu cores : 2
マルチコアでの基準値、コア数 > ロードアベレージは正しい?
※マルチコアでのロードアベレージの基準値は、様々議論があるようですが、この本の作者の方のブログ(https://naoya-2.hatenadiary.org/entry/20070518/1179492085)を拝見すると
nr_running > 1 のときはロードバランスが適切に働く。そのため 4CPU なら 4.00 で割れ、というのは負荷があるときはそれなりに正しい。
とされているので、信頼して良いと思います。
ロードアベレージが低い場合
ロードアベレージが高い場合の説明は後述しますが、「これが低いにも関わらずスループットが遅い場合」に考えられる原因としては、以下の通りです。
ソフトウェアの設定や不具合
ネットワーク
リモートホスト
ソフトウェアの設定や不具合というのは中々見つけづらいと思うので、まずは「ネットワークで遅延が起きていないか」や、リモートホスト、特に「別ホストのDBサーバー、ウェブサーバーで問題が起きていないか」、などをを確認するべきではないでしょうか。
このケースでのこれ以上に詳しい部分、原因の探り方というのは理解できていない(ケースが多い)ので、わからない場合は詳しい人に相談します。
ロードアベレージが高かった場合
これはつまり、実行待ちのタスクが多い=タスクの処理が進んでいないと言うことです。
しかし、ロードアベレージはシステム全体の負荷を示すものでしかありません。
詳しく原因を探るため、ボトルネックが以下のいずれであるかを確認します。
CPU
I/O
それぞれのケースはどのようなものでしょうか?
CPUがボトルネック
リクエストされるタスクに対し、CPUの計算処理が追いついていない状態です。
この「CPUに負荷が掛かっている状態」自体は、リソースをしっかりと使っているということなので悪いことではありませんが、 ロードアベレージが高い場合は、CPUの計算の処理が追いついていないということなので、対策を行う必要があります。
計算の多いアプリケーションサーバーでは、この状態が起きやすくなります。
I/Oがボトルネック
リクエストされるタスクに対し、ディスクとの入出力が追いついていない状態です。
データをディスクから検索するのが主な仕事であるDBサーバーでは、この状態が起きやすくなります。
では説明が終わったので、実際にどちらがボトルネックであるのか、探っていきましょう。
ロードアベレージが高い原因を探る(CPUかI/Oか)
CPUとI/Oの状態を確認するにはsarコマンドを使用します。
このコマンドでは、CPU使用率やI/O待ち率を確認できます。
※sarはsysstatパッケージに含まれているコマンドなので、入っていない方はインストールを行いましょう。
CPU使用率の確認
まずはCPUの使用率を確認していきます。
CPU使用率は先ほどのsarコマンドで、%userと%systemから見ることができます。
この2つの違いは何でしょうか?
%userはユーザーモードといって、通常のアプリケーションが動作するモードです。 これが高い場合はアプリケーションの実行に負荷が掛かっている状態です。
%systemはシステムモードといって、カーネルが動作するモードです。 これが高い場合はプロセス/スレッドの動作やシステムコールによって、負荷が高くなっている状態です。 後に説明する、I/Oの負荷が高い場合、こちらも上がる傾向にあります。
CPU使用率が高い場合
CPUの使用率が平均して80%~100%であれば、高い状態と言えるでしょう。
このようにCPUの使用率が高い場合には、CPUに負荷を掛けているプロセスを確認し、その上でそのプロセスに対して対策を打ちましょう。
負荷が高いプロセスを確認するには、pidstatコマンドを実行します。
これもsysstatパッケージのインストールにより使用ができるコマンドです。
※topやpsでも、プロセス毎にCPUの負荷を確認することができるのですが、これらは%userと%sysの違いが分かりません。
プロセスの確認と対策
ここで%CPUの値が高くなっているプロセスについて、
どのような処理のプロセスか
%usrと%sysのどちらが高くなっているのか
一時的なものなのか(バッチなど)、恒常的なものなのか
などを確認した上で
どのようにCPUの負荷を低くすることができるか
不可能であればCPUの能力を上げる必要があるか
など、具体的な対策を考えていきましょう。
これ以上のところは、今回は話をしません。
I/Oの確認
次はI/Oの確認を行っていきましょう。
先ほどのsarコマンドで、今度は%iowaitを確認します。
この値が高くなっていた場合は、I/Oに問題があると考えられます。
はっきりした基準は無いようですが40~50%かそれ以上になれば、高いと言えるのではないでしょうか。
ロードアベレージが高く、CPUの使用率が低い状態で、%iowaitが高ければ、I/Oが原因であると言えるでしょう
%iowaitが低い場合は、I/Oに問題はない?
上記のように
「ロードアベレージが高く、CPUの使用率が低い状態で、%iowatが高い」場合は、I/O待ちが原因と言えるのですが、では
「ロードアベレージが高く、CPUの使用率が高い状態で、%iowatが低い」場合の原因は何でしょうか?
これについて、以下の記事を参考にさせて頂きました。
結果としては
「CPUかI/O、どちらが原因かわからない」
です。
%iowaitが示すもの
というのも、%iowaitとは、「CPUがアイドル状態で、システムに未処理のディスク入出力要求があった時間の割合」を表しています。
そして、CPUがI/O待ちの状態で、CPUを使用するプロセスが存在した場合には、そのプロセスがCPUの使用を行なうことができます。
つまり
「CPU負荷が高い場合には、I/O待ちが存在したとしても、%iowaitには表れてこない」のです。
I/Oがボトルネックか確認するには、%iowaitを見ろ!と言うことを書いている記事もありますが、これだけで判断できるものではないので、ご注意ください。
CPU負荷が高い場合のI/O待ち確認
では、CPU負荷が高い場合にI/O待ちが発生しているかを確認するにはどうすれば良いでしょうか?
ここで登場するのが、iostatコマンドです。
こちらもsysstatパッケージで使用することができるようになるコマンドです。
この%utilによって、I/Oの利用率の確認を行うことができます。
I/Oがボトルネックの場合
では、I/O待ちがボトルネックとなっている場合について、次に何を行うべきでしょうか?
それは、「スワップ発生の確認」です。
メモリの使用量が高くなった場合、スワップが発生し、ディスクへのアクセスが行われます。
ディスクへのアクセスは、メモリのそれに比べて時間が掛かるため、I/Oに時間が掛かることになるのです。
スワップが発生しているかどうかは、freeコマンドで確認できます。
これはシステム全体のメモリの使用量を確認できます。
ここでSwapのusedに数値が入っていた場合、スワップが発生していることがわかります。
スワップが発生したら
スワップが発生した場合には、メモリの使用量の調節を行うことが必要です。
topコマンドで、メモリを多く使用しているプロセスを確認し、
メモリ使用量を減らすことができないか
できなければ、メモリを増設するべきか
など、スワップを発生させないようなメモリ管理を行いましょう
スワップが発生していない場合
スワップが発生していないにも関わらず、I/Oがボトルネックとなっている場合には、I/Oの頻度が高く、処理が追いついていないことが考えられます。
このような場合にはpidstat -dで、I/Oの負荷が高いプロセスを確認した上
I/O頻度を減らす
メモリを増やし、キャッシュの使用を多くする
などで、I/Oの負荷を低くするような対策を取りましょう
復習
では、最後にもう一度、確認プロセス全体について復習しておきましょう!
ロードアベレージが高くなっているか確認
ロードアベレージが低い場合
- ソフトウェアの設定や不具合、ネットワーク、リモートホストを確認
ロードアベレージが高い場合
CPU・I/Oのいずれがボトルネックかを探る
CPUに原因がある場合
- ユーザープログラム・システムプログラムのいずれが原因かを探る
- 原因となっているプロセスを特定する
I/Oに原因がある場合
- スワップが発生していないか、確認する
- 原因となっているプロセスを特定する
最後に
以上、簡単に負荷の調べ方やその対策について説明しましたが、調べれば調べるほど奥が深く(見るべき内容が多く)、また基準値などもはっきりとしないため、難しい課題だなと思います。
自分で調べることはなるべく調べた上で、わからない場合にはプロフェッショナルに相談することも必要だと感じました。
幸い弊社には素晴らしいSREチームがありますので、相談・協力しながら運用していこうと思います。