dshimizu/blog

アルファ版

Linux系OSのサーバ負荷の原因を調査する

はじめに

サーバが高負荷となっている場合に、何がボトルネックとなっているか原因を特定して適切に対処することはシステムの管理者にとっては重要です。
しかしながら、一口にボトルネックを特定するといっても容易ではなく、トラブルが発生している最中に原因を突き止め、適切な対処をするには負荷や調査方法についてきちんと理解しておく必要がありますし、システム全体としての負荷を調査/特定するには、OSだけではなく、HWの仕組みや動作しているアプリケーションやミドルウェア、ネットワークなどの様々な知識も必要になるかと思います。

ここではその足掛かりとして、単一のLinux系OSに焦点を当てて、負荷とその調査方法について簡単にまとめてみました。

環境


環境は以下のとおりです。

プラットフォーム さくらのVPS(1G SSDモデル)のKVMゲストOS
OS CentOS 6.3 x86_64 (64bit)
カーネルバージョン 2.6.32-279.19.1.el6.x86_64

 

Linux系OSの負荷とその調査手法

Linux系OSの負荷とは


一般的に、Linux系OSでの負荷と呼ばれるものには大きく以下の2つに分類されます。

  • CPU負荷
  • ディスクへのアクセスは基本的に発生せず、CPUの計算速度に依存する処理による負荷
  • I/O負荷
  • ディスクへデータを保存したり、保存されたデータを取り出したりするような、ディスクへのアクセス(読み書き)速度に依存する処理による負荷

Linux系OSは異なる複数のタスクを同時に実行することができるマルチタスクに対応しているため、CPUやメモリ、ハードディスクといったマシンに搭載されいるHWリソースを、それ以上の数のタスクで共有して処理されています。厳密には、実行される複数のタスクそれぞれを極短い間隔で切り替えながら順次処理を行っています(下記のリンク先に記載されている図がわかりやすいかと思います)。

Linux系OSにおける負荷とは、複数のタスクを同時に実行することによって生じる、そのマシンに搭載されている有限なHWリソースの空き待ちが発生している状態となります。このタスクの処理待ちとなる動作原理を理解することが、負荷を理解することにつながると思います。

プロセスの状態遷移


Linux系OSにおける負荷を知る上ではプロセスの状態遷移について知ることも重要です。

プロセスとは

プロセスとは、OSによって実行されているプログラムの単位を指します。そのプログラムの実行に必要なメモリ領域や実行に必要なファイルなどの情報を持っています。

一般的なプロセスの状態は以下の3つに分けられます。

状態 説明
Ready CPUがあれば実行できる
Running CPUが割り当てられ、実行中
Blocked (waiting) I/O完了待ち、ネットワークやユーザからの入力待ち。


Linux系OSから見たプロセスの状態にはもう少し細分化され、以下のようなものがあります。
カーネルのコードを詳しく読むことはできないですが、プロセスの状態は以下のコードに定義されています。

    • /usr/src/kernels/2.6.32-279.19.1.el6.x86_64/include/linux/sched.h

/*
* Task state bitmask. NOTE! These bits are also
* encoded in fs/proc/array.c: get_task_state().
*
* We have two separate sets of flags: task->state
* is about runnability, while task->exit_state are
* about the task exiting. Confusing, but this way
* modifying one set can't modify the other one by
* mistake.
*/
#define TASK_RUNNING 0
#define TASK_INTERRUPTIBLE 1
#define TASK_UNINTERRUPTIBLE 2
#define __TASK_STOPPED 4
#define __TASK_TRACED 8
/* in tsk->exit_state */
#define EXIT_ZOMBIE 16
#define EXIT_DEAD 32
/* in tsk->state again */
#define TASK_DEAD 64
#define TASK_WAKEKILL 128
・・・
一般的な状態 Linux系OSでの状態 psから報告される値 説明
実行中状態(Running) TASK_RUNNING R 実行中状態。CPUが割り当てられていて、今まさに実行している。
実行可能状態(Ready) TASK_RUNNING R 実行可能状態。CPUの割り当てを待っている状態で、CPUが空けば実行できる。
待ち状態(Blocked) TASK_INTERRUPTIBLE S 割り込み可能な待ち状態。ユーザや他のプロセスからの入力を待っている。
TASK_UNINTERRUPTIBLE D 割り込み不可能な待ち状態。ディスク入出力などの完了を待っている。
__TASK_STOPPED, __TASK_TRACED T SIGSTOP,SIGTSTP,SIGTTIN,SIGTTOUといったシグナルを受け取って中断しているか、デバッグの対象になっている。
TASK_DEAD Z 既に終了していて、終了処理の完了を待ってる。


プロセスの状態遷移
プロセスの状態は基本的に以下のような形で遷移します。似たような図が様々な書籍等に記載されているのでご存知の方も多いと思います。プロセスは以下のように状態遷移をしながら、プログラムの計算をしたりディスクへの入出力(I/O)を行ったりします。

負荷を調査する


Linux系OSの負荷が大きいと思われる場合、以下の作業を行います。

  1. ロードアベレージを確認する
  2. CPU使用率/IO待ちの状態を確認する

OSのリソース使用状態を確認するコマンドは多々ありますが、topコマンドやvmstatコマンド、iostatコマンド、Sysstatというシステムリソースの使用状況データを収集するパッケージに含まれるsarというコマンドが用いられることが多いと思います。これらは時間とともに値の推移を追える点や、オプションを利用することで様々な情報を確認できる点が便利だと思います。各コマンドを状況に応じて使い分けていただくと良いと思います。
Unix系OSや別のLinuxディストリビューションによって実行コマンドや出力結果等が異なります。

Sysstatはyumコマンドでパッケージをインストールできます。


# yum install systat

 

ロードアベレージを確認する


ロードアベレージの値はtopコマンドやuptimeコマンド、sarコマンドの-qオプションで確認できます。プロセスの状態も同時に出力できるtopコマンドを用いるのが良いかと思います。 以下はapache benchを実行してみたときのtopの出力結果です。

