このブログを検索

2011年6月24日金曜日

[Postfix]特定のドメインのみ受信しそれ以外は別アドレスに転送する

特定のドメインのみ受信し、それ以外は別アドレスに転送する設定をします。
IPフィルタ、ドメイン偽装などはひとまず触れません。

ケータイのドメインのみ受信し、それ以外はスパム候補として別アドレスに転送する設定をしました。
今回は、少しややこしいのですが、このフィルタリングをしたメールをメールボックスおよびalias転送をします。
システムの構成や細かな要件によっては他にもやり方はあると思います。

今回の構成は次の通り。
 |送信元|
   ↓
 |Postfix|
<フィルタリング>   ⇒info@doubt.spam
  ↓  ↓ 
 MBox info@alias.to

まず、許可ドメインのアクセステーブルを作成します。
※ファイル名は任意です

# vi /etc/allow_domains
indexweb.co.jp  OK
docomo.ne.jp    OK
vodafone.ne.jp  OK
disney.ne.jp    OK
softbank.ne.jp  OK
    :

# /usr/sbin/postmap /etc/allow_domains 

# ls -l /etc/allow_domains*
-rw-r--r-- 1 root root   283  6月 23 18:39 /etc/allow_domains
-rw-r--r-- 1 root root 12288  6月 23 18:39 /etc/allow_domains.db

次にNGドメインのテーブルを正規表現で記述します。
今回はregexpで作りましたが環境や流量によってはpcreでもいいかもしれません。
また、正規表現を工夫して特定地域ドメインだけをリダイレクトすることもできると思います。
※これもファイル名は任意です

# vi /etc/redirect_domains
/^.+@.+$/ REDIRECT info@doubt.spam

# /usr/sbin/postmap /etc/redirect_domains

# ls -l /etc/redirect_domains*
-rw-r--r-- 1 root root    41  6月 23 18:51 /etc/redirect_domains
-rw-r--r-- 1 root root 12288  6月 23 18:51 /etc/redirect_domains.db

最後にmain.cfに次のように記述してreloadします。
smtpd_sender_restrictionsの判定は、alias判定の前に行われるので、aliasesには影響を与えません。
smtpd_sender_restrictions = hash:/etc/allow_domains,check_sender_access regexp:/etc/redirect_domains

# /usr/sbin/postfix check
# /etc/rc.d/init.d/postfix reload

特定地域ドメインだけをリダイレクトし、それ以外は拒否するのであれば、smtpd_sender_restrictionsの最後に", reject"と追加するといいかと思います。(すみません、これは検証してません)

2011年6月22日水曜日

[syslog]syslog-ngでApacheログを集約してみた

syslog-ngを使ってApacheのaccess_logを1箇所に集約してみました。
発端は、PHPやApacheのerror_logを、リリース直後に1箇所でtailしたい要望があったためです。
また、access_logの集計に使っている商用ソフトウェアを廃止することによるコスト削減も狙っていました。

結論から言えば、かなり残念な結果に。

Webサーバ2台で検証環境ですらかなりのCPUを消費するので、Webサーバが10台以上ある本番環境では使いものにならないように思います。


ボクの感想としては2つ。
・I/Oがボトルネックになると予測していたのでディスクアレイも検証したのに残念。
・ベンチか設定が間違ってるだけと信じたいですが、そもそも1GB超/1台/日のaccess_logを処理するのはやはり無理か・・・。

ちなみに、Webサーバで内蔵ディスクにTCP出力しているのは、syslogサーバの取りこぼしに備えてです。
access_logの精度を求めるなら内蔵ディスク、概算やerror_logのエラー検知ならsyslogサーバ、と使い分けるつもりでした。


詳細は次の通り。

まず、負荷試験の構成。
|負荷試験サーバ|
   ↓
|Webサーバ x 2|
     ⇒内蔵ディスクにもログ出力
   ↓
|syslogサーバ|
     ⇒内蔵ディスク or ディスクアレイ

・WebサーバのApacheは、access_log、error_logともにsyslog出力
・Webサーバのsyslogは、TCPで内蔵ディスクにファイル出力
・Webサーバのsyslogは、TCP/UDPでsyslogサーバに転送
・syslogサーバは、内蔵ディスクやディスクアレイにファイル出力

検証には次のような機器を使いました。
(Webサーバ)
CPU: Xeon E5640(Quad)
内蔵ディスクRAID: 5

