Last active
November 21, 2020 19:06
-
-
Save brauliobo/11298486 to your computer and use it in GitHub Desktop.
Unicorn configuration with master warm up and other daemons as workers support. (See lastest and full version at https://github.com/coletivoEITA/noosfero-cookbook/blob/master/templates/default/unicorn.conf.rb.erb)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
RailsRoot = File.expand_path "#{File.dirname __FILE__}/.." | |
PidsDir = "#{RailsRoot}/tmp/pids" | |
OldPidFile = "#{PidsDir}/unicorn.pid.oldbin" | |
ListenAddress = "127.0.0.1" | |
ListenPort = 50000 | |
UnixListen = "tmp/unicorn.sock" | |
Backlog = 2048 | |
Workers = 4 | |
Timeout = 20 * 60 | |
WarmUp = true | |
WarmUpTime = 1 | |
# caution use non cacheable urls | |
WarmUpUrl = ['/admin/plugins', '/', '/profile/content'] | |
CurrentPrio = Process.getpriority Process::PRIO_PROCESS, 0 | |
# put "* - nice 0" on /etc/security/limits.conf to enable | |
WarmUpRenice = `bash -c 'ulimit -e'`.to_i-20 >= CurrentPrio rescue false | |
WarmUpRenicePrio = 19 | |
begin | |
require 'unicorn/worker_killer' | |
WorkerKiller = true | |
rescue LoadError | |
WorkerKiller = nil | |
end | |
WorkerKillByRequests = 500..600 | |
WorkerKillByMemory = 208..256 | |
WorkerListen = true | |
WorkerPidFile = true | |
WorkerDaemons = { | |
0 => { | |
:name => 'delayed_job', | |
:run => proc{ | |
Delayed::Worker.before_fork | |
Delayed::Command.new([]).run 'delayed_job' | |
}, | |
}, | |
1 => { | |
:name => 'feed-updater', | |
:run => proc{ | |
FeedUpdater.new.start | |
}, | |
}, | |
} | |
working_directory RailsRoot | |
worker_processes (if Workers < WorkerDaemons.count+1 then WorkerDaemons.count+1 else Workers end) | |
timeout Timeout | |
stderr_path "#{RailsRoot}/log/unicorn.stderr.log" | |
stdout_path "#{RailsRoot}/log/unicorn.stdout.log" | |
pid "#{PidsDir}/unicorn.pid" | |
listen "#{RailsRoot}/#{UnixListen}", :backlog => Backlog | |
listen "#{ListenAddress}:#{ListenPort}", :tcp_nopush => true | |
# combine Ruby 2 or REE with "preload_app true" for memory savings | |
# http://rubyenterpriseedition.com/faq.html#adapt_apps_for_cow | |
preload_app true | |
GC.copy_on_write_friendly = true if GC.respond_to? :copy_on_write_friendly= | |
# this is loaded on first run or restart conditions (URS2, HUP). Unset on first before_fork call | |
master_run = true | |
before_fork do |server, worker| | |
if master_run | |
if WarmUp | |
Process.setpriority Process::PRIO_PROCESS, 0, WarmUpRenicePrio if WarmUpRenice | |
require 'rack/test' | |
client = Rack::MockRequest.new server.app | |
Array(WarmUpUrl).each do |url| | |
client.get url | |
end | |
Process.setpriority Process::PRIO_PROCESS, 0, CurrentPrio if WarmUpRenice | |
end | |
# Disconnect since the database connection will not carry over | |
ActiveRecord::Base.connection.disconnect! if defined? ActiveRecord::Base | |
if File.exists? OldPidFile | |
Thread.new do | |
# wait a little for the new master | |
sleep WarmUpTime | |
# a .oldbin file exists if unicorn was gracefully restarted with a USR2 signal | |
# we should terminate the old process now that we're up and running | |
old_pid = File.read(OldPidFile).to_i | |
begin | |
Process.kill "QUIT", old_pid | |
File.delete OldPidFile | |
rescue Errno::ENOENT, Errno::ESRCH | |
# someone else did our job for us | |
end | |
end | |
end | |
master_run = false | |
end | |
end | |
after_fork do |server, worker| | |
daemon = WorkerDaemons[worker.nr] | |
# Start up the database connection again in the worker | |
ActiveRecord::Base.establish_connection if defined? ActiveRecord::Base | |
# reset memcache connection (if using memcache-client) | |
Rails.cache.instance_variable_get(:@data).reset if Rails.cache.class.to_s == 'ActiveSupport::Cache::MemCacheStore' | |
if WorkerKiller | |
Unicorn::WorkerKiller::MaxRequests.new nil, WorkerKillByRequests.begin, WorkerKillByRequests.end if WorkerKillByRequests | |
Unicorn::WorkerKiller::Oom.new nil, WorkerKillByMemory.begin * (1024**2), WorkerKillByMemory.end * (1024**2) if WorkerKillByMemory | |
end unless daemon | |
# say to the kernel to kill very big workers first than other processes | |
# Not very secure | |
#File.open("/proc/#{Process.pid}/oom_adj", "w"){ |f| f << '12' } | |
if WorkerListen | |
# per-process listener ports for debugging/admin/migrations | |
server.listen "#{ListenAddress}:#{ListenPort + worker.nr}", :tries => -1, :delay => 5 | |
end unless daemon | |
if WorkerPidFile | |
child_pid_file = server.config[:pid].sub '.pid', ".#{worker.nr}.pid" | |
system "echo #{Process.pid} > #{child_pid_file}" | |
end | |
end | |
# daemons support | |
require 'active_support/all' | |
class Unicorn::HttpServer | |
def worker_loop_with_daemons worker | |
daemon = WorkerDaemons[worker.nr] | |
if daemon | |
ctx = START_CTX.dup #save for later use with proc_name | |
init_worker_process worker | |
START_CTX.merge! ctx | |
name = "#{worker.nr}:#{daemon[:name]}" | |
proc_name "worker[#{name}]" | |
@logger.info "worker=#{name} ready as a daemon" | |
daemon[:run].call | |
else | |
worker_loop_without_daemons worker | |
end | |
end | |
alias_method_chain :worker_loop, :daemons | |
def awaken_master_with_daemons | |
if SIG_QUEUE.include? :QUIT | |
WORKERS.each do |pid, worker| | |
daemon = WorkerDaemons[worker.nr] | |
next unless daemon | |
Process.kill 'TERM', pid | |
end | |
end | |
awaken_master_without_daemons | |
end | |
alias_method_chain :awaken_master, :daemons | |
end | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment