From fd9a2271ffac8073c3f02986b906d782f6b249b7 Mon Sep 17 00:00:00 2001 From: evanweaver Date: Mon, 24 Sep 2007 16:26:38 +0000 Subject: [PATCH] refactor timeout and death_time to throttle and timeout, respectively, make throttle not be zero for sub-second timeouts, improve documentation, update long command-line flags git-svn-id: svn+ssh://rubyforge.org/var/svn/mongrel/trunk@624 19e92222-5c0b-0410-8929-a290d50e31e9 --- bin/mongrel_rails | 5 +++-- lib/mongrel.rb | 34 ++++++++++++++++++---------------- lib/mongrel/configurator.rb | 10 ++++++---- lib/mongrel/handlers.rb | 1 + 4 files changed, 28 insertions(+), 22 deletions(-) diff --git a/bin/mongrel_rails b/bin/mongrel_rails index bf8379b7..9b343b39 100644 --- a/bin/mongrel_rails +++ b/bin/mongrel_rails @@ -23,7 +23,8 @@ module Mongrel ['-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 processors active before clients denied", :@num_procs, 1024], - ['-t', '--timeout TIME', "Time to pause (in hundredths of a second) between accepting clients", :@timeout, 0], + ['-o', '--timeout TIME', "Time to wait (in seconds) before killing a stalled thread", :@timeout, 0], + ['-t', '--throttle TIME', "Time to pause (in hundredths of a second) between accepting clients", :@throttle, 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"], @@ -174,7 +175,7 @@ module Mongrel def config_keys @config_keys ||= %w(host port cwd log_file pid_file environment docroot mime_map daemon debug includes config_script - num_processors timeout user group prefix) + num_processors timeout throttle user group prefix) end def settings diff --git a/lib/mongrel.rb b/lib/mongrel.rb index dc8d16e8..5ed1e660 100644 --- a/lib/mongrel.rb +++ b/lib/mongrel.rb @@ -547,6 +547,7 @@ module Mongrel attr_reader :classifier attr_reader :host attr_reader :port + attr_reader :throttle attr_reader :timeout attr_reader :num_processors @@ -560,18 +561,18 @@ module Mongrel # way to deal with overload. Other schemes involve still parsing the client's request # which defeats the point of an overload handling system. # - # The timeout parameter is a sleep timeout (in hundredths of a second) that is placed between + # The throttle parameter is a sleep timeout (in hundredths of a second) 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) + def initialize(host, port, num_processors=950, throttle=0, timeout=60) @socket = TCPServer.new(host, port) @classifier = URIClassifier.new @host = host @port = port @workers = ThreadGroup.new - @timeout = timeout + @throttle = throttle @num_processors = num_processors - @death_time = 60 + @timeout = timeout end # Does the majority of the IO processing. It has been written in Ruby using @@ -608,12 +609,13 @@ module Mongrel if handlers params[Const::PATH_INFO] = path_info params[Const::SCRIPT_NAME] = script_name - # From http://www.ietf.org/rfc/rfc3875 : - # "Script authors should be aware that the REMOTE_ADDR and REMOTE_HOST - # meta-variables (see sections 4.1.8 and 4.1.9) may not identify the - # ultimate source of the request. They identify the client for the - # immediate request to the server; that client may be a proxy, gateway, - # or other intermediary acting on behalf of the actual source client." + + # From http://www.ietf.org/rfc/rfc3875 : + # "Script authors should be aware that the REMOTE_ADDR and REMOTE_HOST + # meta-variables (see sections 4.1.8 and 4.1.9) may not identify the + # ultimate source of the request. They identify the client for the + # immediate request to the server; that client may be a proxy, gateway, + # or other intermediary acting on behalf of the actual source client." params[Const::REMOTE_ADDR] = client.peeraddr.last # select handlers that want more detailed request notification @@ -683,7 +685,7 @@ module Mongrel @workers.list.each do |w| w[:started_on] = Time.now if not w[:started_on] - if mark - w[:started_on] > @death_time + @timeout + if mark - w[:started_on] > @timeout + @throttle STDERR.puts "Thread #{w.inspect} is too old, killing." w.raise(TimeoutError.new(error_msg)) end @@ -694,13 +696,13 @@ module Mongrel end # Performs a wait on all the currently running threads and kills any that take - # too long. Right now it just waits 60 seconds, but will expand this to - # allow setting. The @timeout setting does extend this waiting period by + # too long. It waits by @timeout seconds, which can be set in .initialize or + # via mongrel_rails. The @throttle setting does extend this waiting period by # that much longer. def graceful_shutdown while reap_dead_workers("shutdown") > 0 - STDERR.print "Waiting for #{@workers.list.length} requests to finish, could take #{@death_time + @timeout} seconds." - sleep @death_time / 10 + STDERR.print "Waiting for #{@workers.list.length} requests to finish, could take #{@timeout + @throttle} seconds." + sleep @timeout / 10 end end @@ -752,7 +754,7 @@ module Mongrel thread[:started_on] = Time.now @workers.add(thread) - sleep @timeout/100 if @timeout > 0 + sleep @throttle/100.0 if @throttle > 0 end rescue StopServer @socket.close rescue nil diff --git a/lib/mongrel/configurator.rb b/lib/mongrel/configurator.rb index 4fd81d68..9886634f 100644 --- a/lib/mongrel/configurator.rb +++ b/lib/mongrel/configurator.rb @@ -119,8 +119,9 @@ module Mongrel # # * :host => Host name to bind. # * :port => Port to bind. - # * :num_processors => The maximum number of concurrent threads allowed. (950 default) - # * :timeout => 1/100th of a second timeout between requests. (10 is 1/10th, 0 is timeout) + # * :num_processors => The maximum number of concurrent threads allowed. + # * :throttle => Time to pause (in hundredths of a second) between accepting clients. + # * :timeout => Time to wait (in seconds) before killing a stalled thread. # * :user => User to change to, must have :group as well. # * :group => Group to change to, must have :user as well. # @@ -128,9 +129,10 @@ module Mongrel raise "Cannot call listener inside another listener block." if (@listener or @listener_name) ops = resolve_defaults(options) ops[:num_processors] ||= 950 - ops[:timeout] ||= 0 + ops[:throttle] ||= 0 + ops[:timeout] ||= 60 - @listener = Mongrel::HttpServer.new(ops[:host], ops[:port].to_i, ops[:num_processors].to_i, ops[:timeout].to_i) + @listener = Mongrel::HttpServer.new(ops[:host], ops[:port].to_i, ops[:num_processors].to_i, ops[:throttle].to_i, ops[:timeout].to_i) @listener_name = "#{ops[:host]}:#{ops[:port]}" @listeners[@listener_name] = @listener diff --git a/lib/mongrel/handlers.rb b/lib/mongrel/handlers.rb index be7860a9..60472a81 100644 --- a/lib/mongrel/handlers.rb +++ b/lib/mongrel/handlers.rb @@ -374,6 +374,7 @@ module Mongrel results << table("settings", [ ["host",listener.host], ["port",listener.port], + ["throttle",listener.throttle], ["timeout",listener.timeout], ["workers max",listener.num_processors], ])