Kodama's home / tips.
ls|sort -n|xargs -l grep -E '(Subject)|(Date)|(Requests)'更に, 整形する.
gawk '/Subject/{if(s~/net_check/){print d" 0"};s=$2}/Date/{d=$4" "$5}/bytes.*in.*Requests/{print d" "$5;s="";next}/Requests/{s=""}'この結果を月ごとに集計する.
gawk '(($1" "$2)!=d){if(n>0){print d" "s/n" "m};m=0;s=0;n=0}{d=$1" "$2;s=s+$3;n=n+1;if(m<$3){m=$3}}'
月ごとの集計結果. mailq による キューサイズ(1時間毎に測定)の 平均 最大
Jan 2006 221.078 304 Feb 2006 128.705 360 Mar 2006 270.508 472 Apr 2006 209.83 380 May 2006 255.063 419 Jun 2006 376.197 746 Jul 2006 430.722 889 Aug 2006 1297.07 2780 Sep 2006 603.092 872 Oct 2006 642.896 1094 Nov 2006 1176.89 1599 Dec 2006 2042.28 3048 Jan 2007 1759.06 27402006 年当初までは, postfix のデフォルトの設定で使用していた. 2006.1月辺りに, キューがしばしば 300を越えるようになってきた. これは, 総当たり的に送りつけて来る SPAM のバウンスに依るものと思われる. そのため, 送信のためのプロセス数が上がって, postfix の制限に抵触して, 通常のメールの送受にも支障が出て, メールの配送がほとんど停止に追い込まれた.
SPAM は実在するアカウントの名簿を元に一斉に送るものと, ありがちなアカウント名の一覧を元に総当たり的に送るものとがある. このうち後者の場合は, 実在しない者あてのメールとなってしまう事が多い. 実在しない者宛のメールは発送元サーバに返送されることになる. しかし, SPAM の場合, 発送元サーバを偽装している事が多く, 返送に失敗してしまう. 返送に失敗したメールは, 外部宛サーバに滞留し, サーバは定期的に配送を試みる. 滞留したメールが多くなって, それがサーバの制限に抵触するようになると, 他の正常なメールの送受にも影響する.
2月に,一旦, access リストによる受信制限をつけて, サーバの状態を回復させ, 同時に, 設定の調整 を行った. その後, サーバの調整の後に制限を解除した. 2月の平均値が下がっているのはこの期間の影響.
現在(2007.2)は, 2006年当初の 10倍程度の負荷となっているが, サーバ自体は問題なく動作している. 回線速度に余裕があるので, 他の用途(WWWなど)には影響は出ていない.
ネットワークから着信--smtpd--cleanup--(incomingキュー)--qmgr(active,deferredキュー)--local,smtp,pipe
他のサーバからの受信の状況は smtpd の動作を観察すると良い. 他のサーバへの送信や転送の状況は smtp の動作を観察すると良い.
該当するユーザ名がないなどの理由で local が配送できなかった場合は, 一旦 bounce スプール(/var/spool/postfix/bounce)に置かれ qmgr が処理する. また, smtp で他に転送しようとして 転送できなかった場合には deferred スプール(/var/spool/postfix/deferred) に置かれ, 一定の時間が経過した後に再度 smtp に引き渡されて転送が試みられる. スプールの状況は mailq コマンドで見ることができる.
$ netstat -A inet -n Active Internet connections (w/o servers) Proto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0 10.20.30.40:25 xx.xx.xx.xx:12345 ESTABLISHED tcp 0 0 10.20.30.40:23001 yy.yy.yy.yy:25 ESTABLISHED tcp 0 0 10.20.30.40:23002 zz.zz.zz.zz:25 SYN_SENT ....略SMTP ポートの利用数をしらべるのは次のように, :25 の部分を grep で取り出し, wc で計数すると良い.
受信による25番ポートの利用数: この例では 3個の接続があることがわかる.
$ netstat -A inet -n | grep :25 | grep 10.20.30.40:25 |wc 3 18 243
送信による25番ポートの利用数: この例では 11個の接続があることがわかる.
$ netstat -A inet -n | grep :25 | grep -v 10.20.30.40:25 |wc 11 66 891
送信のうち State が SYN_SENT になっているものは, 相手方への接続を試みたが, 接続が確立できていない状態を表す. これが多い場合は, mailq でみたときにメールが溜っていることが多い. (タイムアウトでメールを送信できないため.)
netstat -n -A inet | grep SYN_SENT | wc 11 66 891
メールの送信時の qmgr から smtp への引き継ぎは UNIX ソケットを用いている.
$ netstat -A unixソケットの利用数をしらべるには次のようにする. (/smtp の部分を grep で取り出し, wc で計数する.)
$ netstat -A unix | grep /smtp | wc 11 88 792これは, 送信による25番ポートの利用数と対応している.
# ps -U postfix -o args | sort | uniq -c | sort -nr 23 smtp -t unix -u -c 4 smtpd -n smtp -t inet -u -c 2 cleanup -t unix -u -c 1 trivial-rewrite -n rewrite -t unix -u -c 1 qmgr -l -t fifo -u -c 1 pickup -l -t fifo -u -c 1 COMMANDこの例では smtp が 23個, smtpd が 4個起動している. smtp は送信用, smtpd は受信用のプロセス.
停電やネットワーク障害などでサーバが止まっていた後の回復時には, 他サイトからメールが大量に流入することになり, 一時的に負荷が高くなる. 特に smtp と smtpd の起動数が問題となる.
プロセスの同時起動数は postfix の master.cf で設定できる.
$ mailq ... ...略 (個々のメールについて配送出来なかった理由の概略が表示されている) ... -- 3789 Kbytes in 408 Requests.この例では 408 通のメールがキューに滞留している.
上で略した個々のメールを配送できなかった理由をまとめてみるには 次のようにする. 滞留の理由の上位5位を表示してみた.
$ mailq | gawk '/\(/{$1=$1;print}' | sort | uniq -c | sort -nr | head -5 30 (connect to boranch2.mailya.net[58.4.46.57]: Connection timed out) 18 (Name service error for internationalcspedition.com: Host not found, try again) 7 (connect to mx1.aex.com[10.23.42.11]: Connection timed out) 6 (connect to null.com[207.44.141.137]: Connection refused) 6 (Name service error for e-standard.biz: Host not found, try again)
qshape コマンドを使う方が良いらしい.
$ free total used free shared buffers cached Mem: 1024796 1011848 12948 0 59040 346600 -/+ buffers/cache: 606208 418588 Swap: 151192 452 150740
$ cat /proc/sys/fs/file-max 202056 # cat /proc/sys/fs/file-nr 3680 0 202056この例では同時オープンの限界は 202056. 現在の使用数は 3680.
#!/bin/sh MY_ADDRESS=10.20.30.40 echo -n inet_smtp_receive netstat -n -A inet | grep :25 | grep $(MY_ADDRESS):25 | wc echo -n inet_smtp_send netstat -n -A inet | grep :25 | grep -v $(MY_ADDRESS):25 | wc echo -n inet_SYN_SENT netstat -n -A inet | grep SYN_SENT | wc echo -n unix_smtp netstat -A unix | grep /smtp | wc echo process ps -U postfix -o args | sort | uniq -c | sort -nr echo mailq mailq | grep Requests mailq | gawk '/\(/{$1=$1;print}' | sort | uniq -c | sort -nr | head結果の例:
inet_smtp_receive 4 24 324 inet_smtp_send 72 432 5832 inet_SYN_SENT 70 420 5670 unix_smtp 72 576 5184 process 75 postfix smtp -t unix -u -c 2 postfix smtpd -n smtp -t inet -u -c 2 postfix cleanup -t unix -u -c 1 postfix trivial-rewrite -n rewrite -t unix -u -c 1 postfix qmgr -l -t fifo -u -c 1 postfix pickup -l -t fifo -u -c 1 USER COMMAND mailq -- 3043 Kbytes in 467 Requests. 29 (connect to XXXXXXXXXX.net[XX.XX.XX.XX]: Connection timed out) 20 (connect to XXXXXX.com[XX.XX.XX.XX]: Connection refused) 11 (Name service error for XXXXX.biz: Host not found, try again) 9 (connect to XXXXXX.co.jp[XX.XX.XX.XX]: No route to host) 6 (connect to null.com[XX.XX.XX.XX]: Connection refused)
このほか, CPUの利用状況, メモリー, ディスク, ネットワークの負荷などを ps, top, vmstat, df, df -i, free などのコマンドで調べるが, これらは postfix に特有の問題ではないので ここでは割愛する.
cron (man crontab) で定期的にデータを取って, ファイルに落とすか, 自分にメールすると良い. 以下は, 1時間毎にメールする例.
# MIN HOUR DAY MONTH DAYOFWEEK COMMAND 0 * * * * my_script.sh > mailx -s net_check my-mail-addr@math.kobe-u.ac.jp
# cat /proc/sys/kernel/threads-max 14336次のようにして調整する.
# echo 20000 > /proc/sys/kernel/threads-max # cat /proc/sys/kernel/threads-max 20000または /etc/init.d の適当なファイルか, /etc/sysctl.conf に記述する.
sysctl.conf の例:
kernel.threads-max = 20000
$ /usr/sbin/postconf | grep default_process_limit default_process_limit = 50
起動数の設定が少すぎる場合の問題:
# cat /proc/sys/fs/file-max 202056 # echo 300000 > /proc/sys/fs/file-max # cat /proc/sys/fs/file-max 300000また, 起動時にこれを行うように, /etc/init.d の適当なファイルか /etc/sysctl.conf に記述する.
/etc/sysctl.conf の例:
fs.file-max = 300000
送信キューにメールが溜ることで明らかになる問題:
$ postconf | grep qmgr_message_active_limit qmgr_message_active_limit = 10000
# main.cf smtpd_client_restrictions = permit_mynetworks, check_client_access hash:/etc/postfix/access/etc/postfix/access ファイルの例. 変更後は postmap /etc/postfix/access で hash テーブルを更新する.
# access co.jp OK ad.jp OK go.jp OK ac.jp OK so-net.ne.jp OK ezweb.ne.jp OK docomo.ne.jp OK vodafone.ne.jp OK 221.207.172 REJECT 221.207.173 REJECT制限した場合の問題点:
mail.* -/var/log/mail.log
Kodama's home / tips.