Closed7
サーバーが重い...ときに確認すること

ロードアベレージを確認する
$ uptime
11:03 up 6 days, 19:17, 7 users, load averages: 4.88 6.90 7.32

ロードアベレージが低い場合
ネットワークの問題の可能性がある。
TCPコネクションが異常に大量に張られていないか確認する。(TCPコネクション数の上限に張り付いている可能性がある)
$ netstat -an | wc -l
414
# 使っているポートを待機中のものも含めてすべて表示する「-a」
# 名前解決をせずに数字で表示する「-n」

ロードアベレージが高い場合
CPU利用率を確認する
CPU使用率がほぼ100%になっていたらCPUがボトルネックになっている。
$ top -c
top - 11:10:14 up 1058 days, 15:03, 1 user, load average: 0.06, 0.04, 0.05
Tasks: 157 total, 1 running, 156 sleeping, 0 stopped, 0 zombie
%Cpu(s): 2.9 us, 5.7 sy, 0.0 ni, 91.4 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
...
id=アイドル状態なので、100-id(=ここでは8.6)がCPU使用率になる。
top -cもしくはpsコマンドでどのプロセスが原因になっているかを調査する。
$ ps auxf
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 25805 0.0 0.1 64264 4072 ? Ss 2015 0:00 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
nginx 25806 2.6 0.7 70196 15224 ? S 2015 2691:21 \_ nginx: worker process
nginx 25807 2.7 0.8 71700 16416 ? S 2015 2725:39 \_ nginx: worker process
...
# メモリ利用率でソートしてみることもある
$ ps auxf --sort -%mem
DBサーバーの場合はSHOW processlist;で長時間実行したままのクエリがないか(=クエリが刺さっている)確認する。
mysql> SHOW processlist;
| 198276 | xx | 10.xx.xx.xx:36336 | test_db | Query | 517824 | statistics | SELECT DISTINCT `xxx`.* FROM `xxx` INNER JOIN `users` ON `users`.`id` =..|

スワップが発生していないか確認する
freeコマンドでSwapのusedを確認する。
$ free -h
total used free shared buff/cache available
Mem: 3.7G 1.1G 747M 366M 1.8G 1.8G
Swap: 1.0G 74M 949M
スワップが発生するのはメモリが不足したということなので、psコマンドで特定のプロセスがメモリを大量消費していないか確認する。

ディスクI/Oを確認する
直近リリースしたプログラムが激しいI/Oを行っていないか開発者に確認する。
(よくあるのはDBサーバーで、一括取得のSELECT(READ)とか、それをCSVに書き込む(WRITE)とか。全件検索&ダンプ出力でメモリにも乗らない処理をバッチで行なっていたり)
必要に応じて処理の分割やキャッシュサーバの導入、メモリ増設を検討する。

最終手段のstrace
# 怪しいプロセスをstraceしてみる
$ sudo strace -p {なんか怪しいプロセスのプロセス番号}
# I/Oのプロセスのどこで詰まっているのか当たりがつけられる
Process 10471 attached - interrupt to quit
read(58, <unfinished ...>
Process 10471 detached
# lsofでプロセスIDを指定して見る
$ lsof -i -a -p {なんか怪しいプロセスのプロセス番号}
# 直接プロセス見てもいい
# sudo readlink /proc/{なんか怪しいプロセスのプロセス番号}/fd/ファイルディスクリプタ番号
$ sudo readlink /proc/10471/fd/58
socket:[1148032788]
# netstat からソケット番号でgrepして接続先を発見する
$ netstat -ane | grep 1148032788
tcp 0 0 10.0.0.10:44566 10.0.0.11:3306 ESTABLISHED 48 1148032788
参考
このスクラップは2022/11/28にクローズされました