puma_worker_killer 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ad7e53791affc61948522399fb84ff1695c15e10
4
- data.tar.gz: 1705c37b135041e88364c2f47ac6a59cceb6803d
3
+ metadata.gz: 48de7bd76c24b540567047c78701abd668b5a8d1
4
+ data.tar.gz: 66ecc21b98a516a97e533325008a4ccbb8cf7b14
5
5
  SHA512:
6
- metadata.gz: 14870594b03d9ec384b7f3bf6762c3d02f862b55d2ef5052db31578d9c8d852d2e08aaa46a4e277de5c68a210f634b416f3cc6a19ccefd09096dd325a625fc9a
7
- data.tar.gz: f6be7f6cb196854986b572f62a4ea606091ed59dda4bb0e8c045f5d25e0f8b33587e65906194eea3ac3a0690455bd9039e96df5f8b7b5068f74a1b0600769bce
6
+ metadata.gz: dbcf620657fe6b2f04c0904da89bba0f739f3ce30dcbc50cabc668e8664e97a6d4bfa756da1f9fa6f571c25cc79d1dd31f408ea3e78bd70cfca81a72d3411df7
7
+ data.tar.gz: a464e3a896491affbbc724a6ba32919b6027353fe03de1397eb226b9b777fb768a58cd191ee9a7334cad3f8854fa5b21c9a05a6fa7bbbea684210aa31e03e391
@@ -1,3 +1,7 @@
1
+ ## 0.0.4
2
+
3
+ - Add ability to do rolling restart
4
+
1
5
  ## 0.0.3
2
6
 
3
7
  - Fix memory metrics in on linux
data/README.md CHANGED
@@ -9,6 +9,8 @@ If you have a memory leak in your code, finding and plugging it can be a hercule
9
9
 
10
10
  Puma worker killer can only function if you have enabled cluster mode or hybrid mode (threads + worker cluster). If you are only using threads (and not workers) then puma worker killer cannot help keep your memory in control.
11
11
 
12
+ BTW restarting your processes to controll memory is like putting a bandaid on a gunshot wound, try figuring out the reason you're seeing so much memory bloat [derailed benchmarks](https://github.com/schneems/derailed_benchmarks) can help.
13
+
12
14
 
13
15
  ## Install
14
16
 
@@ -20,13 +22,17 @@ gem 'puma_worker_killer'
20
22
 
21
23
  Then run `$ bundle install`
22
24
 
25
+ <!--
23
26
  ## Use
24
27
 