(syslogサーバ)
CPU: Xeon E5502(Dual)
内蔵ディスク: SATA2, RAID5
ディスクアレイ: SATA2, RAID5, SCSI

設定内容は次のように、logger経由でsyslog転送しました。
(Webサーバ)
$ cat /etc/httpd/conf/extra/httpd-vhost.conf

    CustomLog      "| /bin/logger -p local3.info -t aplog001i" combinedmob_uniq
    ErrorLog      "| /bin/logger -p local3.info -t aperr001i"

$ cat /etc/syslog-ng/syslog-ng.conf
# Apache log
destination     d_aplog001i  { file("/home/www/sss01test/running/logs/apache/mobile/i/access_log" owner(root) group(root) perm(0644) template("$MSGONLY\n") template_escape(no)); };
filter          f_aplog001i  { facility(local3) and program("aplog001i"); };

log   { source(s_sys); filter(f_aplog001i); destination(d_aplog001i); };
log   { source(s_sys); filter(f_aplog001i); destination(d_ulog_sss01); };

(syslogサーバ)
$ cat /etc/syslog-ng/syslog-ng.conf
destination d_aplog001i { file("/var/log/httpd-ng/access_log.aplog001i_stb" owner(root) group(root) perm(0644)); };
#destination d_aplog001i { file("/mnt/das/testsyslog/access_log.aplog001i_stb" owner(root) group(root) perm(0644)); };
log { source(t_server); filter(f_host_stb); filter(f_aplog001i); destination(d_aplog001i); };

負荷試験はシンプルにApache Benchを使い、TCPやUDPの違い、出力ストレージの違いを調べました。
グラフは、各サーバのCPU使用率(user, sys)です。

CPU使用率はUDPの方が5%増しくらいですが、処理時間はUDPの方が倍くらい速いです。
UDPでの取りこぼし率は0.00194%でしたが、もしかしたら台数が増えるとどこかのタイミングで急増するんでしょうか。
ストレージの差がもっと出るかと思いましたが、たぶんCPUがボトルネックで違いが現れないのだと思います。

機会があればAmazonなどで追試をしてみたいと思います。

上から(c200, n200000, TCP, syslogは内蔵ディスクへ出力)、(c200, n200000, UDP, syslogはディスクアレイへ出力)

2011年6月9日木曜日

[コマンド]wgetを標準出力に表示しeAcceleratorの使用状況を確認する

サンプルPHPは次の通りで、ピークPHPメモリやeAcceleratorメモリ状況をレポートするもの。
これをDocumentRootに設置しておきます。
余談ですが、私はCloudForecastでこのPHPを定期監視しています。
 $einfo_val) {
  if ($einfo_key != "version" && $einfo_key != "logo") {
    echo $einfo_key . ":" . $einfo_val . "\n";
  }
}

$resusage = getrusage();
echo "ru_oublock:" . $resusage["ru_oublock"] . "\n";
echo "ru_inblock:" . $resusage["ru_inblock"] . "\n";
echo "ru_minflt:" . $resusage["ru_minflt"] . "\n";
echo "ru_majflt:" . $resusage["ru_majflt"] . "\n";
echo "ru_nvcsw:" . $resusage["ru_nvcsw"] . "\n";
echo "ru_nivcsw:" . $resusage["ru_nivcsw"] . "\n";
echo "ru_nswap:" . $resusage["ru_nswap"] . "\n";
echo "ru_utime:" . $resusage["ru_utime.tv_usec"] . "\n";
echo "ru_stime:" . $resusage["ru_stime.tv_usec"] . "\n";
?>

このwgetし、さらにgrepします。
-qで問合せやダウンロード表示を抑制し、-O -で標準出力に表示します。
--headerでHostを指定しているのは、単に私の環境がVirtualHostで管理しているためなくてもOKです。
hostnameコマンドは、各Webサーバに配布したスクリプトで記述したことがあるためこれもなくてOKです。
[t-itoh@snwadm0 eaccel96]$ wget -q -O - --header='Host: zzzz.webwebweb.co.jp' http://`hostname -s`/phpstats.php | grep ^memory[A-Z]
memorySize:134217672
memoryAvailable:44576
memoryAllocated:134173096

2011年4月22日金曜日

[Apache]Combined Log Formatの分間アクセス数を整形表示する