topコマンドの出力結果
※右上の"load average"項目で確認できます。


% top
top - 00:30:26 up 73 days, 10:36, 4 users, load average: 0.05, 0.05, 0.16
Tasks: 135 total, 1 running, 130 sleeping, 4 stopped, 0 zombie
Cpu(s): 0.1%us, 0.0%sy, 0.0%ni, 99.9%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 1020660k total, 556304k used, 464356k free, 208480k buffers
Swap: 1048568k total, 13096k used, 1035472k free, 101924k cached

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1 root 20 0 19228 520 340 S 0.0 0.1 0:04.78 init
2 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kthreadd
3 root RT 0 0 0 0 S 0.0 0.0 0:01.61 migration/0
4 root 20 0 0 0 0 S 0.0 0.0 3:49.98 ksoftirqd/0
5 root RT 0 0 0 0 S 0.0 0.0 0:00.00 migration/0
6 root RT 0 0 0 0 S 0.0 0.0 0:06.85 watchdog/0
7 root RT 0 0 0 0 S 0.0 0.0 0:03.50 migration/1
8 root RT 0 0 0 0 S 0.0 0.0 0:00.00 migration/1
9 root 20 0 0 0 0 S 0.0 0.0 123:25.85 ksoftirqd/1
10 root RT 0 0 0 0 S 0.0 0.0 0:06.78 watchdog/1
11 root 20 0 0 0 0 S 0.0 0.0 4:41.19 events/0
12 root 20 0 0 0 0 S 0.0 0.0 2:59.66 events/1
13 root 20 0 0 0 0 S 0.0 0.0 0:00.00 cgroup
14 root 20 0 0 0 0 S 0.0 0.0 0:00.00 khelper
15 root 20 0 0 0 0 S 0.0 0.0 0:00.00 netns
16 root 20 0 0 0 0 S 0.0 0.0 0:00.00 async/mgr
17 root 20 0 0 0 0 S 0.0 0.0 0:00.00 pm
18 root 20 0 0 0 0 S 0.0 0.0 0:18.44 sync_supers
19 root 20 0 0 0 0 S 0.0 0.0 0:20.86 bdi-default
20 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kintegrityd/0
21 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kintegrityd/1
22 root 20 0 0 0 0 S 0.0 0.0 0:16.31 kblockd/0
23 root 20 0 0 0 0 S 0.0 0.0 0:01.94 kblockd/1
24 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kacpid
25 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kacpi_notify

uptimeコマンドの出力の結果

% uptime
02:05:39 up 8 days, 11:36, 5 user, load average: 4.48, 4.54, 3.24

sarコマンドの-qオプション出力結果

% sar -q 1 10
Linux 2.6.32-279.19.1.el6.x86_64 (www4242gi.sakura.ne.jp) 2013年03月05日 _x86_64_ (2 CPU)

00時26分04秒 runq-sz plist-sz ldavg-1 ldavg-5 ldavg-15
00時26分05秒 0 142 0.07 0.05 0.21
00時26分06秒 0 142 0.14 0.07 0.22
00時26分07秒 0 142 0.14 0.07 0.22
00時26分08秒 0 142 0.14 0.07 0.22
00時26分09秒 0 142 0.14 0.07 0.22
00時26分10秒 0 142 0.14 0.07 0.22
00時26分11秒 0 142 0.13 0.07 0.21
00時26分12秒 0 142 0.13 0.07 0.21
00時26分13秒 0 142 0.13 0.07 0.21
00時26分14秒 0 142 0.13 0.07 0.21
平均値: 0 142 0.13 0.07 0.21

※sar -qの各出力項目


runq-sz :ランキューに溜まっているプロセス数(実行待ちプロセス数)
plist-sz :実行中プロセス・スレッド数
ldavg-1 :ロードアベレージ(1分間の平均値)
ldavg-5 :ロードアベレージ(5分間の平均値)
ldavg-15 :ロードアベレージ(15分間の平均値)

ロードアベレージで示される数値は、"処理を実行したいが、何らかの原因で実行できずに待ち状態となっているのプロセス数の1分、5分、15分の平均値"になります。
ここでいう待ち状態のプロセスとは、TASK_RUNNING状態となっている実行中、および実行可能状態となっているCPU空き待ちのプロセスと、TASK_UNINTERRUPTIBLE状態でディスク入出力待ちとなっているプロセスの合計になります。TASK_INTERRUPTIBLE状態のプロセスは、基本的にHWリソースに依存せずプログラム自身が自ら処理を待っている状態となるので、ロードアベレージには含まれません。
ロードアベレージの値は、HWから定期的に送られる"タイマ割り込み"と呼ばれる信号をCPUが受け取った際に計算されて取得されます。

プロセスが実行待ちとなっている原因は以下の2つになります。

  • 他のプロセスの処理にCPUが使われているため、別のプロセスがその処理が終了するのを待っている状態(CPU負荷)
  • ディスクへの読み書き要求を発行して、その結果を待っている状態(I/O負荷)

重要なのは、"ロードアベレージの値だけでは、CPU負荷なのか、I/O負荷なのかを区別できない"ということです。したがってロードアベレージが高い場合、CPU負荷なのか、I/O負荷なのかの切り分けを行う必要があります。
なお、ロードアベレージが低いのにスループットが上がらない場合、ネットワーク面での問題(パケットロスなど)や実行中のアプリケーションの問題が疑われます。

CPU使用率とIO待ち状態の確認



ロードアベレージの値を確認後、CPUやI/Oの状況を確認していくことになります。
実際にはほとんど同時に確認することになると思います。

実行中のプロセスとそれに伴うCPUの使用率を確認するには"top"コマンドを利用します。 CPU使用率の詳細や時間推移を確認する場合には"sar"コマンドで"-u"オプションを、さらにCPUのコア数ごとの使用率とその時間推移を確認する場合には"-P"オプションを利用します。

以下はApache Benchを実行した際の各コマンドの出力結果になります。

