Ruby, Mina, Puma e Upstart ftw!

Faz um tempo que mudei do Unicorn para o Puma, o motivo é porque precisavamos de um servidor multi-thread, dado que o Unicorn é baseado em fork de processos..

Assim como o Unicorn, precisamos fazer o controle de pid files com Puma, na net a gente encontra vários scripts para fazer isso, porém eu prefiro utilizar a gema mina-puma já que também uso o mina para deploys.

Basta incluir gem 'mina-puma', require: false no Gemfile e então já ganhamos algumas tarefas pra iniciar, parar, e reiniciar o Puma.

Usamos um serviço de CI para rodar testes e fazer deploy no staging, porém, vira e mexe acontecia deste último falhar na task de reinicar o Puma retornando a mensagem Puma is not running!.

Para contornar isso, simplesmente adicionei uma verificação antes da task no config/deploy.rb:

to :launch do
  # ....
  result = capture("[ -e #{deploy_to}/#{shared_path}/tmp/sockets/pumactl.sock ] && echo 'running' || echo 'not running'")

  if result.include?('not')
    puts 'not running'
    invoke :'puma:start'
  else
    puts 'running'
    if rails_env == 'staging'
      puts 'puma:restart'
      invoke :'puma:restart'
    else
      puts 'puma:phased_restart'
      invoke :'puma:phased_restart'
    end
  end
end

Na primeira linha checamos se o servidor de aplicação está rodando e então iniciamos ou reiniciamos..

Estava tudo ok, até que um dia precisamos reinicar o servidor e ele não subiu o Puma também, ou seja, site off. Como solução eu criei um serviço no Upstart do servidor para executar o mesmo script que a gema mina-puma roda:

# /etc/init/puma.conf
description "Puma"
start on runlevel [2345]
stop on runlevel [016]
respawn

env APP_BASE_PATH=/ebs/storage/www/my_app
env APP_ENV=staging

post-start script
  exec su - deploy -c "cd $APP_BASE_PATH/current && bundle exec puma -q -d -e $APP_ENV -b unix://$APP_BASE_PATH/shared/tmp/sockets/puma.sock -S $APP_BASE_PATH/shared/tmp/sockets/puma.state --pidfile $APP_BASE_PATH/shared/tmp/pids/puma.pid --control unix://$APP_BASE_PATH/shared/tmp/sockets/pumactl.sock"
end script

post-stop script
  exec su - deploy -c "cd $APP_BASE_PATH/current && bundle exec pumactl -S $APP_BASE_PATH/shared/tmp/sockets/puma.state stop; rm -f $APP_BASE_PATH/shared/tmp/sockets/pumactl.sock"
end script

Agora ao ligar o servidor o Puma será inicado automaticamente e também podemos usar sudo service puma start e sudo service puma stop para iniciar/parar.

Abs.

Written on July 20, 2015

Share: