先日、自社のバッチサーバがCPUの閾値90%を超え、たくさんのアラートが飛んできたので、原因を調査する機会がありました。
そんな中、調査する上で使用したのが、topコマンドになります。
しかし、調査時にtopコマンドを打ったはいいけど、
「どのように見ればいいんだっけ」
となってしまったため、今回はtopコマンドについて備忘をかねて改めて整理していきたいと思います。
ちなみに、topコマンドは
Load Average、CPU、メモリ、プロセスなどを組み合わせて、「何が原因でサーバーが重いのか」を切り分けるためのコマンド
として使うと、非常に便利なコマンドです。
1. topコマンドとは
簡単にいうと、
どのプロセスが重いかを調べる時に使用するコマンド
になります。
top
を実行すると、サーバーの現在の状態がリアルタイムで表示されます。
例えば、
top - 10:20:30 up 120 days, 3:21, 2 users, load average: 8.20, 6.50, 4.30
Tasks: 250 total, 2 running, 248 sleeping, 0 stopped, 0 zombie
%Cpu(s): 85.0 us, 8.0 sy, 2.0 ni, 3.0 id, 2.0 wa
MiB Mem : 32000 total, 4000 free, 18000 used, 10000 buff/cache
下にはプロセス一覧も表示されます。
PID USER %CPU %MEM COMMAND
1234 oracle 650.0 15.0 oracle
5678 java 80.0 8.0 java
その中でもまずは、
- Load Average
- CPU使用率
- メモリ
- CPUを大量消費しているプロセス
を見るのがおすすめです。
2. Load Averageを見る
topで特に重要なのが、
load average: 8.20, 6.50, 4.30
です。
これは、
1分平均 / 5分平均 / 15分平均
のLoad Averageを表しています。
一言でいうなら、
Load Average = CPUで実行中、またはCPU・I/Oなどの処理を待っているタスク数の平均
となります。
ここで注意したいのが、
Load Average = CPU使用率ではない
ということです。
上記の例だと、
- 1分平均:CPUが8.20個程度の負荷を備えている状態
- 5分平均:CPUが6.50個程度の負荷を備えている状態
- 15分平均:CPUが4.30個程度の負荷を備えている状態
という意味になります。
つまり、
「直近1分では8コア分くらいの仕事をした」ではなく、「直近1分では、平均して8.2程度のタスクがCPUなどの実行を待つ状態にあった」
ということになります。
Load Averageには、CPUを実行したくて待っているタスクだけでなく、I/O待ちなどの状態も関係するみたいです。
そのため、
CPU使用率:20%
Load Average:10
のようなケースもあります。
また、Load AverageはCPUコア数とセットで見ることが重要です。
例えば8コアのサーバーで、
Load Average:2
なら比較的余裕があると考えられます。
一方、
Load Average:20
なら、多くのタスクがCPUやI/Oなどを待っている可能性があります。
ただし、
Load AverageがCPUコア数を超えた=必ずCPU不足
ではありません。
CPU使用率やI/O Waitなどと組み合わせて判断する必要があります。
3. CPU・メモリから何が起きているか考える
次に確認したいのがCPUです。
%Cpu(s): 85.0 us, 8.0 sy, 2.0 ni, 3.0 id, 2.0 wa
特に覚えておきたいのは以下です。
| 項目 | 意味 |
|---|---|
us |
ユーザープロセスがCPUを使用 |
sy |
カーネルがCPUを使用 |
id |
CPUがアイドル |
wa |
I/O待ち |
例えば、
us = 90%
なら、アプリケーションやDBなどのプロセスがCPUを大量に使用している可能性があります。
一方、
wa = 70%
なら、CPUそのものよりもディスクなどのI/Oがボトルネックになっている可能性があります。
つまり、
「CPUが高い」という現象だけを見るのではなく、CPUを何に使っているのかを見る
ことが重要です。
メモリについては、
MiB Mem : 32000 total, 4000 free, 18000 used, 10000 buff/cache
などを確認します。
Linuxでは空いているメモリをキャッシュとして利用するため、free が少ないだけで即「メモリ不足」と判断しないことも重要です。
4. プロセスから原因を絞り込む
CPU使用率が高い場合は、下のプロセス一覧を確認します。
PID USER %CPU %MEM COMMAND
1234 oracle 650.0 15.0 java
5678 java 80.0 8.0 java
この例では、OracleのプロセスがCPUを大量に使用しています。
ここで、
サーバーが重い
↓
CPU使用率が高い
↓
OracleプロセスのCPU使用率が高い
↓
PIDを特定
と、少しずつ原因を絞り込んでいきます。
なお、マルチコア環境では %CPU が100%を超えることがあります。
例えば、
%CPU = 400%
なら、単純化すると4コア分程度のCPUを使用していると考えられます。
プロセスを特定したら、そのPIDを起点にさらに調査できます。
5. 実務ではtopをどう使うのか
例えば、実際の業務で
「画面のレスポンスが遅い」「サーバーが重い」
という事象が発生したとします。
まず top を確認し、
Load Average が実コア数と比較して高い
CPU使用率 が90%以上
↓
%us が高い
↓
特定のOracleプロセスがCPUを大量消費
ということが分かったとします。
ここからさらにOracle側を調査し、
PID
↓
Oracleセッション
↓
SQL
↓
実行計画
と追っていき、
例えば、特定のSQLが大量のデータを読み込み、ORDER BY による大量のソートを行っていたとします。
すると、
SQLの処理量増加
↓
OracleプロセスのCPU使用率上昇
↓
サーバーCPU使用率上昇
↓
Load Average上昇
↓
アプリケーションのレスポンス悪化
という因果関係が見えてきます。
このように top は、
「サーバーが重い」という現象を、プロセスやアプリケーション、さらにはSQLまで掘り下げていくための入口
として非常に役立ちます。
また、普段からCPUやメモリの使用率を把握しておけば、
「現在のリソースに余裕があるのか」
「今後サーバーのスペックアップが必要なのか」
といったキャパシティプランニングにもつなげられます。
ただし、CPU使用率が高いからといって、すぐにCPUを増やすとは限りません。
キャパプラを考える上では、まずSQLチューニングなどによって処理そのものを改善できる場合もあるため、「リソース不足」なのか「処理が非効率」なのかを切り分けることが重要となります。
まとめ
topを見るときは、個々の数字を暗記するよりも、次の流れで考えると分かりやすいです。
① Load Averageを見る
↓
② CPU / メモリ / I/Oの状況を見る
↓
③ 負荷の高いプロセスを特定する
↓
④ PIDを起点にアプリケーションやDBを調査する
↓
⑤ SQLなど、さらに上位の原因を調査する
特に重要なのは、
topは「CPU使用率を見るコマンド」ではなく、「サーバーで何が起きているのかを切り分けるためのコマンド」
と考えることです。
今回は、改めてポイントを記事に落とし込むことで頭の中を整理できたため、非常に良い学びだったと感じます。