diff options
-rw-r--r-- | Gemfile | 3 | ||||
-rw-r--r-- | Gemfile.lock | 8 | ||||
-rw-r--r-- | Procfile | 2 | ||||
-rw-r--r-- | config.ru | 4 | ||||
-rw-r--r-- | config/unicorn.rb | 45 | ||||
-rw-r--r-- | lib/rack/chrome_frame.rb (renamed from lib/chrome_frame.rb) | 0 | ||||
-rw-r--r-- | lib/unicorn_killer.rb | 53 |
7 files changed, 111 insertions, 4 deletions
@@ -6,7 +6,7 @@ gem 'bundler', '>= 1.0.0' gem 'foreman', '0.34.1' gem 'whenever' -gem 'thin', '~> 1.3.1', :require => false +gem 'thin', '~> 1.3.1', :require => false # authentication @@ -41,6 +41,7 @@ end group :heroku do gem 'pg' + gem 'unicorn', '~> 4.1.1', :require => false end gem 'settingslogic', :git => 'git://github.com/binarylogic/settingslogic.git' diff --git a/Gemfile.lock b/Gemfile.lock index 1d79118fb..bc55d6eef 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -208,6 +208,7 @@ GEM multi_json jwt (0.1.4) json (>= 1.2.4) + kgio (2.7.0) launchy (2.0.3) linecache (0.46) rbx-require-relative (> 0.0.4) @@ -299,6 +300,7 @@ GEM rake (>= 0.8.7) rdoc (~> 3.4) thor (~> 0.14.4) + raindrops (0.8.0) rake (0.9.2.2) rbx-require-relative (0.0.5) rdoc (3.12) @@ -383,8 +385,11 @@ GEM typhoeus (0.3.3) mime-types tzinfo (0.3.31) + unicorn (4.1.1) + kgio (~> 2.4) + rack + raindrops (~> 0.6) vegas (0.1.11) - rack (>= 1.0.0) warden (1.0.6) rack (>= 1.0) webmock (1.6.2) @@ -485,6 +490,7 @@ DEPENDENCIES timecop twitter (= 2.0.2) typhoeus + unicorn (~> 4.1.1) webmock whenever will_paginate @@ -1,4 +1,4 @@ -web: bundle exec rails s thin -p $PORT +web: bundle exec unicorn -c config/unicorn.rb -p $PORT redis: redis-server catchall_worker: env QUEUE=* bundle exec rake resque:work slow_worker: env QUEUES=socket_webfinger,photos,http_service,receive_local,mail,receive,receive_salmon,http,delete_account bundle exec rake resque:work @@ -5,7 +5,9 @@ # This file is used by Rack-based servers to start the application. require ::File.expand_path('../config/environment', __FILE__) -require ::File.expand_path('../lib/chrome_frame', __FILE__) + +# use UnicornKiller::MaxRequests, 1000 +use UnicornKiller::Oom, 400 * 1024 #kill a unicorn that has gone over 400mB use Rack::ChromeFrame, :minimum => 8 run Diaspora::Application diff --git a/config/unicorn.rb b/config/unicorn.rb new file mode 100644 index 000000000..6cfcc8f6d --- /dev/null +++ b/config/unicorn.rb @@ -0,0 +1,45 @@ +rails_env = ENV['RAILS_ENV'] || 'development' + +# Enable and set these to run the worker as a different user/group +#user = 'diaspora' +#group = 'diaspora' + +worker_processes 1 + +## Load the app before spawning workers +#preload_app true + +# How long to wait before killing an unresponsive worker +timeout 30 + +#pid '/var/run/diaspora/diaspora.pid' +#listen '/var/run/diaspora/diaspora.sock', :backlog => 2048 + +# Ruby Enterprise Feature +if GC.respond_to?(:copy_on_write_friendly=) + GC.copy_on_write_friendly = true +end + + +before_fork do |server, worker| + # If using preload_app, enable this line + #ActiveRecord::Base.disconnect! + + old_pid = '/var/run/diaspora/diaspora.pid.oldbin' + if File.exists?(old_pid) && server.pid != old_pid + begin + Process.kill("QUIT", File.read(old_pid).to_i) + rescue Errno::ENOENT, Errno::ESRCH + # someone else did our job for us + end + end +end + + +after_fork do |server, worker| + # If using preload_app, enable this line + # ActiveRecord::Base.establish_connection + + # Enable this line to have the workers run as different user/group + #worker.user(user, group) +end diff --git a/lib/chrome_frame.rb b/lib/rack/chrome_frame.rb index 1875bcb1f..1875bcb1f 100644 --- a/lib/chrome_frame.rb +++ b/lib/rack/chrome_frame.rb diff --git a/lib/unicorn_killer.rb b/lib/unicorn_killer.rb new file mode 100644 index 000000000..7e908538d --- /dev/null +++ b/lib/unicorn_killer.rb @@ -0,0 +1,53 @@ +# # your config.ru +# require 'unicorn_killer' +# use UnicornKiller::MaxRequests, 1000 +# use UnicornKiller::Oom, 400 * 1024 + +module UnicornKiller + module Kill + def quit + sec = (Time.now - @process_start).to_i + warn "#{self.class} send SIGQUIT (pid: #{Process.pid})\talive: #{sec} sec" + Process.kill :QUIT, Process.pid + end + end + + class Oom + include Kill + + def initialize(app, memory_size= 512 * 1024, check_cycle = 10) + @app = app + @memory_size = memory_size + @check_cycle = check_cycle + @check_count = 0 + end + + def rss + `ps -o rss= -p #{Process.pid}`.to_i + end + + def call(env) + @process_start ||= Time.now + if (@check_count += 1) % @check_cycle == 0 + @check_count = 0 + quit if rss > @memory_size + end + @app.call env + end + end + + class MaxRequests + include Kill + + def initialize(app, max_requests = 1000) + @app = app + @max_requests = max_requests + end + + def call(env) + @process_start ||= Time.now + quit if (@max_requests -= 1) == 0 + @app.call env + end + end +end |