1、基本配置
在配置unicorn时,分两种情况
preload_app true preload_app false
preload_app false的情况下,unicorn的master不预加载rails app整个环境,每个worker都会执行整个rails app.
preload_app true的情况下,unicorn的master会预先加载rails app环境,而且在copy_on_write_friendly的情况下,每个worker都是从master执行写时复制的(节省资源)。
如果是prelad_app true的情况,需要在before_fork中关闭database connection;因为master不需要保持这个连接
before_fork do |server, worker| # 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! end
但是,在after_fork后,需要为每个worker都重新连接上 database connection;
after_fork do |server, worker| # the following is *required* for Rails + "preload_app true", defined?(ActiveRecord::Base) and ActiveRecord::Base.establish_connection end
当有其他的socket连接时,同样需要在after_fork中,重新连接,或者在before_fork中先关闭,然后在after_fork中重新连接。
2、unicorn信号
kill -s HUP pid
当preload_app false 时,会重新加载配置和rails app,所有修改过的代码都会被重新加载,因为是每个worker去重新执行
当preload_app true 时, 会重新加载配置,但不会重新加载rails app,因为每个worker都是从master copy的,因此修改的代码也不会被重新加载
这时,需要如下命令
kill -s USR2 pid
并且在before_fork中自动关闭旧的unicorn进程
before_fork do |server, worker| # 在执行 kill -s USR2 `oldpid`时会执行,因为unicorn将原来的pid文件名增加了.oldbin后缀 old_pid = "#{server.config[: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 puts "Send 'QUIT' signal to unicorn error!" end end end
结果会重新执行unicorn,生成新的进程,并关闭旧的进程