topコマンドの出力結果
※キーボードの「1」を押下すると下記のようにコア数ごと(ここでは3-4行目にCpu0,Cpu1)の使用率が表示されます。


% top
top - 21:19:56 up 19 days, 22:55, 3 users, load average: 4.51, 4.37, 3.15
Tasks: 436 total, 16 running, 414 sleeping, 0 stopped, 6 zombie
Cpu0: 51.2%us, 31.1%sy, 0.0%ni, 1.0%id, 0.7%wa, 1.2%hi, 14.9%si, 0.0%st
Cpu1: 44.1%us, 24.6%sy, 0.0%ni, 24.6%id, 3.2%wa, 2.1%hi, 1.4%si, 0.0%st
Mem: 514912k total, 495328k used, 19584k free, 28152k buffers
Swap: 1048568k total, 19412k used, 1029156k free, 167012k cached

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
18284 test 17 0 21144 10m 1784 R 47.0 2.2 0:11.22 ab
17181 test 16 0 11244 2996 1492 R 12.9 0.6 2:51.51 pgbench
17187 postgres 15 0 51940 24m 23m S 1.7 4.9 0:08.48 postmaster
17410 apache 15 0 0 0 0 Z 1.7 0.0 0:00.10 httpd
17602 apache 15 0 23776 4088 1056 S 1.7 0.8 0:00.09 httpd
17195 postgres 15 0 51940 24m 23m S 1.3 4.9 0:08.57 postmaster
17198 postgres 15 0 51944 24m 23m S 1.3 4.9 0:08.38 postmaster
17205 postgres 15 0 23776 4088 1056 S 1.3 0.8 0:00.06 httpd
17496 apache 15 0 23776 4088 1056 S 1.3 0.8 0:00.05 httpd
17515 apache 15 0 23776 4088 1056 S 1.3 0.8 0:00.08 httpd
17586 apache 15 0 23776 4088 1056 S 1.3 0.8 0:00.08 httpd
17592 apache 15 0 23776 4088 1056 S 1.3 0.8 0:00.05 httpd
17690 apache 15 0 23776 4088 1056 S 1.3 0.8 0:00.04 httpd
18298 apache 15 0 23776 4088 1056 S 1.3 0.8 0:00.06 httpd
18333 apache 15 0 0 0 0 Z 1.3 0.0 0:00.08 httpd
18355 apache 15 0 23776 4088 1056 S 1.3 0.8 0:00.05 httpd
17185 postgres 15 0 51940 24m 23m S 1.0 4.9 0:08.60 postmaster

sarコマンドの-uオプションの出力結果


% sar -u 1 10
Linux 2.6.32-279.19.1.el6.x86_64 (hostname) 2013年03月05日 _x86_64_ (2 CPU)

11時09分05秒 CPU %user %nice %system %iowait %steal %idle
11時09分06秒 all 50.26 0.00 25.64 4.10 0.00 20.00
11時09分07秒 all 45.79 0.00 26.84 5.79 0.00 21.58
11時09分08秒 all 49.47 0.00 25.53 4.26 0.00 20.74
11時09分09秒 all 48.42 0.00 29.47 2.11 0.00 20.00
11時09分10秒 all 43.48 0.00 27.17 4.89 0.00 24.46
11時09分11秒 all 46.15 0.00 28.57 3.30 0.00 21.98
11時09分12秒 all 45.99 0.00 26.74 3.74 0.00 23.53
11時09分13秒 all 52.11 0.00 24.74 2.63 0.00 20.53
11時09分14秒 all 45.79 0.00 28.42 4.21 0.00 21.58
11時09分15秒 all 46.52 0.00 27.27 3.74 0.00 22.46
平均値: all 47.42 0.00 27.03 3.88 0.00 21.67

mpstatコマンドの出力結果


% mpstat 1 10
Linux 2.6.32-279.19.1.el6.x86_64 (www4242gi.sakura.ne.jp) 2013年03月07日 _x86_64_ (2 CPU)

09時55分25秒 CPU %usr %nice %sys %iowait %irq %soft %steal %guest %idle
09時55分26秒 all 37.37 0.00 1.52 0.00 0.00 1.01 0.00 0.00 60.10
09時55分27秒 all 42.21 0.00 1.01 0.00 0.00 1.01 0.00 0.00 55.78
09時55分28秒 all 60.80 0.00 1.51 0.00 0.00 2.01 0.00 0.00 35.68
09時55分29秒 all 27.64 0.00 0.50 0.00 0.00 0.50 0.00 0.00 71.36
09時55分30秒 all 61.69 0.00 1.49 0.00 0.00 1.99 0.00 0.00 34.83
09時55分31秒 all 27.00 0.00 1.50 0.00 0.00 1.00 0.00 0.00 70.50
09時55分32秒 all 48.99 0.00 0.51 0.00 0.00 1.52 0.00 0.00 48.99
09時55分33秒 all 38.69 0.00 1.01 0.00 0.00 1.01 0.00 0.00 59.30
09時55分34秒 all 40.00 0.00 1.50 0.00 0.00 1.00 0.00 0.00 57.50
09時55分35秒 all 58.00 0.00 2.00 0.00 0.00 2.50 0.00 0.00 37.50
平均値: all 44.25 0.00 1.25 0.00 0.00 1.35 0.00 0.00 53.14

mpstatコマンドの出力結果


% vmstat 1 10
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 17340 68380 129876 54044 0 0 1 3 2 0 0 0 100 0 0
1 0 17340 68008 129876 54116 0 0 0 0 3415 1270 51 4 45 0 0
1 0 17340 68008 129884 54124 0 0 0 52 2065 1018 26 1 73 0 0
0 0 17340 67760 129884 54160 0 0 0 0 2981 1125 51 3 47 0 0
62 0 17340 67760 129884 54176 0 0 0 0 2344 1008 30 3 67 0 0
19 0 17340 67512 129884 54204 0 0 0 0 3002 1035 46 3 51 0 0
0 0 17340 67512 129884 54220 0 0 0 0 2546 1010 30 2 68 0 0
1 0 17340 67264 129892 54232 0 0 0 16 3420 1218 53 3 44 0 0
1 0 17340 67140 129892 54260 0 0 0 0 3758 1404 54 3 43 0 0
0 0 17340 66892 129892 54288 0 0 0 0 2756 1141 35 2 64 0 0

