From 8287106809a82ccd1afba674740486946509b856 Mon Sep 17 00:00:00 2001 From: zedshaw Date: Wed, 22 Mar 2006 03:31:30 +0000 Subject: Updates mongrel scripts to the new thread model with max concurrent and with throttle options. git-svn-id: svn+ssh://rubyforge.org/var/svn/mongrel/trunk@120 19e92222-5c0b-0410-8929-a290d50e31e9 --- bin/mongrel_rails | 4 ++-- bin/mongrel_rails_svc | 4 ++-- lib/mongrel.rb | 56 ++++++++++++++++++++++++++------------------------- 3 files changed, 33 insertions(+), 31 deletions(-) diff --git a/bin/mongrel_rails b/bin/mongrel_rails index 1682ae5..95d0970 100644 --- a/bin/mongrel_rails +++ b/bin/mongrel_rails @@ -14,8 +14,8 @@ class Start < GemPlugin::Plugin "/commands" ['-a', '--address ADDR', "Address to bind to", :@address, "0.0.0.0"], ['-l', '--log FILE', "Where to write log messages", :@log_file, "log/mongrel.log"], ['-P', '--pid FILE', "Where to write the PID", :@pid_file, "log/mongrel.pid"], - ['-n', '--num-procs INT', "Number of processor threads to use", :@num_procs, 20], - ['-t', '--timeout SECONDS', "Timeout all requests after SECONDS time", :@timeout, 120], + ['-n', '--num-procs INT', "Number of processor threads to use", :@num_procs, 1024], + ['-t', '--timeout SECONDS', "Timeout all requests after SECONDS time", :@timeout, 0], ['-m', '--mime PATH', "A YAML file that lists additional MIME types", :@mime_map, nil], ['-c', '--chdir PATH', "Change to dir before starting (will be expanded)", :@cwd, Dir.pwd], ['-r', '--root PATH', "Set the document root (default 'public')", :@docroot, "public"], diff --git a/bin/mongrel_rails_svc b/bin/mongrel_rails_svc index 5e19e82..5fa4caa 100644 --- a/bin/mongrel_rails_svc +++ b/bin/mongrel_rails_svc @@ -203,8 +203,8 @@ if ARGV[0] == 'service' :ip => '0.0.0.0', :port => 3000, :mime_map => nil, - :num_procs => 20, - :timeout => 120, + :num_procs => 1024, + :timeout => 0, :cpu => nil } diff --git a/lib/mongrel.rb b/lib/mongrel.rb index 5bc896c..b501c26 100644 --- a/lib/mongrel.rb +++ b/lib/mongrel.rb @@ -310,29 +310,26 @@ module Mongrel # hold your breath until Ruby 1.9 is actually finally useful. class HttpServer attr_reader :acceptor + attr_reader :workers # Creates a working server on host:port (strange things happen if port isn't a Number). - # Use HttpServer::run to start the server. + # Use HttpServer::run to start the server and HttpServer.acceptor.join to + # join the thread that's processing incoming requests on the socket. # - # The num_processors variable has varying affects on how requests are processed. You'd - # think adding more processing threads (processors) would make the server faster, but - # that's just not true. There's actually an effect of how Ruby does threads such that - # the more processors waiting on the request queue, the slower the system is to handle - # each request. But, the lower the number of processors the fewer concurrent responses - # the server can make. - # - # 20 is the default number of processors and is based on experimentation on a few - # systems. If you find that you overload Mongrel too much - # try changing it higher. If you find that responses are way too slow - # try lowering it (after you've tuned your stuff of course). - def initialize(host, port, num_processors=20, timeout=120) + # The num_processors optional argument is the maximum number of concurrent + # processors to accept. The server will return a "503 Service Unavailable" + # message when this happens so that they know to come back. The timeout + # parameter is a sleep timeout that is placed between socket.accept calls + # in order to give the server a cheap throttle time. It defaults to 0 and + # actually if it is 0 then the sleep is not done at all. + def initialize(host, port, num_processors=(2**30-1), timeout=0) @socket = TCPServer.new(host, port) @classifier = URIClassifier.new @host = host @port = port - @worker_group = ThreadGroup.new + @workers = ThreadGroup.new @timeout = timeout - + @num_processors = num_processors end @@ -394,18 +391,24 @@ module Mongrel BasicSocket.do_not_reverse_lookup=true @acceptor = Thread.new do - Thread.current[:stopped] = false - - while not Thread.current[:stopped] + while true begin client = @socket.accept - - thread = Thread.new do - process_client(client) + + if @workers.list.length >= @num_processors + STDERR.puts "Server overloaded with #{@workers.list.length} active processors." + client.write(Const::ERROR_503_RESPONSE) + client.close + else + thread = Thread.new do + process_client(client) + end + + thread.priority=1 + @workers.add(thread) + + sleep @timeout if @timeout > 0 end - - thread.priority=1 - @worker_group.add(thread) rescue StopServer STDERR.puts "Server stopped. Exiting." @socket.close if not @socket.closed? @@ -420,8 +423,8 @@ module Mongrel # each processor to exit and stop processing. # finally we wait until the queue is empty - while @worker_group.list.length > 0 - STDERR.puts "Shutdown waiting for #{@worker_group.list.length} requests" if @worker_group.list.length > 0 + while @workers.list.length > 0 + STDERR.puts "Shutdown waiting for #{@workers.list.length} requests" if @workers.list.length > 0 sleep 1 end end @@ -447,7 +450,6 @@ module Mongrel # off the request queue before finally exiting. def stop stopper = Thread.new do - @acceptor[:stopped] = true exc = StopServer.new @acceptor.raise(exc) end -- cgit v1.2.3-24-ge0c7