アプリケーションエンジニアの人には「なんか重い」という状況に遭遇したらインフラの人にタスクを投げる、という人もいるかも知れません。けど、その重さのどこに原因があるのか。CPUか、ネットワークか、IOかくらいの診断はできた方がアプリ開発においても有益です。
「せっかくつくったシステムがなんか重い」
そんな時にアプリケーションエンジニアとしてできることを書きます。
本職のインフラの人にはぬるい内容だと思います。何を隠そう僕自身がアプリ寄りの人間なので、突っ込んだ話はできないのです。あしからずご了承ください。
なんかサーバが重いなー
まずはロードアベレージを調べる
サーバが重いと思ったら、まず真っ先にすべきことは対象ホストにSSH接続してロードアベレージを調べることでしょう。ロードアベレージとは 実行されずに待たされているプロセスの数 のことで、多すぎるとやばいと認識しておきましょう。ロードアベレージだけでは何が原因で重くなっているのか判断することはできないけれど、検査のとっかかりとして行います。
ロードアベレージがどれくらいの数値がヤバいのかは、CPUのコアの数とかに依存する(らしい)もので、一概に「Xを超えていたらまずい」と言い切ることができません。なので、日頃からロードアベレージをちょくちょく確認し「あれ、いつもよりロードアベレージ高いな」と言えるようになることが重要なのだろうと思います。
- 使うコマンド: top、uptime
topはロードアベレージの他にも今走ってるプロセスを占有してるメモリ量とかでソートしたり色々できる便利コマンドです。uptimeはほぼロードアベレージだけを表示してくれるコマンドです。
topの方やれることが多いので普段はこちらを使えばいいですが、本当に切迫しているサーバ上だと、topの実行すらままならないという状況もあり得るので、uptimeの存在も頭の片隅においておくべきでしょう。
top使うと右上にload averageに続いて小数が3つ表示されます。これがロードアベレージで、左から過去1分5分15分の間の数値を表しています。強いていうなら 1分と5分のやつだけ高かったら、最近始めたプロセスが原因だと推測できる というくらい。
ロードアベレージが低かった場合
ロードアベレージが低いのに重い、ということは原因は外部にあうことが疑われます。ネットワークの問題や、リモートホスト(例えばWebサーバとDBサーバが別ホストにあって、Webサーバのロードアベレージが低いなら、DBサーバを疑ってみるみたいな)に原因がある可能性があります。なのでサーバのネットワークIOの様子を見てみるといいでしょう。
- 使うコマンド: dstat、netstat
dstatとnetstatは両方statで終わってますが、実は他にもvmstat、iostat、ifstatなんかもあります。このdstatというのは、これら乱立したXXXstatコマンドをひとまとめにし、かつ、使いやすくしよう、という目的で作られた後発ツールです。なので、使うならdstatがいいと思います。
例えば dstat --tcp
とやるとTCPコネクションの様子を見たり dstat --net
とやるとネットワークの様子を見ることができますが、、、はっきり言ってアプリの人間には意味不明だと思いますので、調べても分からない場合は素直にインフラに強い人に尋ねましょう。
ロードアベレージが高かった場合
この場合はホストの中に問題があると想像できます。続いてCPUとIOのどちらに原因があるか探ります。
CPU使用率とIO待ち状態を調べる
- 使うコマンド: sar、dstat、vmstat
sar -u
や dstat -a
などを実行します。sarの場合で話をすると、見るべきは %user
%system
%iowait
の項目です。
%userが高い場合
ユーザプログラムがボトルネックになっていると考えられます。どのプログラムに原因があるか調べましょう。
- 使うコマンド: top、dstat、pidstat
top
はプロセスの一覧をCPU使用率やメモリ占有率などでソートする機能があります。例えばtop
を実行してからおもむろに m
と打つとメモリ順でソートしてくれます。dstat --top-cpu
とすることで最もCPUを使っているプロセスを表示することもできます。
pidstat
は特定のプロセスの統計情報を調べるのに使います。問題のプロセスがある程度しぼれたら pidstat -u -p PID,PID,PID
をします。PIDには怪しいプロセスのPIDを入れます。-u はCPU使用率を表示するオプションです。
ここで、CPUに負荷がかかっているのは、ディスクI/Oやメモリなどが適切に働いているか、プログラムが暴走しているかのどちらかです。後者の場合は完全にアプリケーションエンジニアのデバッグの仕事です。前者かつスループットが上がらない、という場合は、アプリケーションエンジニアとしてはアルゴリズムの改善などで対処できますが、インフラの人とサーバの増設などを検討することも必要かも知れません。前者でかつスループットが高い状態というのは、リソースを余すことなく使えているということなので、むしろ理想的な状態であるといえますが、将来的にリソースが足りなくなる可能性が高いので、早めにリソース増強の算段を建てたほうがいいかも知れません。
%systemが高い場合
これはカーネル空間の処理に時間を取られていることを意味します。この場合に考えられるのは、I/O待ちでCPU時間を消費しているか、大きいプロセスをforkしまくっている等(らしい)です。なので %system が高い場合 %iowait が高い場合も多いようです。
この場合はI/O待ち状態のプロセスを探します
- 使うコマンド: top、dstat
dstat --top-bio
で最もブロックI/Oをしているプロセスが、dstat --top-io
で最もI/Oをしているプロセスが表示されます。
%user も %system も低いのに %iowait が高い場合
何かのプロセスでスワップが発生している可能性があります。
- 使うコマンド: top、free、sar、dstat、vmstat
sar -W
や dstat --swap
はスワップインとスワップアウトの状況、free
はシステム全体のメモリ使用状況が調べらることができます。top
でメモリ使用量でソートすればメモリを沢山使っているプロセスを発見することができます。
スワップが確認された場合、アプリケーションエンジニアとしてはメモリリークがないか調べ、問題箇所を修正することで対処できます。そうでない場合は、純粋に搭載メモリが足りていないのでメモリの増設などを検討しましょう。
まとめ
- 問題があったらまずはロードアベレージを調べましょう
- ロードアベレージが低い場合は、外部に問題がある可能性があります。
- ロードアベレージが高い場合は、内部に問題がある可能性があります。CPU、IOのどこに問題があるのか調べましょう。
-
dstat
便利です