綺麗に死ぬITエンジニア

ノンサーバーエンジニアへ贈る、Webサーバーの負荷テストの手法

2015-03-22

今の時代、仮想化技術の発展・クラウドコンピューティングの普及により、Webデザイナー・プログラマーとサーバーエンジニアの区分が曖昧になってきていて、デザイナーやプログラマーもWebサーバー(apache/httpd)に対して目を瞑っていられる時代じゃなくなってきました。

今回は、ノンサーバーエンジニア向けに、Webサーバーの負荷テストによる、サーバーのボトルネックや問題発生原因の究明の仕方を紐解いていきます。

サーバーの構成要素

Webサーバーのボトルネック(処理速度低下の原因や障害発生の原因)を究明していく上で、最低限、ボトルネックとなりうる要素は知っておかなければなりません。サーバーは簡単に、以下の要素が互いに機能しあって動いています。

  • CPU
  • メモリー
  • ハードディスク
  • ネットワーク

それぞれの役割は後述します。

上のうちの1つでも機能しなくなると、WebサーバーはWebサービスを提供できなくなりますし、1つの機能が遅くなると、全体の処理速度低下に結びつきます(これをボトルネックというわけです)。

つまり、処理速度(Web応答速度)が低下している場合・よくWebサービスが停止してしまう場合には、上の4つの構成要素をそれぞれチェックして、持っているスペック以上の仕事をさせすぎていないかどうか、チェックしていきます。

チェックした結果、例えばCPUのスペックが足りていないとなった場合、「CPUリソースを異常に消費するアプリケーションを突き止めプログラム改修を行う」「そもそもアクセス数に対するCPUリソースが足りていないのでCPUを追加する」など、CPUに的を絞った更なる調査と対策が打てるようになるわけです。

負荷テストを行うツール

負荷テストには、一般的には以下のツールを使う方法があります。

  • LinuxにApache(Webサーバーソフトウェア)をインストールした際に一緒にインストールされるabコマンド(Apache Bench)を利用する方法
  • Apache JMeterというサーバーの負荷テストを行う無料のJavaアプリケーションを用いる方法
  • Load ImpactなどのSaaS(ほぼ有料)を利用する方法などがあります。

どの方法も特定のWebページに対して擬似的なアクセスをして、負荷をかけていくものとなっています。

このとき、「そのツールがどのようにWebコンテンツにアクセスするか」だけには注意を払っておく必要があります。

例えばabコマンドの場合、http://www.example.com/index.htmlというコンテンツに負荷をかけたとすると、そのindex.htmlを読み込んだらそれで終了で、もしindex.html内部で画像ファイルやJavaScript/CSSファイルを参照していたとしても、そこまではアクセスしません。

つまり、現実に想定されるアクセスパターンとは違う負荷のかけ方がされてしまうということです。それで要件を満たすようならいいですが、場合によってはまるで意味のない負荷テストになってしまう可能性があります。

その点、Apache JMeterはきめ細やかに設定することができますし、Load ImpactなどのSaaSは自動で現実のアクセスに近い負荷をかけてくれたりしますので、リアルな負荷テストが必要な場合にはそちらで試してみましょう。

ツールの使い方などは、ここでは解説しません。

CPUスペックの判断基準「ロードアベレージ」

さて、ここからは実際に負荷をかけた状態で先ほどの各4要素のスペックが足りているのかどうかを見ていく方法について解説します。

まず、CPU負荷ですが、サーバーエンジニアではない方は、CPU負荷を見るには"CPU使用率"を見ればいいんだ!と思うかもしれませんが、CPU使用率という値では、CPUが足りていないのかどうか、更には足りていないときにどれくらい足りていないのかというのがわかりません。

CPU使用率100%だとCPUが足りていないのでは?と思うかもしれませんが、CPU使用率100%というのはCPUをフルに使っているという意味で、例えばパソコンで言えば、ブラウザを起動した直後は100%になりますが、起動し終わるとすぐにCPU使用率は下がります。つまり、一瞬だけ100%になるというのはざらにあることで、それが継続的に続くと問題ではありますが、単に100%だからダメ!と決めつけられるものでもありません。

それに、CPUの使用効率という観点から見れば、できるだけCPU使用率は100%に近づけたほうが、リソースを無駄にしていないという考え方もあります。

そこで、CPU負荷について調べるには、ロードアベレージという値を調べます。

ロードアベレージとは、平均実行プロセス数のことで、Linuxではuptimeコマンドを使用することで調べることができます。1分間・5分間・15分間のロードアベレージが下記のように出力されます。

