Module: Unicorn::WorkerKiller::Oom

Defined in:
lib/unicorn/worker_killer.rb

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.new(app, memory_limit_min = (1024**3), memory_limit_max = (2*(1024**3)), check_cycle = 16, verbose = false) ⇒ Object

Killing the process must be occurred at the outside of the request. We’re using similar techniques used by OobGC, to ensure actual killing doesn’t affect the request.



35
36
37
38
39
40
41
42
43
44
45
# File 'lib/unicorn/worker_killer.rb', line 35

def self.new(app, memory_limit_min = (1024**3), memory_limit_max = (2*(1024**3)), check_cycle = 16, verbose = false)
  ObjectSpace.each_object(Unicorn::HttpServer) do |s|
    s.extend(self)
    s.instance_variable_set(:@_worker_memory_limit_min, memory_limit_min)
    s.instance_variable_set(:@_worker_memory_limit_max, memory_limit_max)
    s.instance_variable_set(:@_worker_check_cycle, check_cycle)
    s.instance_variable_set(:@_worker_check_count, 0)
    s.instance_variable_set(:@_verbose, verbose)
  end
  app # pretend to be Rack middleware since it was in the past
end

Instance Method Details

#process_client(client) ⇒ Object



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/unicorn/worker_killer.rb', line 51

def process_client(client)
  super(client) # Unicorn::HttpServer#process_client
  return if @_worker_memory_limit_min == 0 && @_worker_memory_limit_max == 0

  @_worker_process_start ||= Time.now
  @_worker_memory_limit ||= @_worker_memory_limit_min + randomize(@_worker_memory_limit_max - @_worker_memory_limit_min + 1)
  @_worker_check_count += 1
  if @_worker_check_count % @_worker_check_cycle == 0
    rss = GetProcessMem.new.bytes
    logger.info "#{self}: worker (pid: #{Process.pid}) using #{rss} bytes." if @_verbose
    if rss > @_worker_memory_limit
      logger.warn "#{self}: worker (pid: #{Process.pid}) exceeds memory limit (#{rss} bytes > #{@_worker_memory_limit} bytes)"
      Unicorn::WorkerKiller.kill_self(logger, @_worker_process_start)
    end
    @_worker_check_count = 0
  end
end

#randomize(integer) ⇒ Object



47
48
49
# File 'lib/unicorn/worker_killer.rb', line 47

def randomize(integer)
  RUBY_VERSION > "1.9" ? Random.rand(integer.abs) : rand(integer)
end