■ mod_resource_checker [Download](apcheリソースloggingモジュール)
サーバー内で複数のWEBサービスを提供したい場合に、chroot環境でのIPベースと、Virtualhostを用いたnameベースがある。
IPの枯渇や、ハードウェアにあまりお金をかけない、プロセス数の問題などで、最近ではnameベースを用いてサービスを提供することが多い。
ただし、nameベースでは様々な問題が起きる。
例えば、
- VirtualHost毎にログを残す場合、VirtualHostの数が増えてくると、fdの数が足りなくなる
- セキュリティ的にsuEXEC環境をとらないといけなくなる
- DSO版phpにも対応できるようにmod_ruidを使わないといけない
- mod_ruidを使うとCAPABILITYの問題で、request毎にプロセスを破棄しないといけなくてパフォーマンスが落ちる
など・・・
書き出すと、nameベースっていうのは結構な問題を抱えているんだが、今回はnameベースでのひとつの問題である、リソースを消費しているCGIやPHPの特定できない事象を解決するためのモジュールを作ってみた。
suEXECやmod_ruidを使わなかった場合、cgiやphpがapache権限で実行されたりとか、apacheプロセスとして実行されたりするため、高負荷時に迅速に該当のプロセス及びスクリプトに対して制限をかけないときに、なかなか特定できない。
(/proc/pid以下をごりごり探索するのもありだが、pidがコロコロ変わってしまったりと、特定に手間がかかる。)
そのため、今回はあapacheにrequestがあった段階から、responseを返すまでに消費したリソース量をVirtualHost毎にファイル単位でログを残したい。
今回のモジュールはシステムコールのrusageを使って、CPUユーザー使用時間、CPUシステム使用時間、メモリ使用量、を記録する。(.htaccess対応)
実行方法としては、対象をディレクトリ単位でロギングしたい場合、
<Directory "/var/www/html">
RCheckUCPU 0.0001 ALL
</Directory>
対象を、特定のファイル名にしたい場合、
<Files "hoge.cgi">
RCheckUCPU 0.003 ALL
RCheckSCPU 0.004 ALL
</Files>
対象を、正規表現にマッチするファイル名にしたい場合、
<FilesMatch "^.*¥.cgi$">
RCheckUMEM 0.005 ALL
</FilesMatch>
のように書く。
第一引数に閾値、第二引数に計測タイプを指定する。
閾値に関して、CPU系は閾値にCPU使用時間(sec)で指定し、MEM系はメモリ容量(MB)で指定する。
閾値以上の場合に、ログに記録される。
計測タイプは、ALLで自身のプロセスがフォークしたプロセスのリソース量も含めた値を計測し、SELFはフォークしたプロセスは無視して自分自身のみのリソース量を計測する。
CHILDはフォークしたプロセスのみのリソース量を計測する。
一応は途中まで1.3系に対応させようと思っていたが、とりあえず動くのをつくろうと思って途中から2系で作ってしまっていた。
コンパイルオプションで1.3系を指定できるようにはしているが、未完成である。
2系で32ビット64ビットに対応(したつもり)している。
生成するログファイル先はソース内で指定しているので、confで指定できるように書き換えるなり、ソースを書き換えるなりして使うと良いと思う。
#define MOD_RCHECKER_LOG_FILE "/usr/local/apache/logs/mod_rchecker.log"
#endif
#ifdef __MOD_APACHE2__
#define MOD_RCHECKERLOG_FILE "/var/log/apache/mod_rchecker.log"
コンパイルは、
apxs -c -D__MOD_APACHE2__ mod_rchecker.c
syslogにDEBUG出力をしたい場合は、
apxs -c -D__MOD_APACHE2__ -D__MOD_DEBUG__ mod_rchecker.c
でコンパイルする。
できたバイナリは指定のmoduleディレクトリにいれて、loadmoduleすればよい。
LoadModule rchecker_module modules/mod_rchecker.so
ログフォーマットは以下。
mod_rchecker_log_buf = (char *)ap_psprintf(p
, "[%s] pid=%d %s %.5f (%s) > threshold=(%.5f) ] config_dir=(%s) src_ip=(%s) access_file=(%s)\n"
, log_time
, getpid()
, msg
, resource_time
, process_type
, threshold
, pRcheckerDirConf->target_dir
, pAccessInfoData->access_src_ip
, pAccessInfoData->access_file
);
># apxs -c -D__MOD_APACHE2_ mod_rchecker.c
># apxs -c -D__MOD_APACHE2_ -D__MOD_DEBUG__ mod_rchecker.c
些細な事ですが、-Dオプションが誤っています。
x -D__MOD_APACHE2_
o -D__MOD_APACHE2__
はじめまして。
本当ですね、ありがとうございます。
はじめまして
mod_rcheckerを利用して高負荷CGIの検出等を行なっています
素晴らしいモジュールの公開、ありがとうございます。
図々しい意見かもしれませんが、もし宜しければ
mod_rchecker及びmod_process_securityで
AddHandlerでCGIの拡張子を変えた際の検出に対応していただければ嬉しいです
無茶な要求かもしれませんが、要望として受け取って頂ければ幸いです。
>> anyさん
はじめまして。
いえいえ、意見を頂ける事はとてもうれしいです、ありがとうございます。
検討しますので、もしよろしければGitHubにissueとしてあげて頂く事は可能でしょうか?
https://github.com/matsumoto-r/mod_process_security
https://github.com/matsumoto-r/mod_resource_checker
すみません、あとtwitterで声かけて頂けると一番早く反応できると思います。
https://twitter.com/matsumotory