Apacheのログ形式がcombinedの場合で、分間アクセス数を整形表示します。
niceはつけてもつけなくても。
なお、この例ではリクエストドメインでの判定もしたいのでHostリクエストヘッダを追加しています。
$ nice -n 19 zcat /usr/local/apache/logs/access_log.Apr.16.gz | egrep 'soft|ez-soft|j-soft|w-soft|mytown' | cut -d' ' -f4 | cut -d: -f1-3 | sed -e "s/^\[//g" | sort | uniq -c
      8 16/Apr/2011:02:05
      7 16/Apr/2011:02:06

sortが必要なのは次の理由から。
高負荷時は、各リクエストの出力順番がズレる可能性があるためです。
・Combined Log Formatの時刻(%t)は、リクエストを受け取った時刻
・ログ出力されるのは、レスポンスを返したタイミング

長期間を調べる時は、10分ごとで。
$ nice -n 19 zcat /usr/local/apache/logs/access_log.Apr.15.gz | tail -5000 | egrep 'soft|ez-soft|j-soft|w-soft|mytown' | cut -d' ' -f4 | cut -d: -f1-3 | sed -e "s/.$//g" | sed -e "s/^\[//g" | sort | uniq -c
   2959 14/Apr/2011:13:2
   1889 14/Apr/2011:13:3

2011年4月3日日曜日

[MySQL]Maatkitを使ってサイズの大きいテーブルを探す

Maatkitで好きなコマンドの1つ、mk-find。
findコマンド互換のオプションなのでわかりやすい。

例えば、サイズが500K以上のテーブルを探す。
$ mk-find --tablesize +500k -hsssdbmra1 -ucheck --ask-pass
実行例は、次の通り。
Enter password: 
`area001i`.`t01_area_item_hist1`
`area001i`.`t01_area_temp_prev1`
`area001i`.`t01_area_user1`
`area001i`.`t01_area_user_item1`
`area001i`.`t01_area_user_stage1`

2011年3月8日火曜日

[MySQL]分離レベルを設定する

my.cnfのmysqldセクションに記述し、再起動すると反映されます。
set global transactionすることもできるようです。
分離レベルの詳細は公式InnoDB と TRANSACTION ISOLATION LEVELを参照してください。
[mysqld]
transaction-isolation=READ-COMMITTED
設定すると次のように表示されます。
mysql> show variables like 'tx_isolation';
+---------------+----------------+
| Variable_name | Value          |
+---------------+----------------+
| tx_isolation  | READ-COMMITTED |
+---------------+----------------+

2011年3月4日金曜日

[MySQL]スローログクエリを調査する

パッケージに同梱されているmysqldumpslowはスローログクエリを調査するのに便利です。
オプションを付けないと、次のようにリテラル値が表示されなかったり実行順にされます。
$ mysqldumpslow /var/lib/mysql/sssdbmy01-slow.log

Reading mysql slow query log from /var/lib/mysql/sssdbmy01-slow.log
Count: 2  Time=6.96s (13s)  Lock=0.00s (0s)  Rows=5844505.0 (11689010), backup[backup]@localhost
  SELECT /*!N SQL_NO_CACHE */ * FROM `t01_quiz0_user_item1`

Count: 2  Time=3.31s (6s)  Lock=0.00s (0s)  Rows=2649981.0 (5299962), backup[backup]@localhost
  SELECT /*!N SQL_NO_CACHE */ * FROM `t01_quiz0_user_area1`
               :
よく使っているオプションは、-a(リテラル値の表示)、-g(パターンマッチング)、-s(ソート)です。
次の例は、リテラル値の表示、カラムitem_qtyで検索、クエリタイムの降順ソートです。
$ mysqldumpslow -a -g item_qty -s t /var/lib/mysql/sssdbmy01-slow.log 

Reading mysql slow query log from /var/lib/mysql/sssdbmy01-slow.log
Count: 1  Time=12.49s (12s)  Lock=0.00s (0s)  Rows=7.0 (7), quiz0001iuser[quiz0001iuser]@sssdev1.sss.examples.co.jp
  select item_qty,count(user_id) item_qty from t01_quiz0_user_item1 where item_qty<>99
  group by item_qty
  order by item_qty

Count: 1  Time=2.02s (2s)  Lock=0.00s (0s)  Rows=7.0 (7), quiz0001iuser[quiz0001iuser]@sssdev1.sss.examples.co.jp
  select distinct item_qty from t01_quiz0_user_item1