[Mongrel] Design flaw? - num_processors, accept/close

Robert Mela rob at robmela.com
Mon Oct 15 09:20:18 EDT 2007

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 

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 

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

    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
    729             worker_list = @workers.list
    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(c) }
    737               thread[:started_on] = Time.now
    738               @workers.add(thread)
    740               sleep @timeout/100 if @timeout > 0
    741             end

-------------- next part --------------
A non-text attachment was scrubbed...
Name: rob.vcf
Type: text/x-vcard
Size: 116 bytes
Desc: not available
Url : http://rubyforge.org/pipermail/mongrel-users/attachments/20071015/40912d0f/attachment.vcf 

More information about the Mongrel-users mailing list