$ uptime
# 00:03:32 up 1:11, 2 users, load average: 3.90, 0.68, 0.25

上の表示だと、直前1分間の平均実行プロセス数が3.9、直前5分間が0.68、直前15分間が0.25となります。

具体的にこの数値が何を意味しているのかというと、1分間に常時3.9プロセスを最速で動かすには、簡単に言えばCPUが3.9個(3.9コア)必要です。しかし、もしCPUが1個(1コア)で構成されていた場合、最速よりも3.9倍の時間をかけて処理をしていることになります。

勘違いされることが多いのですが、CPU1つに対して、実行できるプロセスというのは1つのみです。「俺のパソコンはCPU1コアだけどブラウザとメーラーを同時に実行できるぞ!」という人がいるかもしれませんが、それは1つのCPUが通常の2倍の時間をかけてブラウザとメーラーを同時に実行しているに過ぎません。

つまり、上の表示の場合、CPUが1個だと想定すると、直前1分間に関しては本来3.9個のCPUで分担してやるべき仕事量を、3.9倍の時間をかけて1個のCPUで処理しているため、CPUのスペックが足りていないということになります。

しかし、5分間・15分間という期間で見た場合には、ロードアベレージ1未満なので、CPU1個で足りる負荷となっています。

上の場合は恐らく、直前1分間に比較的大きなアクセスがあったなどで、負荷が高くなっているということなのでしょう、ということがわかるわけです。

1分間のロードアベレージが3.9というのは、急なアクセス増加があったなどでそうなってしまうのはしょうがないと思いますが、例えば15分間のロードアベレージが10とかになってしまうと、15分間もの間、通常の10倍の時間をかけて処理を行っているということなので、明らかに問題があります。

通常は、15分間のロードアベレージでCPU数×1.2を超えてしまうようなことがあると、スペック不足による応答速度の低下が起きている可能性が高く、時間による改善の見込みが少ないと判断できるため、何かしらの対策をとるべきでしょう。

ちなみに、CPUの個数(コア数)は、以下のコマンドで調べることができます。

# cat /proc/cpuinfo
processor : 0
vendor_id : GenuineIntel
cpu family : 6
model : 15
model name : Intel(R) Core(TM)2 CPU 6400 @ 2.13GHz
stepping : 6
cpu MHz : 2133.675
cache size : 2048 KB
physical id : 0
siblings : 2
core id : 0
cpu cores : 2
fdiv_bug : no
hlt_bug : no
f00f_bug : no
coma_bug : no
fpu : yes
fpu_exception : yes
cpuid level : 10
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe nx lm constant_tsc pni monitor ds_cpl vmx est tm2 cx16 xtpr lahf_lm
bogomips : 4273.36

processor : 1
vendor_id : GenuineIntel
cpu family : 6
model : 15
model name : Intel(R) Core(TM)2 CPU 6400 @ 2.13GHz
stepping : 6
cpu MHz : 2133.675
cache size : 2048 KB
physical id : 0
siblings : 2
core id : 1
cpu cores : 2
fdiv_bug : no
hlt_bug : no
f00f_bug : no
coma_bug : no
fpu : yes
fpu_exception : yes
cpuid level : 10
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe nx lm constant_tsc pni monitor ds_cpl vmx est tm2 cx16 xtpr lahf_lm
bogomips : 4267.00

上の場合は、CPUが2個、ということになります。

メモリーの調査

メモリーの場合は、CPUほど難しくありません。

搭載している物理メモリーの量より多いメモリーを消費してしまって、スワップという現象(物理メモリーが不足し、ハードディスクをメモリーとして使う現象)が起きたらアウトです。

簡単に見る方法は、vmstatコマンドを使うことです。

$ vmstat 1
procs -----------memory---------- ---swap-- -----io---- --system-- ----cpu----
r b swpd free buff cache si so bi bo in cs us sy id wa
0 0 0 297132 11632 99648 0 0 10 3 167 33 0 0 99 0
0 0 0 297132 11640 99640 0 0 0 36 332 66 0 0 100 0
0 0 0 297140 11640 99640 0 0 0 0 344 62 0 0 100 0
0 0 0 297140 11640 99640 0 0 0 0 327 34 0 0 100 0
0 0 0 297132 11640 99640 0 0 0 0 344 66 0 0 100 0

memoryのswpdがスワップ領域の容量なので、ここが0以外の数値だとスワップが発生しています。

他にも、freeコマンドを使う方法もあります。

# free
  total used free shared buffers cached
