10年ほど前、エンジニア駆け出しの頃のブログを再認識兼ねてリバイバルします。
最近はサーバにsshで繋いで確認すると言う機会も減りましたが、覚えておいて損はないです。
https://itinao.hatenadiary.org/
ある日の出来事
エンジニア成り立ての僕。
出勤して早々、キラキラな営業さんや企画の方からこんなこと言われます。
営業「ちょっとなんかサーバが重いんだけど」
企画「なんとかして!仕事にならないよ」
僕「やべ、調査の仕方わからへん。」
僕「すみません。先輩にすぐ連絡します。」
プログラマーの僕はインフラ側の知識、知見が足りてません。
なんとかしたいけど、どうすることもできず。。
自社サービス運用していると良くある光景ですね。
やっぱりなんとかしたい!
報連相は大切だけどやっぱりエンジニア。
自分でなんとか出来るようになりたいと思いますよね。
そんな方へ。まずはボトルネックの考え方を学びましょう。
ボトルネックの考え方は大きく2つ
1. CPU負荷
2. I/O負荷
1. CPU負荷ってなんぞ?
あるプロセス(プログラム)がCPUを使い使用率100%の状態が長く続いてしまった場合、他のプロセスの実行を妨害してしまいます。
一つ語弊があると困りますが、CPU使用率100%自体は悪ではなく、ディスクやメモリ容量などの他にボトルネックがなければ理想的な状態です。
CPU100%が急に続くようであれば
プログラムが暴走(無限ループ等)していないか確認する。
直近のリリースバージョン内の処理を見直す。
2. じゃCPU負荷とI/O負荷の違いは?
I/Oとは入出力(Input/Output)の意味です。
頻繁にデータを出し入れすることにより、ハードウェアやネットワークに負荷がかかることで、CPU負荷とI/O負荷は別物です。CPU負荷が高いからと言って必ずしもI/Oが遅くなるわけではなく、あくまでもディスクへ大量の読み書きが発生している状態です。
I/O負荷が続くようであれば
ファイルに入出力ようなプログラムが多くないか?
メモリ不足でスワップが発生してディスクアクセスが発生していないか?
メモリが足らないとシステムはスワップを使います。
逆に言うとスワップに対してのアクセスが多い場合はメモリ不足の可能性があります。
ボトルネック調査手順
ここまでCPU負荷とI/O負荷の概念を見てきました。
次に早速、CPU負荷とI/O負荷についてのボトルネックの調査方法に入っていきます。
1. まずは心を落ち着かせます。これ大事。
2. topでロードアベレージを確認します。
3. sarでCPUとI/O負荷どちらが高いか確認します。
4. psで各プロセスの情報を見ます。
5. 実行プログラムの見直しやバージョンを戻すなどの対応をします
6. 途中でとめて問題ない場合は悪さをしているプロセスをkillしたり再起動します。
1. まずは心を落ちつかせる
これはどんな時も大切です。
周りに早くなんとかしろと言う視線が痛いですが、パニックになってはいけません。
太々しいほど落ちつき対応をしましょう。
2. すぐにTOPコマンド
とにかくまずはTOPコマンドでロードアベレージを見ましょう。
ロードアベレージとは
1CPUにおける単位時間あたりの実行待ちとディスクI/O待ちのプロセスの数。
単位時間当たりにどの程度のタスクが待ち状態にあったかを報告する数値です。
これが高いとシステムへの負荷が高いということです。
ロードアベレージが高いとは
コア数よりロードアベレージが高ければ負荷の原因になる可能性があります。
$top
top - 00:41:49 up 6 days, 2:24, 1 user, load average: 2.15, 3.02, 3.20
Tasks: 93 total, 1 running, 45 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.0 us, 0.2 sy, 0.0 ni, 99.8 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 3977928 total, 3324844 free, 121568 used, 531516 buff/cache
KiB Swap: 0 total, 0 free, 0 used. 3630656 avail Mem
load average: 2.15, 3.02, 3.20という表示がロードアベレージです。
左から直近1分, 5分, 15分間の値です。
見るべきものは以下2つ
load averageの状態がコア数を超えてないか。
Swapは発生していないか。
次にコアごとの負荷状況を見て行きましょう。
2. sarコマンドでCPU使用率とI/O待ち率を見る
マルチコアの場合ロードアベレージだけでは判断がつかないことがあります。
そんなときは合わせてsar -P ALLで各CPUの状態を個別に把握しましょう。
マルチCPUが搭載されていてもディスクは1つしかない場合、CPU負荷は他のCPUに分散できてもI/Oは分散できないため負荷原因となります。
$ sar -P ALL
Linux 3.10.0-862.2.3.el7.x86_64 (118-27-1-88) 10/01/2018 _x86_64_ (2 CPU)
01:17:35 AM CPU %user %nice %system %iowait %steal %idle
01:17:36 AM all 0.00 0.00 0.00 0.00 0.00 100.00
01:17:36 AM 0 0.00 0.00 0.00 0.00 0.00 100.00
01:17:36 AM 1 0.00 0.00 0.00 0.00 0.00 100.00
それぞれの意味はこちらになります。
表示 | 説明 |
---|---|
%user | CPUがユーザモードにあった時間の割合 |
%system | CPUがカーネルモードにあった時間の割合 |
%iowait | CPUがIO待ちをしていた時間の割合 |
%idle | CPUがアイドル状態にあった時間の割合 |
見るべきものは以下
%idleが小さいとCPUの使用率が高いのでCPUがボトルネックになっている可能性があります。
CPUに割り当てられるプロセスの状態遷移をpsコマンドで確認
CPUが負荷の原因とわかった場合は
次にどのプロセスが悪さをしているのかを把握しましょう。
$ ps auwx | head
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.1 19232 1516 ? Ss Feb09 0:00 /sbin/init
root 2 0.0 0.0 0 0 ? S Feb09 0:00 [kthreadd]
root 3 0.0 0.0 0 0 ? S Feb09 0:00 [migration/0]
root 4 0.0 0.0 0 0 ? S Feb09 0:00 [ksoftirqd/0]
root 5 0.0 0.0 0 0 ? S Feb09 0:00 [stopper/0]
root 6 0.0 0.0 0 0 ? S Feb09 0:06 [watchdog/0]
root 7 0.0 0.0 0 0 ? S Feb09 0:00 [migration/1]
root 8 0.0 0.0 0 0 ? S Feb09 0:00 [stopper/1]
root 9 0.0 0.0 0 0 ? S Feb09 0:00 [ksoftirqd/1]
それぞれの意味は下記を参照ください。
表示 | 説明 |
---|---|
%CPU | プロセスのCPU使用率 |
%MEM | プロセスの物理メモリ |
VSZ(RSS) | プロセスが確保している仮想(物理)メモリ領域 |
STAT | プロセスの状態 |
TIME | プロセスがCPUを占有した時間 |
STAT(プロセスステータス)について
CPU上で実行可能なプロセスはTASK_RUNNING状態になっています。
複数あるTASK_RUNNING状態のプロセスのうち最も高いプライオリティを持つタスクにCPUが与えられます。
表記 | 状態 | 説明 |
---|---|---|
R | TASK_RUNNING | 実行可能状態 |
S | TASK_INTERRUPTIBLE | 待ち状態。シグナル受信可能 |
D | TASK_UNINTERRUPTIBLE | 待ち状態。シグナル受信不可 |
Z | TASK_ZOMBIE | ゾンビ状態。exit後の状態 |
T | TASK_STOPPED | サスペンド状態 |
見るべきものは以下2つ
RSSのサイズを見て極端に大きなプロセスがないか確認する。
TIMEの状態をみます。無限ループ(TASK_RUNNING)の場合、TIMEが増加し続けます。
スワップが発生している場合
TOPコマンドでスワップが発生している場合には物理メモリ不足が原因となる可能性があります。
sarコマンドでさらに細かくみていきます。
$ sar -S
00時00分01秒 kbswpfree kbswpused %swpused kbswpcad %swpcad
00時10分01秒 2097148 0 0.00 0 0.00
00時20分01秒 2097148 0 0.00 0 0.00
00時30分01秒 2097148 0 0.00 0 0.00
00時40分01秒 2097148 0 0.00 0 0.00
状態 | 説明 |
---|---|
kbswpfree | スワップ領域の空き容量 |
kbswpused | スワップ領域の使用容量 |
%swpused | スワップ領域の使用量割合 |
kbswpcad | スワップ領域のキャッシュ容量 |
こちらでどの程度Swapが発生しているのか確認した上、
vmstatでvmstat 1 100 のようにインターバルを指定して見るとわかりやすい
$ vmstat 1 5
procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu------
r b swpd free buff cache si so bi bo in cs us sy id wa st
3 1 244208 10312 1552 62636 4 23 98 249 44 304 28 3 68 1 0
0 2 244920 6852 1844 67284 0 544 5248 544 236 1655 4 6 0 90 0
1 2 256556 7468 1892 69356 0 3404 6048 3448 290 2604 5 12 0 83 0
0 2 263832 8416 1952 71028 0 3788 2792 3788 140 2926 12 14 0 74 0
0 3 274492 7704 1964 73064 0 4444 2812 5840 295 4201 8 22 0 69 0
表示 | 説明 |
---|---|
r | 実行待ちプロセス数 |
b | スリープ(割り込み可能)のプロセス数、実行できてないプロセス数 |
swpd | スワップサイズ(KB) |
free | 空きメモリ(KB) |
buff | バッファメモリサイズ(KB) |
cache | キャッシュメモリサイズ(KB) |
si | ディスクからスワップインされているメモリサイズ(KB/秒) |
so | ディスクへスワップアウトされているメモリサイズ(KB/秒) |
bi | ブロックデバイスから受け取ったブロック数(ブロック/秒) |
bo | ブロックデバイスに送られたブロック数(ブロック/秒) |
in | 割り込み回数/秒 |
cs | コンテキストスイッチ回数/秒 |
us | ユーザプロセスのCPU使用時間割合 |
sy | カーネルコードの実行に使用した時間 |
id | CPUがアイドル状態の時間割合 |
wa | CPUがI/O待ち |
st | ゲストOSがCPUを割り当てられなかった時間の割合 |
r、bは通常は0~2程度。
この数値が大きい場合サーバ重いと感じる可能性があります。
si、soは常時ゼロが基本。
ここに常時数値が現れることはメモリ不足か、メモリを食ってしまうプログラムがあるのどちらかです。
負荷対策まとめ
まずはCPUかI/Oかを以下のコマンドで判断する
top
sar
ps
vmstat
対処法としては
CPU負荷が高い場合
サーバ増設やプログラムのロジック、アルゴリズムの改善
I/O負荷が高い場合
メモリ増設でキャッシュ領域を拡大する
メモリ増設不可なら、データの分散やキャッシュサーバの導入を検討
プログラムの改善でI/O頻度を軽減する
ふう、まとめるの疲れました。
これで負荷の原因を説明できるようになったら良いな。