How can I tell unicorn to understand Heroku's signals?
This is a hack, but I've successfully created a unicorn config file that traps the TERM
signal, preventing unicorn from receiving it and performing its quick shutdown. My signal handler then sends QUIT
signal back to itself to trigger the unicorn graceful shutdown.
Tested with Ruby 1.9.2, Unicorn 4.0.1 and 4.2.1, Mac OS X.
listen 9292
worker_processes 1
# This is a hack. The code is run with 'before_fork' so it runs
# *after* Unicorn installs its own TERM signal handler (which makes
# this highly dependent on the Unicorn implementation details).
#
# We install our own signal handler for TERM and simply re-send a QUIT
# signal to our self.
before_fork do |_server, _worker|
Signal.trap 'TERM' do
puts 'intercepting TERM and sending myself QUIT instead'
Process.kill 'QUIT', Process.pid
end
end
One concern is that (I believe) this signal handler is inherited by worker processes. But, the worker process installs its own TERM
handler, which should overwrite this one, so I would not expect any issue. (See Unicorn::HttpServer#init_worker_process @ lib/unicorn/http_server.rb:551
.Edit: one more detail, this block that installs the signal handler will run once per worker process (because before_fork
), but this merely redundant and won't affect anything.
Optimizing Heroku, Rails, and Unicorn: defining proper configuration options like how many worker processes?
There are two resources you need to run a Rails unicorn worker process: memory and CPU.
Most likely, you will run out of memory before you are able to exhaust the CPU resources on a Heroku dyno. Therefore, measure the loaded in-memory size of your app per unicorn worker and you get a rough number of workers you can fit with some headroom.
For example, if your app need about 110mb (common Rails 3.2 needs), you can fit about 4 on a single 1X dyno.
Heroku provides 2X dynos with more memory and CPU. I do not recommend 2X dynos because they have not delivered 2x performance in our benchmarks.
You can spin up a terminal on a dyno to manually run unicorn and measure the memory usage via:
> heroku run bash
> unicorn -c config/unicorn.rb & # Run unicorn in the background
> ps euf # Read RSS value for each worker, in kb - ie: 116040 ~ 116mb
You can view your Application configuration using:> heroku config
> heroku config | grep WEB_CONCURRENCY # Filter config output to WEB_CONCURRENCY
EDIT:Heroku posted updated information about dyno sizing three months after I originally answered this.
Unicorn swallowing USR2 signals
Just checking back in here - the solution was the same as Unicorn restart issue with capistrano, we completely missed that part of the Unicorn documentation.
How to determine which ruby gem version is actually in use
Run
bundle list | grep unicorn
and it will show the gem version number.
Related Topics
How to Declare a Two-Dimensional Array in Ruby
Pod Install in Xcode Bots Trigger
Ruby Gem Development - How to Use Activerecord
Multistep Form with Activeadmin
Remove Adjacent Identical Elements in a Ruby Array
Running Capybara Without Rack Produces Errors When Using Url Parameters
Completely Random Identifier of a Given Length
Activerecord Join Table for Legacy Database
How to Write (Large) Files with Ruby Eventmachine
Clean Install Osx 10.9.1 Returns "Undefined Method 'Path2Class'" When Trying to Install Gems
Need Help on Reading Emails with "Mail" Gem in Ruby
Why Does Ruby Parallel Assignment with Array of Strings Returns String
Bundler Using Wrong Ruby Version
Sql Like Operator in Ruby on Rails
Does The Rails Orm Limit The Ability to Perform Aggregations