Mem: 1553752 1457668 96084 0 90080 699200
-/+ buffers/cache: 668388 885364
Swap: 1024120 468 1023652

こちらはリアルタイム性に欠けますが、メモリの空き容量やスワップ領域の容量のみ、わかりやすく表示されます。

ここでも一点、注意が必要なのが、Linuxの設定によっては物理メモリーを使い切らなくてもスワップすることがあります。それはswappinessというカーネルパラメーターで変更することができます。ここでは詳しくは書きませんが、物理メモリーの空きが十分であるにもかかわらず、スワップが発生している場合には、swappinessを変更しましょう。

負荷テスト中であれば、vmstatコマンドのswapのsiが0以外になると、リアルタイムでスワップが発生していることを表すので、そこの値を随時確認して、スワップが負荷と同時に発生していないかどうかを確認するといいでしょう。

ちなみに、メモリの情報は、以下のコマンドで調べることができます。

# cat /proc/meminfo
MemTotal: 255908 kB
MemFree: 69936 kB
Buffers: 15812 kB
Cached: 115124 kB
SwapCached: 0 kB
Active: 92700 kB
Inactive: 63792 kB
HighTotal: 0 kB
HighFree: 0 kB
LowTotal: 255908 kB
LowFree: 69936 kB
SwapTotal: 524280 kB
SwapFree: 524280 kB
Dirty: 4 kB
Writeback: 0 kB
Mapped: 42236 kB
Slab: 25912 kB
Committed_AS: 118680 kB
PageTables: 1236 kB
VmallocTotal: 3874808 kB
VmallocUsed: 1416 kB
VmallocChunk: 3872908 kB
HugePages_Total: 0
HugePages_Free: 0
Hugepagesize: 4096 kB

ディスクI/Oの調査

こちらもvmstatコマンドで調査することができます。

$ vmstat 1
procs -----------memory---------- ---swap-- -----io---- --system-- ----cpu----
r b swpd free buff cache si so bi bo in cs us sy id wa
0 0 0 297132 11632 99648 0 0 10 3 167 33 0 0 99 0
0 0 0 297132 11640 99640 0 0 0 36 332 66 0 0 100 0
0 0 0 297140 11640 99640 0 0 0 0 344 62 0 0 100 0
0 0 0 297140 11640 99640 0 0 0 0 327 34 0 0 100 0
0 0 0 297132 11640 99640 0 0 0 0 344 66 0 0 100 0

ioのbiとboが、注目すべき点です。biがディスクから読み出しているデータブロック数、boがディスクに送っているデータブロック数です。搭載しているデバイスのスペックにもよりますが、ここの値が増大している場合には、「キャッシュなどを利用してディスクアクセスを極力減らす」「物理的な帯域幅を増やす」「プログラムによるディスクアクセスを減らす」「コンテンツを圧縮する」などの対策をとる必要があるでしょう。

ネットワークの調査

ネットワークがボトルネックになった経験がないのであまりわかりませんが……。

TCPのコネクション数が原因となる場合と、帯域幅(転送速度)が原因となる場合が考えられます。

TCPのコネクション数を調べるには、以下のコマンドを使います。

# netstat -an | wc -l
3010

このコマンドは正確な値ではないですが、大体のコネクション数を測るのに便利です。コネクション数が増大した場合の対処法としては、サーバーの台数を増やして複数サーバーで分散処理をするなどが挙げられます。

転送速度を調べるには、以下のコマンドを使います。

# cat /proc/net/dev
Inter-| Receive | Transmit
 face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed
 lo:61101820 57561 0 0 0 0 0 0 61101820 57561 0 0 0 0 0 0
 eth0:211752374 14263469 0 0 0 0 0 0 33509783 17990346 0 0 0 0 0 0

こちらは転送量の総量なので、負荷テストのピーク時に特定の間隔をあけて2回実行し、その間に増加したデータ量を時間で割ると、転送速度が算出できます。

まとめ

サーバー調査は専門家でないと難しいイメージがあるかもしれませんが、一旦実際にやってみると案外簡単にできたりします。

これを機に、ノンサーバーエンジニアの方々も、サーバーをいじってみて、仕事の幅を広げてみてはいかがでしょうか。

Linuxコマンドの基礎について知りたい方は、こちらの記事を参考にしてみてください。

そもそも、Linuxについて知りたい方は、以前まとめましたのでどうぞ。

筆者について

フリーランスエンジニアとして活動している、「もりやませーた」です。

筆者のTwitterはこちら。記事に関するご意見等はTwitterの方へお寄せください。

その他業務に関するお問い合わせは、こちらのページをご覧ください。

Linux