若干改良

uptimeを呼んで数値を得るのではなくて直接/procから数値を読むようにした。
同時にswapの空きが10Mを切ったときも、リスタートするように変更。

元の書き殴りじゃあんまりなのでちゃんとstrictとwarningsを指定した。しばらく使いそうだしね。

#!/usr/bin/perl
use strict;
use warnings;

my $limit15 = 10;
my $limit5  = 15;
my $limit1  = 30;
my $limitM  = 10 * 1024;

print "$limitM:$limit15:$limit5:$limit1\n";

while(1){

    my $swapFree = 0;
    my $load15 = 0;
    my $load5 = 0;
    my $load1 = 0;

    open MEMINFO,"/proc/meminfo" or die;

    while(<MEMINFO>){
        next unless /^SwapFree/;
        my @workTbl = split(/[\s:]+/);

        $swapFree = $workTbl[1]+0;
    }

    close MEMINFO;

    open UPTIME,"/proc/loadavg" or die;

    while(<UPTIME>){
        my @workTbl = split(/[\s,]+/);

        $load15 = $workTbl[2] + 0;
        $load5 = $workTbl[1] + 0;
        $load1 = $workTbl[0] + 0;
    }

    close UPTIME;

    my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time());
    $mon += 1;
    $year += 1900;

    if($load15 > $limit15){
        if($load5 > $limit5){
            if($load1 > $limit1){
                print '('. join(':',($swapFree,$load1,$load5,$load15)).") restart at $year/$mon/$mday $hour:$min:$sec : cpu busy\n" ;
                system("/sbin/service httpd restart");
                sleep(60);
            }
            else {
                print ' ('. join(':',($swapFree,$load1,$load5,$load15)).") step2 at $year/$mon/$mday $hour:$min:$sec \n" ;
            }
        }
        else {
            print ' ('. join(':',($swapFree,$load1,$load5,$load15)).") step1 at $year/$mon/$mday $hour:$min:$sec \n" ;
        }
    }

    if($swapFree <= $limitM){
        print '('. join(':',($swapFree,$load1,$load5,$load15)).") restart at $year/$mon/$mday $hour:$min:$sec : memlow \n" ;
        system("/sbin/service httpd restart");
        sleep(30);
    }
    sleep(10);
}

うお

今、負荷が想定を超えて、強制リスタートモニターが起動はした。

が、総定数よりもかなり過負荷にならないとロジックが発動しない……そりゃそうか、中でプロセス起動してるものなあ、監視もリスタートも。

と言うわけで、とりあえず過負荷のまま遷移はしないことはわかったけど、もうちょっとロジックを考えた方がよさそう。

全然資源が足りないっぽい……

ごはん食べて帰ってきたら、ロードアベレージ119.7とかでスラッジングをおこして事実上システム停止してた……。swapのフリーが0Kとかどう見てももうだめ。

再びさくらインターネットに連絡してリブート。

常駐プロセスのうち、運用上の必要度が低いものから数個止めた。具体的にはファイアウォールログをMySQLに書き込んでwebから履歴参照できるようにするデーモンと、clamav。clamavはもうこのサーバーでメール受けてないし、使ってる人もボクだけだから、ローカルでチェック済みのものをアップロードする分にはファイルシステム内スキャンは必要ないだろうと。

で、どうかなー?

現時点での.screenrc

なんかどうにも負荷がかってスラッジングをおこしがちなので、とりあえず状況を常時監視することにした。

~/.screenrc

defutf8 on
defkanji UTF-8
defencoding UTF-8
encoding UTF-8 UTF-8
defscrollback 10000
autodetach on
startup_message off
multiuser on
caption always "%n %t %= %{=b wk} %{=s wb}%y/%m/%d %{=s wb}%02c"
bind ^e encoding eucJP UTF-8
bind ^u encoding UTF-8 UTF-8
bind ^w encoding sjis UTF-8
bind ^j encoding jis UTF-8
chdir
screen -t "top +" /usr/bin/top
scrollback 0
split
focus down
screen -t "vmstat +" /usr/bin/vmstat 10
scrollback 200
split
focus down
chdir tiarra
screen -t "tiarra: errlog.stderr" /usr/bin/less errlog.stderr
screen -t "tiarra: errlog.stdout" /usr/bin/less errlog.stdout
chdir
screen -t "sakura.fairies.jp"
screen -t "* work tty *"

まあ、別途負荷がかかったときの対策なり、負荷がかからないようなチューニングが必要という前提で。

MySQLチューニング

結局MySQLのプロセスがいっぱいメモリーをとってスラッジングしているのが原因のような気がする。
ので、例によって適当にチューニング。

以下を /etc/my.cnf に挿入

# Tuning Memory Usage
innodb_buffer_pool_size=512M
innodb_additional_mem_pool_size=20M
innodb_log_buffer_size=16M
innodb_log_file_size=128M
sort_buffer_size=2M
read_rnd_buffer_size=1M
join_buffer_size=256KB
read_buffer_size=1M
key_buffer_size=256M
myisam_sort_buffer_size=1M
net_buffer_length=16384
max_connections=100
innodb_log_files_in_group=2

何かメモリーリークしてた?

よくよく見てるとすごくswapが消費された状態だったので、いったんリブートしてみた。

どうかしら?

っていうか、別の問題として、shutdown -r new だと起動途中で止まってしまうっぽく、さくらさんにリセットコールしなきゃいけなかったのと、tiarraが

weaken is only available with the XS version of Scalar::Util at main/ModuleManager.pm line 12

というエラーで起動しない問題があるのだけれど。

apacheのチューニング

今までは、さくらの専用サーバエントリーのデフォルトというか、おそらくCeontOS4のデフォルト値のまま運用してきてたのですが。

ググルさんのクローラーがきたときとかはともかく、POST時にものすごくロードアベレージが上がるのでどうしようかと。

大名管理者的にはメモリとCPUの大きなメニューに変更するか、機能を分散配置するんだろうけど。さくらのVPSが逆引きできればいくつかのサーバに分散してもやすくなるんだけど、とりあえず現状では無理だし、どうしようかと。

で、とりあえず、今までデフォルトのまま運用していたapacheのパラメタを見直そうかと言うことで。

/etc/httpd/conf/httpd.conf
変更前:

KeepAlive Off
MaxKeepAliveRequests 100
KeepAliveTimeout 15
ServerLimit      256
MaxClients       256
MaxRequestsPerChild  4000

変更後:

KeepAlive On
MaxKeepAliveRequests 50
KeepAliveTimeout 10
ServerLimit      100
MaxClients       100
MaxRequestsPerChild  400

変更後の数字は適当。本当はちゃんと計算すべきな気もする。とりあえず運用して具合を見ようかと。