(Min|Max)SpareServers にかわる prefork モデルを考えてみる

そもそも動的にプロセス数を変化させることができて何がうれしいか、というと、負荷が軽い時に、別のタスクを動かしても、アイドル状態のサーバプロセスが邪魔にならない。ってあたりなのかな。でもそのため(だけ)に Scoreboard とか複雑な仕組みを用意するのはなんだかなーと思ったり。
#scoreboard 自体には mod_status みたいな使い方もあるけど

一方で、(Min|Max)SpareServers 方式には、負荷の増大局面で fork(2) が発生するという好ましからざる問題もあったりする。
#特にベンチマーク結果に悪影響が出る :-p

じゃあプロセス数を固定したまま、負荷が軽い際に余計なリソースを食わないような設計ができないか。できるんじゃないかなー、というのが本題。具体的には、

  • accept(2) には、必ず mutex lock をかける
  • mutex をロックできなかったワーカープロセスは、自分が一定量以上メモリを消費していて*1、かつ、最後にリクエストを処理してから一定時間以上経過していた新しい接続を受け付けることがなかった場合は exit(2) する
    • 親プロセスは新しい子プロセスを spawn する

でいいんじゃないのかなーと。vanilla なワーカープロセスは CoW なのでほとんどメモリ食わないし。スケジューラ的には thundering herd が起こらなければ、待機プロセス増やしても問題ないはずだし。

アプリケーションサーバ書くようなケースだと、このほうが、(Min|Max)SpareServers モデルよりも、結果消費メモリ量は少なくなるんじゃないかな(SpareServers モデルが MinSpareServers 個のプロセスの消費メモリを回収しないのに対し、このモデルだと全ワーカープロセスの消費メモリを回収できるため)。

参考: Apache Performance Tuning - Apache HTTP Server Version 2.2

2009/09/25 追記: mutex lock 使わなくても alarm(2) でできると思ったので修正。というか、もっと単純に「ハンドルしたリクエスト数と待機した時間の合計が0でなく、かつ一定数(例えば100)を超えたらワーカープロセスは exit(2)」というモデルが良さそう。

*1:アプリケーションサーバなら、1回でもリクエストを処理した、みたいな基準でいいと思う