25
28
  > If you like `puma_worker_killer` consider using [puma_auto_tune instead](https://github.com/schneems/puma_auto_tune). It handles memory leaks and tunes your workers too!
26
29
 
30
+ -->
31
+
27
32
  Somewhere in your main process run this code:
28
33
 
29
34
  ```ruby
35
+ # config/initializers/puma_worker_killer.rb
30
36
  PumaWorkerKiller.start
31
37
  ```
32
38
 
@@ -41,7 +47,9 @@ PumaWorkerKiller.config do |config|
41
47
  config.ram = 1024 # mb
42
48
  config.frequency = 5 # seconds
43
49
  config.percent_usage = 0.98
50
+ config.rolling_restart_frequency = 12 * 3600 # 12 hours in seconds
44
51
  end
52
+ PumaWorkerKiller.start
45
53
  ```
46
54
 
47
55
  It is important that you tell your code how much RAM is available on your system. The default is 512 mb (the same size as a Heroku 1x dyno). You can change this value like this:
@@ -62,6 +70,29 @@ You may want to tune the worker killer to run more or less often. You can adjust
62
70
  PumaWorkerKiller.frequency = 20 # seconds
63
71
  ```
64
72
 
73
+ You may want to periodically restart all of your workers rather than simply killing your largest. To do that set:
74
+
75
+ ```ruby
76
+ PumaWorkerKiller.rolling_restart_frequency = 12 * 3600 # 12 hours in seconds
77
+ ```
78
+
79
+ By default PumaWorkerKiller will perform a rolling restart of all your worker processes every 12 hours. To disable, set to `false`.
80
+
81
+ ## Only turn on Rolling Restarts
82
+
83
+ If you're running on a platform like [Heroku where it is difficult to measure RAM from inside of a container accurately](https://github.com/schneems/get_process_mem/issues/7), you may want to disable the "worker killer" functionality and only use the rolling restart. You can do that by running:
84
+
85
+ ```ruby
86
+ PumaWorkerKiller.enable_rolling_restart
87
+ ```
88
+
89
+ or you can pass in the restart frequency
90
+
91
+ ```ruby
92
+ PumaWorkerKiller.enable_rolling_restart(12 * 3600) # 12 hours in seconds
93
+ ```
94
+
95
+ Make sure if you do this to not accidentally call `PumaWorkerKiller.start` as well.
65
96
 
66
97
  ## License
67
98
 
@@ -70,4 +101,4 @@ MIT
70
101
 
71
102
  ## Feedback
72
103
 
73
- Open up an issue or ping me on twitter [@schneems](http://twitter.com/schneems).
104
+ Open up an issue or ping me on twitter [@schneems](http://twitter.com/schneems).
@@ -3,10 +3,11 @@ require 'get_process_mem'
3
3
  module PumaWorkerKiller
4
4
  extend self
5
5
 
6
- attr_accessor :ram, :frequency, :percent_usage
6
+ attr_accessor :ram, :frequency, :percent_usage, :rolling_restart_frequency
7
7
  self.ram = 512 # mb
8
8
  self.frequency = 10 # seconds
9
9
  self.percent_usage = 0.99 # percent of RAM to use
10
+ self.rolling_restart_frequency = 6 * 3600
10
11
 
11
12
  def config
12
13
  yield self
@@ -18,10 +19,17 @@ module PumaWorkerKiller
18
19
 
19
20
  def start(frequency = self.frequency, reaper = self.reaper)
20
21
  AutoReap.new(frequency, reaper).start
22
+ enable_rolling_restart(rolling_restart_frequency) if rolling_restart_frequency
23
+ end
24
+
25
+ def enable_rolling_restart(frequency = self.rolling_restart_frequency)
26
+ frequency = frequency + rand(0..10.0) # so all workers don't restart at the exact same time across multiple machines
27
+ AutoReap.new(frequency, RollingRestart.new).start
21
28
  end
22
29
  end
23
30
 
24
31
  require 'puma_worker_killer/puma_memory'
25
32
  require 'puma_worker_killer/reaper'
33
+ require 'puma_worker_killer/rolling_restart'
26
34
  require 'puma_worker_killer/auto_reap'
27
- require 'puma_worker_killer/version'
35
+ require 'puma_worker_killer/version'
@@ -18,4 +18,4 @@ module PumaWorkerKiller
18
18
  end
19
19
 
20
20
  end
21
- end
21
+ end
@@ -0,0 +1,21 @@
1
+ module PumaWorkerKiller
2
+ class RollingRestart
3
+ def initialize(master = nil)
4
+ @cluster = PumaWorkerKiller::PumaMemory.new(master)
5
+ end
6
+
7
+ # used for tes
8
+ def get_total_memory
9
+ @cluster.get_total_memory
10
+ end
11
+
12
+ def reap(wait_between_worker_kill = 60) # seconds
13
+ return false unless @cluster.running?
14
+ @cluster.workers.each do |worker, ram|
15
+ @cluster.master.log "PumaWorkerKiller: Rolling Restart. #{@cluster.workers.count} workers consuming total: #{ get_total_memory } mb out of max: #{@max_ram} mb. Sending TERM to #{worker.inspect}"
16
+ worker.term
17
+ sleep wait_between_worker_kill
18
+ end
19
+ end
20
+ end
21
+ end
@@ -1,3 +1,3 @@
1
1
  module PumaWorkerKiller
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.4"
3
3
  end
@@ -19,6 +19,8 @@ Gem::Specification.new do |gem|
19
19
  gem.require_paths = ["lib"]
20
20
 
21
21
  gem.add_dependency "puma", "~> 2.7"
22
- gem.add_dependency "get_process_mem", "~> 0.1"
22
+ gem.add_dependency "get_process_mem", "~> 0.2"
23
23
  gem.add_development_dependency "rake", "~> 10.1"
24
+ gem.add_development_dependency "test-unit", ">= 0"
25
+
24
26
  end
@@ -10,6 +10,8 @@ end
10
10
  PumaWorkerKiller.start
11
11
 
12
12
 
13
+ puts "Frequency: #{PumaWorkerKiller.frequency}" if ENV['PUMA_FREQUENCY']
14
+
13
15
  class HelloWorld
14
16
  def response
15
17
  [200, {}, ['Hello World']]
@@ -5,12 +5,12 @@ class PumaWorkerKillerTest < Test::Unit::TestCase
5
5
  def test_starts
6
6
  app_path = fixture_path.join("app.ru")
7
7
  port = 0 # http://stackoverflow.com/questions/200484/how-do-you-find-a-free-tcp-server-port-using-ruby
8
- puma_log = Pathname.new "puma.log"
9
- `rm #{puma_log}; touch #{puma_log}`
10
- pid = Process.spawn("PUMA_FREQUENCY=1 bundle exec puma #{app_path} -t 1:1 -w 5 --preload --debug -p #{port} > #{puma_log}")
8
+ puma_log = Pathname.new "#{ SecureRandom.hex }-puma.log"
9
+ pid = Process.spawn("PUMA_FREQUENCY=1 bundle exec puma #{ app_path } -t 1:1 -w 5 --preload --debug -p #{ port } > #{puma_log}")
11
10
  sleep 5
12
11
  assert_match "PumaWorkerKiller:", puma_log.read
13
12
  ensure
13
+ puma_log.delete
14
14
  Process.kill('TERM', pid) if pid
15
15
  end
16
16
 
@@ -59,4 +59,19 @@ class PumaWorkerKillerTest < Test::Unit::TestCase
59
59
  cluster.workers.map(&:term)
60
60
  end
61
61
 
62
+
63
+ def test_rolling_restart
64
+ ram = rand(75..100) #mb
65
+ cluster = FakeCluster.new
66
+ cluster.add_worker
67
+
68
+ worker = cluster.workers.first
69
+ reaper = PumaWorkerKiller::RollingRestart.new(cluster)
70
+ reaper.reap(1)
71
+
72
+ assert_equal 1, cluster.workers.select {|w| w.is_term? }.count
73
+ ensure
74
+ cluster.workers.map(&:term)
75
+ end
62
76
  end
77
+
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: puma_worker_killer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Richard Schneeman
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-04-03 00:00:00.000000000 Z
11
+ date: 2015-09-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: puma
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '0.1'
33
+ version: '0.2'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '0.1'
40
+ version: '0.2'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rake
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '10.1'
55
+ - !ruby/object:Gem::Dependency
56
+ name: test-unit
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
55
69
  description: " Kills pumas, the code kind "
56
70
  email:
57
71
  - richard.schneeman+rubygems@gmail.com
@@ -69,6 +83,7 @@ files:
69
83
  - lib/puma_worker_killer/auto_reap.rb
70
84
  - lib/puma_worker_killer/puma_memory.rb
71
85
  - lib/puma_worker_killer/reaper.rb
86
+ - lib/puma_worker_killer/rolling_restart.rb
72
87
  - lib/puma_worker_killer/version.rb
73
88
  - puma_worker_killer.gemspec
74
89
  - test/fixtures/app.ru
@@ -94,7 +109,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
94
109
  version: '0'
95
110
  requirements: []
96
111
  rubyforge_project:
97
- rubygems_version: 2.2.2
112
+ rubygems_version: 2.4.5.1
98
113
  signing_key:
99
114
  specification_version: 4
100
115
  summary: If you have a memory leak in your web code puma_worker_killer can keep it