sarコマンドの-Pオプションの出力結果


% sar -P 1 10
Linux 2.6.32-279.19.1.el6.x86_64 (hostname) 2013年03月05日 _x86_64_ (2 CPU)

11時09分22秒 CPU %user %nice %system %iowait %steal %idle
11時09分23秒 all 45.88 0.00 28.87 2.58 0.00 22.68
11時09分23秒 0 45.36 0.00 27.84 3.09 0.00 23.71
11時09分23秒 1 47.42 0.00 28.87 2.06 0.00 21.65
11時09分23秒 CPU %user %nice %system %iowait %steal %idle
11時09分24秒 all 50.00 0.00 27.37 3.16 0.00 19.47
11時09分24秒 0 47.92 0.00 29.17 5.21 0.00 17.71
11時09分24秒 1 49.48 0.00 27.84 2.06 0.00 20.62
11時09分24秒 CPU %user %nice %system %iowait %steal %idle
11時09分25秒 all 45.26 0.00 27.37 4.21 0.00 23.16
11時09分25秒 0 46.81 0.00 24.47 4.26 0.00 24.47
11時09分25秒 1 43.75 0.00 29.17 4.17 0.00 22.92
11時09分25秒 CPU %user %nice %system %iowait %steal %idle
11時09分26秒 all 49.22 0.00 26.42 3.11 0.00 21.24
11時09分26秒 0 46.94 0.00 26.53 4.08 0.00 22.45
11時09分26秒 1 52.63 0.00 26.32 2.11 0.00 18.95
11時09分26秒 CPU %user %nice %system %iowait %steal %idle
11時09分27秒 all 47.69 0.00 29.23 2.56 0.00 20.51
11時09分27秒 0 48.96 0.00 32.29 2.08 0.00 16.67
11時09分27秒 1 47.92 0.00 25.00 2.08 0.00 25.00
11時09分27秒 CPU %user %nice %system %iowait %steal %idle
11時09分28秒 all 46.45 0.00 26.78 3.83 0.00 22.95
11時09分28秒 0 45.56 0.00 27.78 3.33 0.00 23.33
11時09分28秒 1 46.32 0.00 26.32 5.26 0.00 22.11
11時09分28秒 CPU %user %nice %system %iowait %steal %idle
11時09分29秒 all 45.03 0.00 26.70 4.71 0.00 23.56
11時09分29秒 0 42.71 0.00 25.00 4.17 0.00 28.12
11時09分29秒 1 46.32 0.00 28.42 5.26 0.00 20.00
11時09分29秒 CPU %user %nice %system %iowait %steal %idle
11時09分30秒 all 48.70 0.00 24.87 3.63 0.00 22.80
11時09分30秒 0 48.45 0.00 24.74 3.09 0.00 23.71
11時09分30秒 1 50.00 0.00 26.04 3.12 0.00 20.83
11時09分30秒 CPU %user %nice %system %iowait %steal %idle
11時09分31秒 all 46.11 0.00 27.46 3.63 0.00 22.80
11時09分31秒 0 45.92 0.00 28.57 3.06 0.00 22.45
11時09分31秒 1 46.32 0.00 26.32 4.21 0.00 23.16
11時09分31秒 CPU %user %nice %system %iowait %steal %idle
11時09分32秒 all 47.45 0.00 27.55 2.04 0.00 22.96
11時09分32秒 0 45.45 0.00 29.29 3.03 0.00 22.22
11時09分32秒 1 48.98 0.00 25.51 2.04 0.00 23.47
平均値: CPU %user %nice %system %iowait %steal %idle
平均値: all 47.18 0.00 27.27 3.34 0.00 22.21
平均値: 0 46.41 0.00 27.58 3.54 0.00 22.48
平均値: 1 47.92 0.00 26.98 3.23 0.00 21.88

※sar -u/-Pの各出力項目


%user :ユーザプロセスによるCPUの使用率の割合
%system :システムプロセスによるCPUの使用率の割合
%nice :実行優先度を変更した(nice値)ユーザプロセスによるCPUの使用率の割合
%iowait :I/O終了待ち時間の割合(I/O進行中でその終了を待っている時間)
%steal :仮想サーバがCPUを使って待たされていた時間の割合
%idle :ディスクI/O待ち以外でCPUが何もしないで待っていた時間の割合

CPU負荷で着目するのは%user, %systemの値です。
CPUの%user値
%user値は、ユーザプロセス(アプリケーションのプロセス等)の処理に消費されたCPU使用率を意味します。基本的にディスクへのアクセス(I/O)はありません。 %userの値が高い場合、主には以下のような状態が考えられます。

  • I/O等にボトルネックはなく、単にプロセスがCPUパワーを必要とする処理をしている
  • プログラムの暴走などでプロセスが大量にCPUを消費している。

CPUの%system値
%system値は、カーネル空間により実行されるプロセスの処理に消費されたCPU使用率を意味します。 %systemの値が高い場合、主には以下のような状態が考えられます。

  • ディスクI/Oが多発している
  • 重いプロセスを高頻度でfork(プロセスのコピーを生成)している

