Commit d599096a authored by Kirill Smelkov's avatar Kirill Smelkov

gitlab/unicorn.rb: Configure preload_app and pre-/post- forking actions

Unicorn is a forking server with the idea that master process preloads
heavy Ruby-on-Rails application, and then to handle new request a worker
process is forked with application already loaded in its memory (and
modification being tracked by OS via copy-on-write).

From this point of view the only reasonable value for preload_app is
always "true" and omnibus-gitlab does this:

    https://gitlab.com/gitlab-org/omnibus-gitlab/blob/8eda0933/files/gitlab-cookbooks/gitlab/definitions/unicorn_service.rb#L65

Then unicorn documentation shows what code has to be there in pre-/post-
forking event:

    http://bogomips.org/unicorn.git/tree/examples/unicorn.conf.rb?id=3312aca8#n57

GitLab uses only part of it that "allows a new master process to
incrementally phase out the old master process with SIGTTOU to avoid a
thundering herd":

    https://gitlab.com/gitlab-org/omnibus-gitlab/blob/8eda0933/files/gitlab-cookbooks/gitlab/definitions/unicorn_service.rb#L69
    http://bogomips.org/unicorn.git/tree/examples/unicorn.conf.rb?id=3312aca8#n75

but strangely does not use code parts that are "highly recommended" or
"require" for "Rails + "preload_app true"" case.

For the reference I've added such codes, but kept them being commented
out.

/cc @kazuhiko, @jerome
parent 0aae33d9
......@@ -18,25 +18,50 @@ working_directory '{{ gitlab_work.location }}'
timeout {{ cfg('unicorn_worker_timeout') }}
# Whether the app should be pre-loaded
preload_app <%= @preload_app %>
preload_app true
# How many worker processes
worker_processes {{ cfg('unicorn_worker_processes') }}
<%- if @before_fork %>
# about before_fork / after_fork - see:
# https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/files/gitlab-cookbooks/gitlab/definitions/unicorn_service.rb
# http://bogomips.org/unicorn.git/tree/examples/unicorn.conf.rb?id=3312aca8#n75
# What to do before we fork a worker
before_fork do |server, worker|
<%= @before_fork %>
# XXX why gitlab does not enable this?
# # the following is highly recomended for Rails + "preload_app true"
# # as there's no need for the master process to hold a connection
# defined?(ActiveRecord::Base) and
# ActiveRecord::Base.connection.disconnect!
# This allows a new master process to incrementally
# phase out the old master process with SIGTTOU to avoid a
# thundering herd (especially in the "preload_app false" case)
# when doing a transparent upgrade. The last worker spawned
# will then kill off the old master process with a SIGQUIT.
old_pid = "#{server.config[:pid]}.oldbin"
if old_pid != server.pid
begin
sig = (worker.nr + 1) >= server.worker_processes ? :QUIT : :TTOU
Process.kill(sig, File.read(old_pid).to_i)
rescue Errno::ENOENT, Errno::ESRCH
end
end
end
<%- end %>
<%- if @after_fork %>
# What to do after we fork a worker
after_fork do |server, worker|
<%= @after_fork %>
# per-process listener ports for debugging/admin/migrations
# addr = "127.0.0.1:#{9293 + worker.nr}"
# server.listen(addr, :tries => -1, :delay => 5, :tcp_nopush => true)
# XXX why gitlab does not enable this?
# # the following is *required* for Rails + "preload_app true",
# defined?(ActiveRecord::Base) and
# ActiveRecord::Base.establish_connection
end
<%- end %>
# Where to drop a pidfile
pid '{{ directory.run }}/unicorn.pid'
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment