Skip to content

Commit

Permalink
Added a verbose option, which prints additional information to the log
Browse files Browse the repository at this point in the history
  • Loading branch information
tmorton committed Aug 14, 2013
1 parent 14047b2 commit 0bf0aff
Show file tree
Hide file tree
Showing 2 changed files with 11 additions and 4 deletions.
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,18 @@ This module automatically restarts the Unicorn workers, based on the number of r

`max_requests_min` and `max_requests_max` specify the min and max of maximum requests per worker. The actual limit is decided by rand() between `max_requests_min` and `max_requests_max` per worker, to prevent all workers to be dead at the same time. Once the number exceeds the limit, that worker is automatically restarted.

### Unicorn::WorkerKiller::Oom(memory_limit_min=(1024**3), memory_limit_max=(2*(1024**3)), check_cycle = 16)
If `verbose` is set to true, then after every request, your log will show the requests left before restart. This logging is done at the `info` level.

### Unicorn::WorkerKiller::Oom(memory_limit_min=(1024**3), memory_limit_max=(2*(1024**3)), check_cycle = 16, verbose = false)

This module automatically restarts the Unicorn workers, based on its memory size.

`memory_limit_min` and `memory_limit_max` specify the min and max of maximum memory per worker. The actual limit is decided by rand() between `memory_limit_min` and `memory_limit_max` per worker, to prevent all workers to be dead at the same time. Once the memory size exceeds `memory_size`, that worker is automatically restarted.

The memory size check is done in every `check_cycle` requests.

If `verbose` is set to true, then every memory size check will be shown in your logs. This logging is done at the `info` level.

# Special Thanks

- [@hotchpotch](http://github.com/hotchpotch/) for the [original idea](https://gist.github.com/hotchpotch/1258681)
Expand Down
9 changes: 6 additions & 3 deletions lib/unicorn/worker_killer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,14 @@ module Oom
# affect the request.
#
# @see https://github.com/defunkt/unicorn/blob/master/lib/unicorn/oob_gc.rb#L40
def self.new(app, memory_limit_min = (1024**3), memory_limit_max = (2*(1024**3)), check_cycle = 16)
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
Expand All @@ -48,7 +49,6 @@ def randomize(integer)

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
Expand All @@ -57,6 +57,7 @@ def process_client(client)

if @_worker_check_count % @_worker_check_cycle == 0
rss = _worker_rss()
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)
Expand Down Expand Up @@ -104,11 +105,12 @@ module MaxRequests
# affect the request.
#
# @see https://github.com/defunkt/unicorn/blob/master/lib/unicorn/oob_gc.rb#L40
def self.new(app, max_requests_min = 3072, max_requests_max = 4096)
def self.new(app, max_requests_min = 3072, max_requests_max = 4096, verbose = false)
ObjectSpace.each_object(Unicorn::HttpServer) do |s|
s.extend(self)
s.instance_variable_set(:@_worker_max_requests_min, max_requests_min)
s.instance_variable_set(:@_worker_max_requests_max, max_requests_max)
s.instance_variable_set(:@_verbose, verbose)
end

app # pretend to be Rack middleware since it was in the past
Expand All @@ -125,6 +127,7 @@ def process_client(client)
@_worker_process_start ||= Time.now
@_worker_cur_requests ||= @_worker_max_requests_min + randomize(@_worker_max_requests_max - @_worker_max_requests_min + 1)
@_worker_max_requests ||= @_worker_cur_requests
logger.info "#{self}: worker (pid: #{Process.pid}) has #{@_worker_cur_requests} left before being killed" if @_verbose

if (@_worker_cur_requests -= 1) <= 0
logger.warn "#{self}: worker (pid: #{Process.pid}) exceeds max number of requests (limit: #{@_worker_max_requests})"
Expand Down

0 comments on commit 0bf0aff

Please sign in to comment.