ロードアベレージの値が、搭載されているCPU数(コア数)より大きくなっており、CPUの%user,%system値が高い状態である場合、"処理が追いついていない"、つまりCPU負荷が高いということになります。
これは、例えば、2コアのCPUでロードアベレージが4となっている場合、2コアのCPUがそれぞれ1プロセスずつ処理を実行しており、残る2つのプロセスは実行待ち状態になっているということになります。
ただし、マルチタスクの場合、プログラムの作りにもよるため一概には言えません。(仮に4コアのCPUを搭載しているマシンがあったとして、4つのタスク(A,B,C,D)を実行する際に2CPUしか使わないようなプログラムを実行した場合、4CPUが全て空きの状態だったとしても、2CPU分のみが2つのタスク(A,B)で使用され、残る2つのタスク(C,D)は待ちの状態となるため、ロードアベレージは2となります。)
逆に、仮に1コアのCPUの使用率が常に100%の状態が1時間続いたとしても、その間のロードアベレージが常に1であったとすれば、サーバ負荷は0という事になります。これは1個のプロセスが常にCPUを占有している状態であり、そのプロセスがCPUをフルで使いつづけたという理想的な状態になるためです。

CPUの%user, %systemが高い場合、 以下のような対策を講じることになります。

  • %userが高い場合、アプリケーションを修正して、処理の効率が良くなるように改善する
  • 該当プロセスのスケジューリングを調整する
  • CPUを高性能なものに変更する
  • サーバを増設し、スケールアウトさせることで負荷を分散させる



CPUの%iowait値
続いてI/O負荷について記載します。 I/O負荷で着目すべきは%iowaitです。
%iowait値は、CPUがアイドル状態(待機状態)で、OS上に未処理のディスク入出力(読み書き)要求があった時間の割合を意味します。
※一般的にCPU使用率とは%userと%systemの値を足した値であり、%iowaitが高い状態であっても、CPU計算を必要とするプロセスが他にある場合には、そのプロセスがCPUを使用することが可能です。
I/O負荷が高い状態の場合、ロードアベレージとCPU使用率の%iowait値が高くなりますが、%system値も高くなる場合があります。これは、I/O負荷がカーネルからのread/write応答を待つことなので、カーネルのread/writeシステムコールの処理時間が増えることで%system値の上昇につながります。
逆に、ロードアベレージが高く、かつCPU使用率の%iowaitが%userや%systemに比べて著しく高い状態である場合、ディスクI/Oがボトルネックになっている可能性が高いと考えられます。これは、CPUを使用する処理が大きくないのにディスクへの読み書き要求が発生していることになり、求められるI/O要求に対して、ディスクの処理速度が追いついていない状態になるためです。
したがって、%iowait値が高い場合、主には以下のような状態が考えられます。 ・ディスクにアクセスする速度自体が遅い ・メモリが不足していてスワップ領域(つまりディスク)へのアクセスが頻発していて遅い CPUの%iowaitが高い場合、以下点についての確認や対策を講じる必要があります。 メモリ、スワップの状態を確認する 該当のプログラムを修正して、ディスクへのアクセスを減少させる SSDなどを高速なディスクを利用する サーバ増設、ディスク増設、RAID構成の見直し等を行い、I/O処理の負荷分散、性能向上を図る なお、どれだけ量のディスクI/Oが発生しているかは、"sar -b"コマンドで確認できます。 IOで重要なのはtps(1秒当たりのI/Oリクエスト数)の値で、これが高い場合、ディスクへのアクセスが頻発していることを意味します。 ----------------------------------------------------------------------------------------------------------------


timer.c sched.c kernel_stat.h これらの負荷がかかっているときに確認すべき点としては、大きく以下の4点があります。

  1. ロードアベレージ
  2. CPU使用率
  3. ディスクI/O
  4. メモリ使用状況

これらの状態を参照するコマンドはいくつかありますが、多くのLinuxディストリビューションでは、Sysstatというシステムリソースの使用状況データを収集するパッケージに含まれるsarというコマンドを利用することで確認できます。

Sysstatの概要


Sysstatについて簡単に記載します。

Sysstatとは、バックグラウンドでシステムのリソース情報をバイナリデータとして収集するsadcと、sadcで収集されたバイナリデータをテキストデータに変換するsarの2つのプログラムを含むパッケージです。 
CentOS標準のSysstatをインストールすると、sadcを実行するスクリプト(/usr/lib/sa/sa1)とsarを実行するスクリプト(/usr/lib/sa/sa2)がcronへ登録されます。これによりsadcが10分間隔でカーネルからデータを収集するようになり、取得されたデータは/var/log/sa/sa[日付]という形式で保存されます。sarは毎日23時53分に実行されるようになり、その日にsadcで取得されたバイナリデータをテキストデータへ変換し/var/log/sa/sar[日付]という形式で保存します。
sarをオプションなしで実行すると、sadcにより保存されている当日0:00からの10分間隔のデータが出力されます。"-f"オプションを指定し、過去に収集されたファイルを指定して実行することで、その日のデータを参照することも可能です。
多くの場合、sarに様々なオプションを組み合わせることであらゆるリソースデータを参照することができます。また、実行結果の推移を時間と共に追える点も非常に便利です。


SysstatはOSによっては標準のパッケージがありますが、存在しない場合はソースから導入することになります。

本家ダウンロードページ
http://sebastien.godard.pagesperso-orange.fr/download.html

環境


動作確認した環境は以下となります。

    • OS

CentOS5.7 i386 (カーネル 2.6.18-274.17.1.el5)

    • アプリケーション

Sysstat バージョン 7.0.2(CentOS標準パッケージ) 

サーバ負荷状況の確認手法と対策

 

ロードアベレージの確認


高負荷となっている場合、まず、負荷状況の確認のためにシステムのロードアベレージを確認します。
ロードアベレージの確認には"sar" コマンドの"-q"オプションを指定して実行します。

実行例(sar -q)

% sar -q 1 10
Linux 2.6.18-274.17.1.el5 (test)       2012年02月04日
11時04分48秒         4       215      3.99      3.48      1.84
11時04分49秒         2       215      3.99      3.48      1.84
11時04分50秒         2       215      3.99      3.48      1.84
11時04分51秒         3       215      3.99      3.48      1.84
11時04分52秒         4       215      3.99      3.48      1.84
11時04分53秒         0       215      4.23      3.54      1.86
11時04分54秒         2       215      4.23      3.54      1.86
11時04分55秒         2       215      4.23      3.54      1.86
11時04分56秒         3       215      4.23      3.54      1.86
11時04分57秒         3       215      4.23      3.54      1.86
平均値:          2       215      4.11      3.51      1.85

