概要
CentOSでシステムのボトルネックを調査する時の問題切り分け方法の自分メモ。
前提
- カーネルモードでCPUが使われるのは、
割り込み
、システムコール
、カーネルスレッド
ロードアベレージとは
- CPUの実行権限が与えられているのを待っているタスク
- ディスクI/Oが完了するのを待っているタスクの
2つの状態のプロセスの数
切り分けフロー
- LA高いか?
- 低い
- ネットワークなどがボトルネックになっているかも。muninなど、NWに関するグラフを見ると帯域が圧迫しているなどありえる
- OSの設定などがボトルネック。カーネルのsynパケットの受付数が低いなど。
- アプリケーション、OSのログ、各種ログを見ることが大事
- 低い
↓
LA高い場合
-
vmstatで負荷の特徴把握
↓ -
CPU負荷 or IO負荷 どちらか
- cpu負荷: us列, sy列 が高い
- IO負荷: b列をみる。IO列は低くてもIOが高い場合がるので注意
↓
- CPU負荷の場合
- システム空間での負荷(system列多い)
- 割り込み調査
- システムコール調査
- カーネルスレッド調査
- ユーザー空間での負荷(user列多い)
- アプリケーション調査
- システム空間での負荷(system列多い)
- IO負荷の場合
- スワップ
- メモリ沢山使用しているプロセスを調査
- IO量
- iostatでボトルネックがディスクなのか、ディスクより上のシステムコール層、VFS層、ファイルシステム層なのかを調査
- スワップ
詳細
LAが高いか?
-
uptime
,sar -q 1
などでLAを把握
vmstat、その前に
-
mpstat -P ALL 1
などで各コアでの状況を確認したほうがよい。コアで分散すれば解決するような問題もある。 - システムログも大事(dmesg | tail)
- oomkillerやパケットのエラーなどでている場合がある様子。エラーは使用率や飽和などを端的に表しているのでやはりログのエラーは大事。
vmstatで負荷の特徴を把握する
vmstat -S m 1
procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
0 0 17 5064 275 204 0 0 3 154 11 16 0 1 96 3 0
0 0 17 5064 275 204 0 0 0 580 1255 329 1 2 87 10 0
特徴無し
- muninなども含めてシステムに異常がない場合は、監視の閾値上げても良いかも
waが高い
- IO負荷調査へ
syとwaが高い
- IO負荷調査へ
syだけ高い場合(システム空間での負荷)
-
top
などでどのプロセスがCPUを使っているか特定しておく - waが小さくてもIO負荷ありえるので、IO負荷もありうる。IO待ちメモ
- システムの他の箇所(前提より、
割り込み
、システムコール
、カーネルスレッド
)のどれかでCPU沢山使っている- 割り込み調査
-
vmstat
のcs,inが多い -
systemtap
、perf
で割り込みの種類を特定する。その割り込み毎に対応する。
-
- システムコール調査
-
strace -c -tttT -p
してシステムコールのレイテンシ、頻度を計測。怪しいシステムコールを把握する。 - システムコールの先を
systemtap
、perf
で調査。関数まで特定する。カーネルソース読んで静的解析。
-
- カーネルスレッド調査
-
systemtap
,perf
で調査。関数まで特定する。カーネルソース読んで静的解析。
-
- 割り込み調査
- システムの他の箇所(前提より、
us高い(ユーザー空間での負荷)
- プロセスのログをみる。apacheならアクセスログなど、変なIPなどないかなどなど。
-
top
などでどのプロセスがCPUを使っているか特定してしてpsatck
を何回か打ってユーザースタックを確認することでアプリケーションがどの処理で何をしているのかを把握する。ただアプリケーションのシンボル情報がない場合が多いはずなので関数名は16進数表示になっているかも。カーネルの関数やなぜか共有ライブラリの関数はわかるはずなのでそこからなんとかする
IO負荷高い場合
スワップを疑う
-
vmstatの
swpd、free
でスワップの状況を把握 - メモリを消費しているプロセス特定
ps aux --sort -rss
IO量が多いかどうか
-
iostat
で調査- IOPS(r/s + w/s)が増え、await(1回のI/Oに要する時間)が増える、(avgqu-sz)キューも増えている場合
- IOが増えた原因はなにかを調査する必要あり
-
iotop
でプロセス特定 - アクセスログ、重いクエリ、などなどアプリの観点で調査
-
- IOが増えた原因はなにかを調査する必要あり
- 平均 I/O サイズ(avgrq-sz)が変わらないのにサービスタイム、1回のI/Oに要する時間 (ミリ秒)(svctm)が大きくなった場合
- I/O性能が劣化しており、ストレージに問題がありそう
- ストレージがボトルネックになっていない場合
- それより上のシステムコール層、VFS層、ファイルシステム層を調査
-
strace -cttT -p
でIOに関するシステムコールのレイテンシを測定。時間が通常よりかかっていればディスクより上層が怪しい。レイテンシが小さいのであればストレージもそれより上層も怪しくない。 - ここでも深く調べるには
systemtap
,perf
。そう、カーネルソースまで追ってボトルネックになっている関数を特定する。
-
- それより上のシステムコール層、VFS層、ファイルシステム層を調査
- IOPS(r/s + w/s)が増え、await(1回のI/Oに要する時間)が増える、(avgqu-sz)キューも増えている場合
iostatのカラムの見方
r/s: 秒間の読み込み回数
w/s: 秒間の書き込み回数
avgrq-sz: 平均 I/O サイズ
avgqu-sz: 平均待ち行列長
await: レスポンスタイム。I/O を実施していない待ち時間を含む。
svctm: サービスタイム。1回のI/Oに要する時間 (ミリ秒)。
%util: 使用率(ビジー率)
メモ
IOのレスポンスが悪いかどうか
- iotopなどで怪しいプロセスを発見、
strace -cttT -p
してIO関連システムコールのレイテンシを計測する。 - レイテンシが大きかったらiostatでどこがボトルネックになっているのはディスクなのか、それより上位なのか切り分ける。最初からiostatで切り分ければよいのかも
VFS層、ブロック層
システムコール
↓
---------------------------------------------
(VFSレイヤー)
VFS
↓
ファイルシステム ← → ディスクキャッシュ
---------------------------------------------
↓
---------------------------------------------
(ブロックレイヤー)
IOスケジューラ → デバイスドライバ
---------------------------------------------
↓
ディスクコントローラ
↓
物理ディスク
まとめ
- システム空間で負荷がある場合、深く調べるには上記で度々できているsystemtap、perfなどのLinuxツールでボトルネックになっている関数まで特定するしかなさそう。そしてソースを呼んで静的に解析。対策実施。
- 自分で根本原因まで特定しようとしたいならば、最後はカーネルソースに辿り着くことがありそう。そして、システムの状況とコードを結びつけてなんとか原因を推定してチューニングを実施する。自分でここまでできるのがオープンソースのよいところ。
- perf使ってみた