unicorn-worker-killer-2 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/lib/unicorn/worker-killer-2/max_requests.rb +43 -0
- data/lib/unicorn/worker-killer-2/oom.rb +51 -0
- data/lib/unicorn/worker-killer-2.rb +38 -0
- metadata +80 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 978787e2d1d75226ad11e4bcd96c84c39a9102c3
|
4
|
+
data.tar.gz: f59f3e586709b9ee51972ee9d3698829ba74a529
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 657ff2fc32758ff7255c9d999acb3bce1e36cc145d2bf35a602399544f72bf9ebc4a0ffc019cb83fb5dcbc6967ebe4916f21e469f7a04c515c6ed79f6a4929f9
|
7
|
+
data.tar.gz: '0903a412426f770137ef330f505db9245df49c8c8df4aadd0e5889e5eb82f3b67996f31f6334d6351617f38e731b70cf9148953cd40c12fd3bf68aaaf7756657'
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Unicorn
|
4
|
+
module WorkerKiller
|
5
|
+
module MaxRequests
|
6
|
+
module MonkeyPatch
|
7
|
+
def process_client(client)
|
8
|
+
super(client) # Unicorn::HttpServer#process_client
|
9
|
+
|
10
|
+
return if @_worker_max_requests_min.zero? &&
|
11
|
+
@_worker_max_requests_max.zero?
|
12
|
+
|
13
|
+
logger.info "#{self}: worker (pid: #{Process.pid}) has #{@_worker_request_limit} left before being killed" if @_verbose
|
14
|
+
|
15
|
+
@_worker_request_limit -= 1
|
16
|
+
return if @_worker_request_limit.positive?
|
17
|
+
|
18
|
+
logger.warn "#{self}: worker (pid: #{Process.pid}) exceeds max number of requests (limit: #{@_worker_max_requests})"
|
19
|
+
WorkerKiller.kill_self(logger, @_worker_process_start)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.monkey_patch(opts = {})
|
24
|
+
min = opts[:max_requests_min] || 3072
|
25
|
+
max = opts[:max_requests_max] || 4096
|
26
|
+
verbose = opts[:verbose] || false
|
27
|
+
|
28
|
+
ObjectSpace.each_object(HttpServer) do |s|
|
29
|
+
s.extend(MonkeyPatch)
|
30
|
+
|
31
|
+
s.instance_variable_set(:@_worker_process_start, WorkerKiller.now)
|
32
|
+
|
33
|
+
s.instance_variable_set(:@_worker_max_requests_min, min)
|
34
|
+
s.instance_variable_set(:@_worker_max_requests_max, max)
|
35
|
+
s.instance_variable_set(:@_verbose, verbose)
|
36
|
+
|
37
|
+
r = WorkerKiller.randomize(max - min + 1)
|
38
|
+
s.instance_variable_set(:@_worker_request_limit, min + r)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'get_process_mem'
|
4
|
+
|
5
|
+
module Unicorn
|
6
|
+
module WorkerKiller
|
7
|
+
module Oom
|
8
|
+
module MonkeyPatch
|
9
|
+
def process_client(client)
|
10
|
+
super(client) # Unicorn::HttpServer#process_client
|
11
|
+
|
12
|
+
return if @_worker_memory_limit_min.zero? &&
|
13
|
+
@_worker_memory_limit_max.zero?
|
14
|
+
|
15
|
+
@_worker_check_count ||= 0
|
16
|
+
@_worker_check_count += 1
|
17
|
+
|
18
|
+
return unless (@_worker_check_count % @_worker_check_cycle).zero?
|
19
|
+
|
20
|
+
rss = GetProcessMem.new.bytes
|
21
|
+
logger.info "#{self}: worker (pid: #{Process.pid}) using #{rss} bytes." if @_verbose
|
22
|
+
return if rss < @_worker_memory_limit
|
23
|
+
|
24
|
+
logger.warn "#{self}: worker (pid: #{Process.pid}) exceeds memory limit (#{rss} bytes > #{@_worker_memory_limit} bytes)"
|
25
|
+
WorkerKiller.kill_self(logger, @_worker_process_start)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.monkey_patch(opts = {})
|
30
|
+
min = opts[:memory_limit_min] || (1024**3)
|
31
|
+
max = opts[:memory_limit_max] || 2 * (1024**3)
|
32
|
+
check_cycle = opts[:check_cycle] || 16
|
33
|
+
verbose = opts[:verbose] || false
|
34
|
+
|
35
|
+
ObjectSpace.each_object(HttpServer) do |s|
|
36
|
+
s.extend(MonkeyPatch)
|
37
|
+
|
38
|
+
s.instance_variable_set(:@_worker_process_start, WorkerKiller.now)
|
39
|
+
|
40
|
+
s.instance_variable_set(:@_worker_memory_limit_min, min)
|
41
|
+
s.instance_variable_set(:@_worker_memory_limit_max, max)
|
42
|
+
s.instance_variable_set(:@_worker_check_cycle, check_cycle)
|
43
|
+
s.instance_variable_set(:@_verbose, verbose)
|
44
|
+
|
45
|
+
r = WorkerKiller.randomize(max - min + 1)
|
46
|
+
s.instance_variable_set(:@_worker_memory_limit, min + r)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'unicorn'
|
4
|
+
|
5
|
+
require_relative 'worker-killer-2/oom'
|
6
|
+
require_relative 'worker-killer-2/max_requests'
|
7
|
+
|
8
|
+
module Unicorn
|
9
|
+
module WorkerKiller
|
10
|
+
# Kill the current process by telling it to send signals to itself. If the
|
11
|
+
# process isn't killed after 5 QUIT signals, send 10 TERM signals. Finally,
|
12
|
+
# send a KILL signal. A single signal is sent per request.
|
13
|
+
#
|
14
|
+
# @see http://unicorn.bogomips.org/SIGNALS.html
|
15
|
+
def self.kill_self(logger, start_time)
|
16
|
+
alive_sec = (now - start_time).round
|
17
|
+
worker_pid = Process.pid
|
18
|
+
|
19
|
+
@kill_attempts ||= 0
|
20
|
+
@kill_attempts += 1
|
21
|
+
|
22
|
+
sig = :QUIT
|
23
|
+
sig = :TERM if @kill_attempts > 10
|
24
|
+
sig = :KILL if @kill_attempts > 15
|
25
|
+
|
26
|
+
logger.warn "#{self} send SIG#{sig} (pid: #{worker_pid}) alive: #{alive_sec} sec (trial #{@kill_attempts})"
|
27
|
+
Process.kill sig, worker_pid
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.randomize(integer)
|
31
|
+
Random.rand(integer.abs)
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.now
|
35
|
+
Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
metadata
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: unicorn-worker-killer-2
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Chris Elsworth
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-03-17 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: get_process_mem
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: unicorn
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '4'
|
34
|
+
- - "<"
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: '6'
|
37
|
+
type: :runtime
|
38
|
+
prerelease: false
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '4'
|
44
|
+
- - "<"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '6'
|
47
|
+
description: Kill Unicorn child processes when they exceed memory/request limits
|
48
|
+
email:
|
49
|
+
- chris.elsworth@bytemark.co.uk
|
50
|
+
executables: []
|
51
|
+
extensions: []
|
52
|
+
extra_rdoc_files: []
|
53
|
+
files:
|
54
|
+
- lib/unicorn/worker-killer-2.rb
|
55
|
+
- lib/unicorn/worker-killer-2/max_requests.rb
|
56
|
+
- lib/unicorn/worker-killer-2/oom.rb
|
57
|
+
homepage: https://gitlab.bytemark.co.uk/bytemark/unicorn-worker-killer-2
|
58
|
+
licenses: []
|
59
|
+
metadata: {}
|
60
|
+
post_install_message:
|
61
|
+
rdoc_options: []
|
62
|
+
require_paths:
|
63
|
+
- lib
|
64
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '0'
|
74
|
+
requirements: []
|
75
|
+
rubyforge_project:
|
76
|
+
rubygems_version: 2.6.13
|
77
|
+
signing_key:
|
78
|
+
specification_version: 4
|
79
|
+
summary: Rewrite of unicorn-worker-kill
|
80
|
+
test_files: []
|