※出力結果の各項目の意味は以下の通りです。


ロードアベレージが示す数値は、"処理を実行したいが、何らかの原因で実行できず待ち状態となっているプロセス数の1分、5分、15分の平均値"になります(厳密には現在実行中のプロセス数+実行可能で待ち状態のプロセス数)。
Linuxカーネルは、専用のハードウェアからCPUへ定期的に送られてくるタイマ割り込みという信号を受け取るたびに、実行可能状態のプロセス数と実行中のプロセス数の数を計算し、それを単位時間(1分、5分、15分)で割ったものがロードアベレージとして出力されます。

この実行待ちプロセス数の平均値がサーバ負荷の判断基準となる数値になります。
ロードアベレージの値がCPU数(コア数)より大きくなっている場合は、そのCPUでは処理できていない待ち状態プロセスがある、つまり、それによりサーバ負荷が高くなっている、ということになります。
例えば、2コアのCPUでロードアベレージが4となっている場合、2つの実行待ちプロセスがあるということになり(ただし、マルチタスクの場合、プログラムの作りやHW環境にもよります)、プログラムの実行に遅延が生じていることになります。
逆に、仮に1コアのCPUの使用率が常に100%の状態が1時間続いたとして、その間のロードアベレージが常に1であったとすれば、 サーバの負荷はほぼ0と言えます。これは1個のプロセスが常にCPUを占有している状態であり、そのプロセスがCPUをフルで使いつづけたという理想的な 状態になるためです。
また、ロードアベレージが低いのにスループットが上がらない場合、ネットワーク面での問題(パケットロスなど)や、アプリケーション自体の不具合などが疑われます。

ロードアベレージが高い(プロセスが実行待ち状態となっている)原因は大きく以下の2つに分けられます。

・他のプロセスの処理にCPUが使われているため、別のあるプロセスはその処理の終了を待っている状態(CPU負荷)
・実行中プロセスがディスクへの読み書き要求を発行しており、その完了結果を待っている状態(I/O負荷)

上記から、"ロードアベレージが示す値は待ち状態のタスク数を示すのみ"あり、ロードアベレージの値を見るだけでは、CPU負荷なのか、ディスクI/Oの負荷なのか判別できません。
したがって、ロードアベレージが高い場合は、次に、CPU負荷なのか、I/O負荷なのかを調査していくことになります。

CPU使用率とI/O負荷の確認


ロードアベレージの値はCPU負荷、及びI/O負荷を示しています。そのため、続いてCPU使用率とI/O負荷の状況について調査していくことになります。

まず、CPUの状態を確認するにはsarコマンドの" -u"オプションや "-P"オプションを指定して実行します。"sar -P"では各CPU数(コア数)ごとの各使用率を参照することができます。

実行例(sar -u)

# sar -u 1 10 
Linux 2.6.18-274.17.1.el5 (test)       2012年02月04日
11時09分05秒       CPU     %user     %nice   %system   %iowait    %steal     %idle
11時09分06秒       all     50.26      0.00     25.64      4.10      0.00     20.00
11時09分07秒       all     45.79      0.00     26.84      5.79      0.00     21.58
11時09分08秒       all     49.47      0.00     25.53      4.26      0.00     20.74
11時09分09秒       all     48.42      0.00     29.47      2.11      0.00     20.00
11時09分10秒       all     43.48      0.00     27.17      4.89      0.00     24.46
11時09分11秒       all     46.15      0.00     28.57      3.30      0.00     21.98
11時09分12秒       all     45.99      0.00     26.74      3.74      0.00     23.53
11時09分13秒       all     52.11      0.00     24.74      2.63      0.00     20.53
11時09分14秒       all     45.79      0.00     28.42      4.21      0.00     21.58
11時09分15秒       all     46.52      0.00     27.27      3.74      0.00     22.46
平均値:        all     47.42      0.00     27.03      3.88      0.00     21.67


実行例(sar -P)

