preforkの挙動確認

preforkの挙動について確認してみた。

ちなみに、preforkのポリシーは「事前に、ある程度余裕もって子プロセス作っていこうぜ。リクエストの度にforkするのはもっさりするからやめようぜ」です。まぁ、プロセス毎に処理をするのでいろいろ安全だけど、当然リソース食います。

<IfModule prefork.c>
StartServers       8
MinSpareServers    5
MaxSpareServers   20
ServerLimit      256
MaxClients       256
MaxRequestsPerChild  4000
</IfModule>
  • StartServers

Apache起動時に作っておく子プロセスの数。

$ sudo /usr/sbin/apachectl restart
$ ps -ef | grep http | grep -v grep | grep -v vim | grep -v root
apache   26276 24728  0 17:10 ?        00:00:00 /usr/sbin/httpd
apache   26277 24728  0 17:10 ?        00:00:00 /usr/sbin/httpd
apache   26278 24728  0 17:10 ?        00:00:00 /usr/sbin/httpd
apache   26279 24728  0 17:10 ?        00:00:00 /usr/sbin/httpd
apache   26280 24728  0 17:10 ?        00:00:00 /usr/sbin/httpd
apache   26281 24728  0 17:10 ?        00:00:00 /usr/sbin/httpd
apache   26282 24728  0 17:10 ?        00:00:00 /usr/sbin/httpd
apache   26283 24728  0 17:10 ?        00:00:00 /usr/sbin/httpd
  • MinSpareServers
  • MaxSpareServers

作っておく子プロセス数の範囲。これより少なすぎたり多すぎると、1秒おきに1プロセスずつ調整する。

$ ps -ef | grep http | grep -v grep | wc -l
65
$ ps -ef | grep http | grep -v grep | wc -l
58
$ ps -ef | grep http | grep -v grep | wc -l
54
$ ps -ef | grep http | grep -v grep | wc -l
51
$ ps -ef | grep http | grep -v grep | wc -l
49
$ ps -ef | grep http | grep -v grep | wc -l
29
$ ps -ef | grep http | grep -v grep | wc -l
23
$ ps -ef | grep http | grep -v grep | wc -l
21
$ ps -ef | grep http | grep -v grep | wc -l
21
$

MaxSpareServersより一つ多いのは親プロセス分.


対MaxClientsを前に、こんな接続スクリプトをやっつけで書いておく。

require 'socket'

raise "no max connection" unless conn_max = ARGV[0]

conn_box = []
(0...conn_max.to_i).each do |i|
  s = TCPSocket.new "cent1.lan", 80
  s.write "GET /cgi-bin/sleepy.cgi HTTP/1.0\r\n\r\n"
  conn_box[i] = s
end

conn_box.each do |s|
  p s.read
  s.close
end
  • MaxClients

preforkの場合、子プロセスの最大数っぽい。

<IfModule prefork.c>
StartServers       8
MinSpareServers    5
MaxSpareServers   20
ServerLimit       64
MaxClients        64
MaxRequestsPerChild  4000
</IfModule>

諸事情により… 設定値を小さめにして実験。

httpクライアント側

[mitsu@koma_colinux ruby]$ ruby conntest.rb 100

httpサーバー側

$ netstat -ant | grep ':80' | grep ESTA | wc -l
100
$ netstat -ant | grep ':80' | grep ESTA | wc -l
100
$

$ ps -ef | grep http | grep -v grep | grep -v vim | grep -v root | wc -l
64
$ ps -ef | grep http | grep -v grep | grep -v vim | grep -v root | wc -l
64
$ ps -ef | grep http | grep -v grep | grep -v vim | grep -v root | wc -l
64

100接続はできているけど、子プロセスはMaxClientsの設定どおり、64個までしか増えない。それ以外の接続はListenBackLog(デフォルト値 => 511)で設定されるキューで吸収されているのだろう。