module Unicorn::AutoScaling::HttpServer

Auto scaling extensions for the Unicorn http server

Constants

DECREMENT
INCREMENT
NONE
RAINDROP_OFFSET

Attributes

autoscale_check_interval[RW]
autoscale_idle_time_decrement[RW]
autoscale_idle_time_increment[RW]
autoscale_idle_time_samples[RW]
autoscale_max_workers[RW]
autoscale_min_workers[RW]
autoscaling[RW]

Private Class Methods

extend_instance!(s) click to toggle source
# File lib/unicorn/auto_scaling/http_server.rb, line 105
def self.extend_instance!(s)
  s.extend(self)

  s.instance_variable_set(:@_autoscale_raindrop, Raindrops.new(Unicorn::Worker::PER_DROP))
  s.instance_variable_set(:@_autoscale_last_scaling, Time.now.to_f)
end

Public Instance Methods

init_worker_process(worker) click to toggle source
Calls superclass method
# File lib/unicorn/auto_scaling/http_server.rb, line 48
def init_worker_process(worker)
  @_autoscale_time_of_last_request = Time.now.to_f
  @_autoscale_last_check           = Time.now.to_f
  @_autoscale_idle_times           = []

  super(worker)
end
process_client(client) click to toggle source
Calls superclass method
# File lib/unicorn/auto_scaling/http_server.rb, line 16
def process_client(client)
  autoscale! if self.autoscaling

  super(client)

  @_autoscale_time_of_last_request = Time.now.to_f if self.autoscaling
end
reap_all_workers() click to toggle source
Calls superclass method
# File lib/unicorn/auto_scaling/http_server.rb, line 24
def reap_all_workers
  if @_autoscale_last_scaling < Time.now.to_f - 10
    if @_autoscale_raindrop[RAINDROP_OFFSET] == INCREMENT
      if self.worker_processes < self.autoscale_max_workers
        logger.info("Auto scaling: UP")

        self.worker_processes += 1
      end
    elsif @_autoscale_raindrop[RAINDROP_OFFSET] == DECREMENT
      if self.worker_processes > self.autoscale_min_workers
        logger.info('Auto scaling: DOWN')

        self.worker_processes -= 1
      end
    end

    @_autoscale_raindrop[RAINDROP_OFFSET] = NONE

    @_autoscale_last_scaling = Time.now.to_f
  end

  super
end
start() click to toggle source
Calls superclass method
# File lib/unicorn/auto_scaling/http_server.rb, line 56
def start
  self.autoscale_max_workers ||= self.worker_processes

  super
end

Private Instance Methods

autoscale!() click to toggle source
# File lib/unicorn/auto_scaling/http_server.rb, line 64
def autoscale!
  # Only clear idle times if scaling is requested
  unless @_autoscale_raindrop[RAINDROP_OFFSET] == NONE
    @_autoscale_idle_times.clear

    return
  end

  average_idle_time = autoscale_average_idle_time

  return unless @_autoscale_last_check < Time.now.to_f - self.autoscale_check_interval

  update_autoscale_action_if_necessary(average_idle_time)

  @_autoscale_last_check = Time.now.to_f
end
autoscale_average_idle_time() click to toggle source
# File lib/unicorn/auto_scaling/http_server.rb, line 81
def autoscale_average_idle_time
  idle_time = Time.now.to_f - @_autoscale_time_of_last_request

  @_autoscale_idle_times.unshift(idle_time)

  @_autoscale_idle_times = @_autoscale_idle_times[0..self.autoscale_idle_time_samples]

  @_autoscale_idle_times.inject(:+) / @_autoscale_idle_times.count
end
update_autoscale_action(action) click to toggle source
# File lib/unicorn/auto_scaling/http_server.rb, line 99
def update_autoscale_action(action)
  @_autoscale_raindrop[RAINDROP_OFFSET] = action

  @_autoscale_idle_times.clear
end
update_autoscale_action_if_necessary(average_idle_time) click to toggle source
# File lib/unicorn/auto_scaling/http_server.rb, line 91
def update_autoscale_action_if_necessary(average_idle_time)
  if average_idle_time < self.autoscale_idle_time_decrement
    update_autoscale_action(INCREMENT)
  elsif average_idle_time > self.autoscale_idle_time_increment
    update_autoscale_action(DECREMENT)
  end
end