$ sar -P ALL 1 10
Linux 2.6.18-274.17.1.el5 (test)      2012年02月04日
11時09分22秒       CPU     %user     %nice   %system   %iowait    %steal     %idle
11時09分23秒       all     45.88      0.00     28.87      2.58      0.00     22.68
11時09分23秒         0     45.36      0.00     27.84      3.09      0.00     23.71
11時09分23秒         1     47.42      0.00     28.87      2.06      0.00     21.65
11時09分23秒       CPU     %user     %nice   %system   %iowait    %steal     %idle
11時09分24秒       all     50.00      0.00     27.37      3.16      0.00     19.47
11時09分24秒         0     47.92      0.00     29.17      5.21      0.00     17.71
11時09分24秒         1     49.48      0.00     27.84      2.06      0.00     20.62
11時09分24秒       CPU     %user     %nice   %system   %iowait    %steal     %idle
11時09分25秒       all     45.26      0.00     27.37      4.21      0.00     23.16
11時09分25秒         0     46.81      0.00     24.47      4.26      0.00     24.47
11時09分25秒         1     43.75      0.00     29.17      4.17      0.00     22.92
11時09分25秒       CPU     %user     %nice   %system   %iowait    %steal     %idle
11時09分26秒       all     49.22      0.00     26.42      3.11      0.00     21.24
11時09分26秒         0     46.94      0.00     26.53      4.08      0.00     22.45
11時09分26秒         1     52.63      0.00     26.32      2.11      0.00     18.95
11時09分26秒       CPU     %user     %nice   %system   %iowait    %steal     %idle
11時09分27秒       all     47.69      0.00     29.23      2.56      0.00     20.51
11時09分27秒         0     48.96      0.00     32.29      2.08      0.00     16.67
11時09分27秒         1     47.92      0.00     25.00      2.08      0.00     25.00
11時09分27秒       CPU     %user     %nice   %system   %iowait    %steal     %idle
11時09分28秒       all     46.45      0.00     26.78      3.83      0.00     22.95
11時09分28秒         0     45.56      0.00     27.78      3.33      0.00     23.33
11時09分28秒         1     46.32      0.00     26.32      5.26      0.00     22.11
11時09分28秒       CPU     %user     %nice   %system   %iowait    %steal     %idle
11時09分29秒       all     45.03      0.00     26.70      4.71      0.00     23.56
11時09分29秒         0     42.71      0.00     25.00      4.17      0.00     28.12
11時09分29秒         1     46.32      0.00     28.42      5.26      0.00     20.00
11時09分29秒       CPU     %user     %nice   %system   %iowait    %steal     %idle
11時09分30秒       all     48.70      0.00     24.87      3.63      0.00     22.80
11時09分30秒         0     48.45      0.00     24.74      3.09      0.00     23.71
11時09分30秒         1     50.00      0.00     26.04      3.12      0.00     20.83
11時09分30秒       CPU     %user     %nice   %system   %iowait    %steal     %idle
11時09分31秒       all     46.11      0.00     27.46      3.63      0.00     22.80
11時09分31秒         0     45.92      0.00     28.57      3.06      0.00     22.45
11時09分31秒         1     46.32      0.00     26.32      4.21      0.00     23.16
11時09分31秒       CPU     %user     %nice   %system   %iowait    %steal     %idle
11時09分32秒       all     47.45      0.00     27.55      2.04      0.00     22.96
11時09分32秒         0     45.45      0.00     29.29      3.03      0.00     22.22
11時09分32秒         1     48.98      0.00     25.51      2.04      0.00     23.47
平均値:        CPU     %user     %nice   %system   %iowait    %steal     %idle
平均値:        all     47.18      0.00     27.27      3.34      0.00     22.21
平均値:          0     46.41      0.00     27.58      3.54      0.00     22.48
平均値:          1     47.92      0.00     26.98      3.23      0.00     21.88

※出力結果の各項目の意味は以下の通りです。

  • %user:ユーザプロセスによるCPUの使用率の割合
  • %system:システムプロセスによるCPUの使用率の割合
  • %nice:実行優先度を変更した(nice値)ユーザプロセスによるCPUの使用率の割合
  • %iowait:I/O終了待ち時間の割合(I/O進行中でその終了を待っている時間)
  • %steal:仮想サーバがCPUを使って待たされていた時間の割合
  • %idle:ディスクI/O待ち以外でCPUが何もしないで待っていた時間の割合


まず、CPU負荷について記載します。
CPU負荷で着目するのは%user, %systemの値です。

CPUの%user値
%user値は、ユーザプロセス(アプリケーションのプロセス等)の処理に消費されたCPU使用率を意味します。
%userの値が高い場合、主には以下のような状態が考えられます。

・I/O等にボトルネックはなく、単にプロセスがCPUパワーを必要とする処理をしている
・プログラムの暴走などでプロセスが大量にCPUを消費している。

CPUの%system値
%system値は、カーネルレベルのプロセスの処理に消費されたCPU使用率を意味します。
%systemの値が高い場合、主には以下のような状態が考えられます。

・ディスクI/Oが多発している
・重いプロセスを高頻度でfork(プロセスのコピーを生成)している

CPUの%user, %systemが高い場合、 以下のような対策を講じることになります。

  • %userが高い場合、アプリケーションを修正して、処理の効率が良くなるように改善する
  • 該当プロセスのスケジューリングを調整する
  • CPUを高性能なものに変更する
  • サーバを増設し、スケールアウトさせることで負荷を分散させる

CPUの%iowait値
続いてI/O負荷について記載します。
I/O負荷で着目すべきは%iowaitです。
%iowait値は、CPUがアイドル状態(待機状態)で、OS上に未処理のディスク入出力(読み書き)要求があった時間の割合を意味します。
※一般的にCPU使用率とは%userと%systemの値を足した値であり、%iowaitが高い状態であっても、CPUを必要とするプロセスが他にある場合には、そのプロセスがCPUを使用することが可能です。

I/O負荷の場合、CPU使用率の%iowait値とロードアベレージも高くなりますが、%system値も高くなる場合があります。I/O負荷とはカーネルからのread/write応答を待つことなので、カーネルのread/writeシステムコールの処理時間が増えることで%system値の上昇につ ながります。
逆にロードアベレージが高く、かつCPU使用率の%iowaitが%userや%systemに比べて著しく高い状態である場合、ディスクI/Oがボトルネックになっている可能性があります。
これは、CPUを使用する処理が大きくないのにディスクへの読み書き要求が発生していることになり、求められるI/O要求に対して、ディスクの処理速度が追いついていない状態になります。

したがって、%iowait値が高い場合、主には以下のような状態が考えられます。

・ディスクにアクセスする速度自体が遅い
・メモリが不足していてスワップ領域(つまりディスク)へのアクセスが頻発していて遅い

CPUの%iowaitが高い場合、以下点についての確認や対策を講じる必要があります。

  • メモリ、スワップの状態を確認する
  • 該当のプログラムを修正して、ディスクへのアクセスを減少させる
  • SSDなどを高速なディスクを利用する
  • サーバ増設、ディスク増設、RAID構成の見直し等を行い、I/O処理の負荷分散、性能向上を図る

なお、どれだけ量のディスクI/Oが発生しているかは、"sar -b"コマンドで確認できます。
IOで重要なのはtps(1秒当たりのI/Oリクエスト数)の値で、これが高い場合、ディスクへのアクセスが頻発していることを意味します。

実行例(sar -b)

$ sar -b 1 10
Linux 2.6.18-274.17.1.el5 (test)       2012年02月04日

