まだ重たいCMSをお使いですか?
毎秒1000リクエスト を捌く超高速CMS「adiary

2010/04/20(火)ApacheのRLimitMEMが効かない

CGI開発中についうっかり無限ループを生成するなんて経験のある人も多いと思いますが、つい最近2回連続でサーバごと落としてしまったので*1本格的に対策しました。

*1 : メモリオーバーフローでカーネルが端からプロセスを殺し始めてサーバ停止

RLimitMEMとRLimitCPU

ApacheにはもともとCGIのメモリやCPU使用量を制限する設定があります。それがRLimitMEMとRLimitCPUです

それぞれ「メモリ(リソース)使用量」と「CPU時間使用量を制限する」もので、制限値を超えた瞬間にプロセスを殺してくれます便利なものです。*2

# 256MB limit(unit Byte)
RLimitMem 268435456
RLimitCPU 30

もちろんこれは設定していたのですが……。

*2 : kernelの機能によります。

RLimitMemが効かない

top コマンドで監視していいたら普通に500MBのメモリを食ってます。どうやら、RLimitMemやRLimitCPUが効かないようです。

  • mod_perl / mod_perl2
  • FastCGI(mod_fastcgi) / mod_fcgid

では効きません。ちょうどmod_fcgidを使用していました。Perl自体は別プロセスで起動しているので効くのかと思ったのですが、どうやら無効なようです(汗)。ちなみに通常CGIの他、SpeedyCGIは効きます。*3

*3 : 普段はSpeedyCGIで開発するのですがImageMagick問題のせいでFastCGIを使っていました。

Apache自体に制限を掛ける

Apache自体のメモリ消費量に制限をかければ、万が一無限ループなどで暴走してもサーバ落ちを防ぐことができます。Apache自体は落ちてしまいますが、サーバが落ちるよりは100倍マシです。

Apacheの起動スクリプト(シェルスクリプト)に

# 1GB limit(unit KByte)
ulimit -v 1048576

と記述することで制限を加えることができます。

Ubuntu/Debian系の場合は /etc/apache2/envvars に ulimit を書き加えればよいようです。これでApache自体が落ちると思ったのですが、mod_fcgid の場合 fcgi プロセスのみが落ちてくれました。

ちょっと謎は残るけど、とりあえず目的は達成したのでこれで。