Atualmente, estou usando o Nginx para fazer solicitações de proxy a um servidor Unicorn executando um Sinatra . O aplicativo possui apenas algumas rotas definidas, as quais fazem consultas bastante simples (não onerosas) em um banco de dados PostgreSQL e, finalmente, retornam dados no formato JSON, esses serviços estão sendo monitorados por Deus .
Atualmente, estou experimentando tempos de resposta extremamente lentos desse servidor de aplicativos. Eu tenho outros dois servidores Unicorn sendo proxied via Nginx, e estes estão respondendo perfeitamente bem, então eu acho que posso excluir qualquer ação errada do Nginx.
Aqui está minha configuração de Deus:
# God configuration
APP_ROOT = File.expand_path '../', File.dirname(__FILE__)
God.watch do |w|
w.name = "app_name"
w.interval = 30.seconds # default
w.start = "cd #{APP_ROOT} && unicorn -c #{APP_ROOT}/config/unicorn.rb -D"
# -QUIT = graceful shutdown, waits for workers to finish their current request before finishing
w.stop = "kill -QUIT 'cat #{APP_ROOT}/tmp/unicorn.pid'"
w.restart = "kill -USR2 'cat #{APP_ROOT}/tmp/unicorn.pid'"
w.start_grace = 10.seconds
w.restart_grace = 10.seconds
w.pid_file = "#{APP_ROOT}/tmp/unicorn.pid"
# User under which to run the process
w.uid = 'web'
w.gid = 'web'
# Cleanup the pid file (this is needed for processes running as a daemon)
w.behavior(:clean_pid_file)
# Conditions under which to start the process
w.start_if do |start|
start.condition(:process_running) do |c|
c.interval = 5.seconds
c.running = false
end
end
# Conditions under which to restart the process
w.restart_if do |restart|
restart.condition(:memory_usage) do |c|
c.above = 150.megabytes
c.times = [3, 5] # 3 out of 5 intervals
end
restart.condition(:cpu_usage) do |c|
c.above = 50.percent
c.times = 5
end
end
w.lifecycle do |on|
on.condition(:flapping) do |c|
c.to_state = [:start, :restart]
c.times = 5
c.within = 5.minute
c.transition = :unmonitored
c.retry_in = 10.minutes
c.retry_times = 5
c.retry_within = 2.hours
end
end
end
Aqui está minha configuração do Unicorn:
# Unicorn configuration file
APP_ROOT = File.expand_path '../', File.dirname(__FILE__)
worker_processes 8
preload_app true
pid "#{APP_ROOT}/tmp/unicorn.pid"
listen 8001
stderr_path "#{APP_ROOT}/log/unicorn.stderr.log"
stdout_path "#{APP_ROOT}/log/unicorn.stdout.log"
before_fork do |server, worker|
old_pid = "#{APP_ROOT}/tmp/unicorn.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
Eu verifiquei os registros de status de Deus, mas parece que a CPU e o uso da memória estão nunca fora dos limites. Eu também tenho algo para matar trabalhadores de alta memória, que podem ser encontrados na página do blog do GitHub aqui .
Ao executar um tail -f
nos registros do Unicorn, eu vejo alguns pedidos, mas eles estão longe e poucos entre, quando eu estava por volta de 60-100 por segundo antes desse problema parecer ter chegou. Este log também mostra os trabalhadores sendo colhidos e iniciados como esperado.
Então, minha pergunta é: como eu iria depurar isso? Quais são os próximos passos que devo seguir? Estou extremamente perplexo com o fato de que o servidor às vezes responde rapidamente, mas em outros momentos é muito lento, por longos períodos de tempo (que podem ou não ser tempos de pico de tráfego).
Qualquer conselho é muito apreciado.