Windows server上に、Windowsドメイン認証のできるSubversionサーバを構築してハマる。
主な環境
サーバ
CPU | Intel(R) Xeon(R) CPU 5160 @ 3.00GHz |
---|---|
Memory | 3.00GB |
O/S | Microsoft Windows Server 2003 Standard Edition Service Pack2 |
その他 | Apache/2.2.13 (Win32), SVN/1.6.4 |
Compiled in modules: core.c mod_win32.c mpm_winnt.c http_core.c mod_so.c|
httpd.confに追加
LoadModule sspi_auth_module modules/mod_auth_sspi.so LoadModule dav_svn_module modules/mod_dav_svn.so LoadModule authz_svn_module modules/mod_authz_svn.so <Location /svn> DAV svn SVNPath "E:/svnrepository" AuthType SSPI AuthName "Authentication request from Subversion." SSPIAuth On SSPIAuthoritative On SSPIDomain MYDOMAIN SSPIOfferBasic On Require valid-user </Location>
クライアント(代表例)
CPU | Intel(R) Pentium(R) 4 CPU 2.80GHz |
---|---|
Memory | 2.50GB |
O/S | Windows XP Professional Version 2002 Service Pack 2 |
その他 | TortoiseSVN 1.6.5, Subversion コマンドラインクライアント, バージョン 1.6.4. |
一応、こんな感じで基本動作はするようになった。
が、念のため、開発ピーク時の負荷を想定して、20人がかりで一斉にcheckoutをかけてみたところ、Apacheがダウン。
ここから、ハマり道が始まった。
同時接続数が多すぎて捌ききれないのかもしれない
httpd-mpm.confで、以下の値を調整。
<IfModule mpm_winnt_module> # 150→500 ThreadsPerChild 500 # 0→10000 MaxRequestsPerChild 10000 </IfModule>
もう一度同じ負荷をかけたところ、Apacheが落ちなかったので、これで安心と思ったら、しばらくたつとやっぱり落ちた。
どこに負荷がかかっているのだろうか
Windows タスク マネージャでパフォーマンスタブを確認。
PF使用量が非常に高い。
プロセスタブを確認すると、httpd.exeが最大で約2GBも使用している。パフォーマンスモニターのカウンタログで、Processor/Memory/PhysicalDiskの負荷状況を記録すると、Memory/Available MBytesがどんどん落ちていく。CPU/HDDの負荷は許容範囲内。
負荷テストを毎度20人がかりで行うのはしんどい
use strict; use warnings; my $pid; for(my $i = 0; $i < 10; $i++){ mkdir($i); if ($pid = fork()){ print "親プロセス(" . $pid . ")です。\n"; } elsif(defined $pid){ print $i . ":子プロセス(" . $pid . ")です。\n"; chdir($i); system("svn co http://foo/svn --username bar --password baz"); last; } else{ print "親でも子でもないです。\n"; } }
同一IPからのアクセスになるが、ちゃんと別々のフォルダにcheckoutされ、負荷テストの状況(メモリ空き容量がどんどん減っていく)を再現できた。処理速度的にはクライアント側のDisk I/Oが律速になっているようだが、問題は再現する。
問題の元がメモリリークならば
何度も負荷テスト→負荷テスト→負荷テスト→サーバのメモリ逼迫→何かの拍子にApacheダウンというのを繰り返してみて、感覚的に"svn coするとどんどんApacheがメモリを喰う"という線が濃厚になってきた。
Windows + Apacheの環境では、AcceptEXが問題になるケースがあるというが、今回の環境では、error.logにはその兆候は出ていない。
(参考)mpm_winnt - Apache HTTP サーバ
メモリリークに対して根本対策をする(hackする?)スキルがないため、プロセスをリセットすることで暫定対策を図る。
httpd-mpm.confで、以下の値を調整。
<IfModule mpm_winnt_module> # 10000→5 MaxRequestsPerChild 5 </IfModule>
何度も負荷テスト→負荷テスト→負荷テスト→…と繰り返すと、確かにプロセスがリセットされ、メモリ逼迫が解除された。
svn coの場合は、いくつファイルをダウンロードしようが、コマンド1回で、Request1回とカウントされている気がする(KeepAliveが効いてるせいかもしれない)が、コマンド5回でリセットがかかるかというとそうではないようだ。
おそらく仕掛かりのセッションが全部終わったときに、処理したRequest数が閾値を超えていればリセット、としている気がする。
長いことリセットがかからないときがある
何度も負荷テスト→負荷テスト→負荷テスト→…と繰り返すと、どうもリセットがかからないことがある。
前回の想像(仕掛かりのセッションが全部終わったときにリセット)が正しければ、何かのセッションが残ったままのはず。
httpd.confで、以下の値を有効化(#を外す)
LoadModule status_module modules/mod_status.so
ブラウザでhttp://foo/server-statusにアクセスすると、Mode of operationが"K" Keepalive (read)のままのやつがいる。
RequestはPROPFIND /CVS HTTP/1.1などとなっていて、svnサービスと関係ないリソースに対して行っている。
CVSの文字から、TortoiseCVSを疑ってみる。
共有フォルダを見たときに、TortoiseCVSが何かのバグで、WebDAVアクセスを試みているのでは?と思い、TortoiseCVS 1.2.2からTortoiseCVS 1.10.10にアップデートしてみた。
すると、PROPFIND /CVS HTTP/1.1は現れなくなった。
が、なぞのPROPFIND投げっぱなしKeep攻撃は他にもまだやってくる。
またMicrosoftか
一体なんのプログラムがPROPFIND攻撃をしてくるのか確かめるべく、access.logでユーザーエージェントを記録するようにhttpd.confで、以下の値を変更(common→combind)
CustomLog "logs/access.log" combined
そうして待ち構えたところ、見事にトラップにはまってくれたのがコレ。
xxx.xxx.xxx.xxx - - [21/Oct/2009:12:21:33 +0900] "OPTIONS / HTTP/1.1" 200 - "-" "Microsoft-WebDAV-MiniRedir/5.1.2600" xxx.xxx.xxx.xxx - - [21/Oct/2009:12:21:33 +0900] "PROPFIND /hoge HTTP/1.1" 405 346 "-" "Microsoft-WebDAV-MiniRedir/5.1.2600"
またMicrosoftか。また、Microsoftか。
server-statusとaccess.logを付き合わせたところ、これが"K" Keepalive (read)のままのやつというのはほぼ疑いない。
Microsoft-WebDAV-MiniRedirでググると、栄えある検索結果第1位がコレ。
Windows XPからファイルサーバへの接続が非常に遅い
こいつだ。間違いない。
お前の相手などしていられない
ということで、UserAgent指定でサービス拒否を行う。
# MicrosoftのWebDAVエージェントからリクエストが来た場合、サービスを拒否 SetEnvIf User-Agent "^Microsoft-WebDAV-MiniRedir/5.1.2600" deny_agent <Location /> Order allow,deny Allow from all Deny from env=deny_agent </Location> # MicrosoftのWebDAVエージェントからリクエストについて、Keep-Aliveを許可しない BrowserMatch "^Microsoft-WebDAV-MiniRedir/5.1.2600" nokeepalive
完全にWindows XP決め打ちだが、もしVistaとか7とかから別のやつがやってきたら、そいつらもブッタKill。
ついでに自分のPCからもこのエージェントを切っておく。
[コントロールパネル]-[管理ツール]-[サービス]を開き、WebClientという名前の虫垂炎を無効にする。