Rails instances themselves are almost always single-threaded, whereas
Mongrel, and it’s acceptor, are multithreaded.
In a situation with long-running Rails pages this presents a problem for
mod_proxy_balancer.
If num_processors is greater than 1 ( default: 950 ), then Mongrel will
gladly accept incoming requests and queue them if its rails instance is
currently busy. So even though there are non-busy mongrel instances,
a busy one can accept a new request and queue it behind a long-running
request.
I tried setting num_processors to 1. But it looks like this is less
than ideal – I need to dig into mod_proxy_balancer to be sure. But at
first glance, it appears this replaces queuing problem with a proxy
error. That’s because Mongrel still accepts the incoming request –
only to close the new socket immediately if Rails is busy.
Once again, I do need to set up a test and see exactly how
mod_proxy_balancer handles this… but…
If I understand the problem correctly, then one solution might be moving
lines 721 thru 734 into a loop, possibly in its own method, which does
sth like this:
def myaccept
while true
return @socket.accept if worker_list.length < num_processors ##
check first to see if we can handle the request. Let client worry about
connect timeouts.
while @num_processors < reap_dead_workers
sleep @loop_throttle
end
end
end
720 @acceptor = Thread.new do
721 while true
722 begin
- 723 client = @socket.accept
- 724
725 if $tcp_cork_opts
726 client.setsockopt(*$tcp_cork_opts) rescue nil
727 end
728
729 worker_list = @workers.list
730
731 if worker_list.length >= @num_processors
732 STDERR.puts “Server overloaded with
#{worker_list.length} processors (#@num_processors max).
Dropping connection.” - 733 client.close rescue Object*
734 reap_dead_workers(“max processors”)
735 else
736 thread = Thread.new(client) {|c| process_client©
}
737 thread[:started_on] = Time.now
738 @workers.add(thread)
739
740 sleep @timeout/100 if @timeout > 0
741 end