From e74dac7aebd453449d632c697cb05a277c998690 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Fri, 24 Apr 2009 13:36:49 -0700 Subject: SIGTT{IN,OU} {in,de}crements worker_processes This allows dynamic tuning of the worker_processes count without having to restart existing ones. This also allows worker_processes to be set to a low initial amount in the config file for low-traffic deployments/upgrades and then scaled up as the old processes are killed off. Remove the proposed reexec_worker_processes from TODO since this is far more flexible and powerful. This will allow not-yet-existent third-party monitoring tools to dynamically change and scale worker processes according to site load without increasing the complexity of Unicorn itself. --- lib/unicorn.rb | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'lib/unicorn.rb') diff --git a/lib/unicorn.rb b/lib/unicorn.rb index 9510e4b..33be99a 100644 --- a/lib/unicorn.rb +++ b/lib/unicorn.rb @@ -101,7 +101,7 @@ module Unicorn raise ArgumentError, "no listeners" if LISTENERS.empty? self.pid = @config[:pid] build_app! if @preload_app - spawn_missing_workers + maintain_worker_count self end @@ -192,7 +192,7 @@ module Unicorn case SIG_QUEUE.shift when nil murder_lazy_workers - spawn_missing_workers if respawn + maintain_worker_count if respawn master_sleep when :QUIT # graceful shutdown break @@ -214,6 +214,10 @@ module Unicorn else logger.info "SIGWINCH ignored because we're not daemonized" end + when :TTIN + @worker_processes += 1 + when :TTOU + @worker_processes -= 1 if @worker_processes > 0 when :HUP respawn = true if @config.config_file @@ -257,7 +261,8 @@ module Unicorn private # list of signals we care about and trap in master. - QUEUE_SIGS = [ :WINCH, :QUIT, :INT, :TERM, :USR1, :USR2, :HUP ].freeze + QUEUE_SIGS = [ :WINCH, :QUIT, :INT, :TERM, :USR1, :USR2, :HUP, + :TTIN, :TTOU ].freeze # defer a signal for later processing in #join (master process) def trap_deferred(signal) @@ -380,7 +385,6 @@ module Unicorn end def spawn_missing_workers - return if WORKERS.size == @worker_processes (0...@worker_processes).each do |worker_nr| WORKERS.values.include?(worker_nr) and next begin @@ -399,6 +403,14 @@ module Unicorn end end + def maintain_worker_count + (off = WORKERS.size - @worker_processes) == 0 and return + off < 0 and return spawn_missing_workers + WORKERS.each_pair { |pid,w| + w.nr >= @worker_processes and kill_worker(:QUIT, pid) rescue nil + } + end + # once a client is accepted, it is processed in its entirety here # in 3 easy steps: read request, call app, write app response def process_client(client) -- cgit v1.2.3-24-ge0c7