ログ日記

作業ログと日記とメモ

pe1650でトラブった

私が居ないときに再起動したらしい。そんでディスクエラー続出だとか。
リモートから入ってもすぐ接続が切れるし、viが見つからないとか特定ファイルをlsしたらsshが切られるとか・・。


shutdownコマンドも受け付けないような状態だったので電源をぽちっと・・。
BIOSではraidにエラーがあるわけではなかったぽい。そんで再び起動したら何の問題もなく動いた。


エラーログには何も出てない。
omsaのログは

# omreport system alertlog

Severity      : Critical
ID            : 2145
Date and Time : Wed Apr 25 20:21:49 2007
Category      : Storage Service
Description   : Controller battery low:  Battery 0 Controller 0

これぐらい。batteryがlowだからって、電源コード差してるのに一部データだけ見れないことってあるのか??
中古品には思わぬ罠が。

dbmailでもトラブった

送信できなくなった。調べるとSMTPが固まっていた。


問題の一つは、ディスクエラー時にもサーバが瀕死状態で動いていたことだと思う。二台のpostgresqlの同期が取れていなかった。特定の問い合わせに対してだけエラーになる。



そしてもう一つは・・今でもよく分かってない。
pgpoolのデフォルト最大接続数の32を超えると固まる。その状態でpostgresqlには接続できる。こっちはデフォルトが100か。どの部分で処理が止まっているのかいまいち分からない。既に接続が閉じているのにCLOSE_WAITで止まっていたり、そうじゃなくてもdbmailが接続を離さなかったり。
時間が来ても一向にリソースを解放する気配がないので、pgpool.confを適当に編集して対応した。num_init_children を増加させて child_life_time と connection_life_time をかなり小さい値にした。


場当たり的な解決ではあるが・・一応ちゃんと動いた。それでもスパムが一度に大量に来ると、しばらく固まる。そういうもんなの?メール処理中はDBに接続しっぱなしなの?
メールサーバのために色々組み合わせすぎて原因の特定が難しい・・。取り敢えずdbmailのソースを読んだ方がいいのかな。



しかしdbmailで検索しても何も出てこないねぇ・・。はてなキーワードにも自分だけだし。たまにヒットしたと思ったらここへのリンクだったりして。



child_life_time と connection_life_time を小さくする意味って何なんだろう・・。一応動くようにはなったけど、いちいちpgpoolの接続切ってたらコネクションプールが効かないよねぇ。。まずはpgpool抜きのpostgresqlのみでdbmailを試すべきだったか。

postfixとdbmailからpgpoolへの接続、接続数

  • smtpd
    • アカウントの存在チェック
select transport from postfix_transport where domain = '*'
select transport from postfix_transport where domain = 'hoge.hoge'
select transport from postfix_transport where domain = 'hoge'
...
select since from dbmail_pbsp where ipnumber = '192x168x10x100ap1.fuga.fuga'
select since from dbmail_pbsp where ipnumber = 'fuga.fuga'
select since from dbmail_pbsp where ipnumber = 'fuga'
select since from dbmail_pbsp where ipnumber = '192.168.10.100'
select username from postfix_users where username = 'from@fuga.fuga'
  • lmtpd
    • メールのアドレスの検索
SELECT deliver_to FROM dbmail_aliases WHERE lower(alias) = lower('hoge@hoge.hoge') AND lower(alias <> lower(deliver_to)
    • メールの配送
BEGIN
SELECT user_idnr FROM dbmail_users WHERE userid='__@!internal_delivery_user!@__'
SELECT mailbox_idnr FROM dbmail_mailboxes WHERE name='INBOX' AND owner_idnr='1'
INSERT INTO dbmail_physmessage (messagesize, internal_data) VALUES ('0', CURRENT_TIMESTAMP)
SELECT currval('dbmail_physmessage_id_seq')
INSERT INTO dbmail_message(mailbox_idnr, physmessage_id, unique_id, recent_flag, status) VALUES( '1', '2', '343af...', '3', 4)
SELECT currval('dbmail_message_idnr_seq')
SELECT physmessage_id FROM dbmail_message WHERE message_idnr = '6')
INSERT INTO dbmail_messageblks (is_header, messageblk, blocksize, physmessage_id) VALUES ('1', 'Return-Path: hoge...', '8', '9')
SELECT currval('dbmail_messageblk_idnr_seq')
...

postfixのプロセスがそれぞれ独立しているもんだから、DBへの接続リソースも独立している。
で、スパマーが10通とか20通とか同時に送ってくると、大量の接続が一気に開かれるわけ。
ここで本文データ格納のための接続が、pgpoolの接続最大数を超えているとリソース待ちになる。



いや・・しかしプロセスがそれぞれ独立しているなら、各プロセスの処理が終わったらDBへの接続を閉じればデッドロック(?)にならないわけだが・・閉じないの?接続を開いたままプロセスが待機しているとか?

# ps -A
...
23468 ?        00:00:00 dbmail-pop3d
23469 pts/5    00:00:00 postmaster
23470 ?        00:00:00 dbmail-pop3d
23471 pts/5    00:00:00 postmaster
23472 ?        00:00:00 dbmail-pop3d
23473 pts/5    00:00:00 postmaster
23474 ?        00:00:00 dbmail-pop3d
23475 pts/5    00:00:00 postmaster
23476 ?        00:00:00 dbmail-pop3d
23477 pts/5    00:00:00 postmaster
...
23482 ?        00:00:00 dbmail-lmtpd
23483 pts/5    00:00:00 postmaster
23485 ?        00:00:00 dbmail-lmtpd
23486 pts/5    00:00:00 postmaster
23487 ?        00:00:00 dbmail-lmtpd
23488 pts/5    00:00:00 postmaster
23489 ?        00:00:00 dbmail-lmtpd
23490 pts/5    00:00:00 postmaster
23491 ?        00:00:00 dbmail-lmtpd
23492 pts/5    00:00:00 postmaster
...


メール配送の処理が終わっても接続を持続させたまま待機していますね・・・。




ってことはですよ。

の設定を行わないと固まるというわけか。



.......
dbmailの設定は

[LMTP]
MAXCHILDREN=200
MAXCONNECTS=10000 # !!!

同じような設定がPOP等にもあるわけで・・・

一度のdbmailへの接続に対して複数のpgpoolへの接続が行われるわけで・・・


えっと・・・


orz



現在のプロセス数が200程度でカーネルの最大プロセス数が16382でメモリが1Gで・・・一体postgresqlのプロセスは何個まで立ち上げられるんだ?混乱してきた・・


# 追記

メモリは先にpostgresqlが使うshared memoryの上限値に引っかかる。取り敢えずプロセスを500ほど立ち上げてみて、様子見。
DBプロセス500で待機とか普通なの?大規模運用したことないから分からん。。
CPUをもりもり積んでるわけでもないので意味は無いんだが・・スパムのためのリソースを用意するっていうのはどうなんだこれ。


http://www.mono-space.net/doc/pgpool.html

num_init_childrenとmax_poolを理解し、正しく設定する。PostgreSQL側から見た最大同時接続数はnum_init_children * max_poolとなるが、クライアント側から見た最大同時接続数はnum_init_childrenとなる。

これ重要。
面倒なのでmax_poolを1に設定。9割以上がdbmailの接続だから大丈夫だろう。



あとは・・・MAXCONNECTS=10000 が気になる。一つのプロセスから大量にDB接続されたらやっぱり固まることになるな・・。