11時10分06秒       tps      rtps      wtps   bread/s   bwrtn/s
11時10分07秒   1585.57      0.00   1585.57      0.00  19991.75
11時10分08秒   1721.62      0.00   1721.62      0.00  21470.27
11時10分09秒   1741.79      0.00   1741.79      0.00  22770.15
11時10分10秒   2222.99      0.00   2222.99      0.00  27567.82
11時10分11秒   2189.80      0.00   2189.80      0.00  27232.65
11時10分12秒   2004.21      0.00   2004.21      0.00  24707.37
11時10分13秒   1987.76      0.00   1987.76      0.00  24653.06
11時10分14秒   2080.85      0.00   2080.85      0.00  26229.79
11時10分15秒   2093.62      0.00   2093.62      0.00  25957.45
11時10分16秒   2354.17      0.00   2354.17      0.00  29200.00
平均値:    2010.56      0.00   2010.56      0.00  25103.11

※出力結果の各項目の意味は以下の通りです。

  • tps:物理デバイスへの1秒間のI/Oリクエストの転送量
  • rtps:物理デバイスへの1秒間の読み込みリクエストの転送量
  • wtps:物理デバイスへの1秒間の書き込みリクエストの転送量
  • bread/s:1秒間に読み出されたデータ量(ブロック単位)
  • bwrtn/s:1秒間に書き込まれたデータ量(ブロック単位)

 

メモリ、スワップ使用量の確認


ロードアベレージが高く、CPUの%iowaitが高い場合、ディスクアクセスの他に、メモリ不足によるスワップの多発が疑われます。

メモリ使用量を見るにはsarコマンドで"-rオプションを指定して実行します。スワップの状態を確認するにはsarコマンドで"-W"オプションを指定して実行します。

実行例(sar -r)

% sar -r 1 10
Linux 2.6.18-274.17.1.el5 (test)       2012年02月04日
11時10分36秒 kbmemfree kbmemused  %memused kbbuffers  kbcached kbswpfree kbswpused  %swpused  kbswpcad
11時10分37秒     67928    446984     86.81     22784    209332   1029192     19376      1.85      4460
11時10分38秒     67184    447728     86.95     22784    209712   1029192     19376      1.85      4460
11時10分39秒     83304    431608     83.82     22784    193600   1029192     19376      1.85      4460
11時10分40秒     83180    431732     83.85     22792    193820   1029192     19376      1.85      4460
11時10分41秒     82932    431980     83.89     22792    194200   1029192     19376      1.85      4460
11時10分42秒     82808    432104     83.92     22792    194504   1029192     19376      1.85      4460
11時10分43秒     82560    432352     83.97     22792    194776   1029192     19376      1.85      4460
11時10分44秒     82312    432600     84.01     22792    195004   1029192     19376      1.85      4460
11時10分45秒     82064    432848     84.06     22800    195344   1029192     19376      1.85      4460
11時10分46秒     81816    433096     84.11     22800    195572   1029192     19376      1.85      4460
平均値:      79609    435303     84.54     22791    197586   1029192     19376      1.85      4460

※各出力項目の意味は以下の通りです。

  • kbmemfree:物理メモリの空き容量
  • kbmemused:使用中のメモリの容量
  • %memused:物理メモリ使用率
  • kbbuffers:バッファとして使用されている物理メモリの使用率
  • kbcached:キャッシュとして使用されている物理メモリの使用率
  • kbswpfree:スワップ領域の空き容量
  • kbswpused:使用中のスワップ領域の容量
  • %swpused:スワップ使用率
  • kbswpcad:キャッシュされたswap領域の容量


実行例(sar -W)

$ sar -W 1 10
Linux 2.6.18-274.17.1.el5 (test)       2012年02月04日
11時11分33秒  pswpin/s pswpout/s
11時11分34秒      0.00      0.00
11時11分35秒     64.79      0.00
11時11分36秒      0.00   4613.51
11時11分37秒      8.42   5708.42
11時11分38秒      0.00   4497.80
11時11分39秒      0.00   4522.73
11時11分40秒      0.00   3886.32
11時11分41秒      0.00   5215.00
11時11分42秒     55.17   5801.15
11時11分43秒      0.00   3634.83
平均値:      34.17   4491.55

※出力結果の各項目の意味は下記になります。

  • pswpin/s:ディスクからメモリに転送される 1 秒当たりのページ(仮想アドレス空間)数。
  • pswpout/s:メモリからディスクへ転送される 1 秒当たりのページ(仮想アドレス空間)数。


Linuxの場合、メモリをできるだけ有効に活用しようとするため、一度読み込んだプロセスやデータを空きメモリ上にキャッシュして保存し、次にそのデータを読み出す場合にはディスクへアクセスせず、メモリ上のデータを参照します。
そのため、メモリ使用量が増えてくると、キャッシュの使用領域が少なくなり、ディスクへのアクセスが増加します。ディスクへの読み書きはメモリへの読み書きよりはるかに遅いため、ディスクI/Oが増えると、I/O待ちとなるプロセスが増え、処理のボトルネックとなります。

※メモリ使用量(kbmemused)の値はキャッシュやバッファを含めた値となるため大きいものになりますので、実際にプロセスがどの程度メモリ を使用しているかは、キャッシュ(kbcached)とバッファ(kbbuffers)に利用されているメモリ容量を差し引いた値で判断する必要があります。
 メモリ使用率が高く、スワップが多発している原因は以下になります。

・メモリを大量に使用する処理があるが、搭載しているメモリが不足している

利用可能なメモリ量が不足してくると、メモリへ保存されている古いプロセスやデータはディスク上のスワップと呼ばれる領域に保存されます。 そのため、スワップが多発することは、その分ディスクへのアクセスが発生することになるため、サーバのスループットが低下します。

メモリ不足やスワップ多発の場合は以下のような対策を講じることになります。

  • プログラムのメモリ使用量を減らしたり、キャッシュの仕組みを見直す 
  • メモリを増設する 

以上がsysstatを利用してのサーバの負荷状況、及びその原因を追及する手順の一つになります。
最近では様々な監視ツールもあるため、それらを利用することで、もっと簡単に原因を特定できるかと思います。様々な方法を使ってサーバ負荷となる原因を特定し、対策を行えるように心がけたいものです。