Nginx + Unicorn
Desde que a Phusion lançou o passenger eu sempre o utilizei em conjunto com o apache que já era familizarizado.
Quando trabalhei na Digital Pages me deparei com o pessoal utilizando o passenger com nginx, pra falar a verdade eu só tinha escutado falar deste servidor web e nem dei muita bola, além de que a aplicação caia de tempos em tempos e o log ficava poluído com algumas mensagens que o passenger adicionava, mostrei para o pessoal como utilizar o apache no lugar do nginx, a aplicação acabou ficando bem estável e optamos por colocar em produção.
De lá pra cá procurei evitar o nginx porém o servidor que está rodando este blog também está rodando outras aplicações como o gettherank e comecei a ter alguns problemas com memória, visto que o passenger não consegue lidar muito bem com os processos que ficam muito tempo ativos aumentando o consumo ao extremo, seguindo alguns conselhos resolvi dar mais uma chance para o nginx, porém não com o passenger e sim com o unicorn criado pelo Chris Wanstrath pra suportar o Github.
Confesso que antes mesmo de usar o unicorn pensei que seria uma tarefa muito complexa, mas hoje depois de configurar este servidor que você está acessando devo dizer que é tão fácil quanto, então resolvi compartilhar a configuração que utilizei tanto pro unicorn como para o nginx e quem sabe isso não o ajude a usar esta combinação também.
working_directory "/var/www/marciotrindade/current" pid "/var/www/marciotrindade/shared/pids/unicorn.pid" stderr_path "/var/www/marciotrindade/shared/log/unicorn.log" stdout_path "/var/www/marciotrindade/shared/log/unicorn.log" preload_app true listen 5002 worker_processes 2 timeout 30
Todas estas e as demais configurações do unicorn você pode encontrar aqui
server {
listen 80;
server_name marciotrindade.com www.marciotrindade.com;
if ($host = 'www.marciotrindade.com' ) {
rewrite ^/(.*)$ http://marciotrindade.com/$1 permanent;
}
root /var/www/marciotrindade/current/public;
try_files $uri/index.html $uri.html $uri @unicorn;
location ~ ^/assets/ {
expires 1y;
add_header Cache-Control public;
add_header Last-Modified "";
add_header ETag "";
break;
}
location @unicorn {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://localhost:5002;
}
client_max_body_size 4G;
keepalive_timeout 10;
error_page 500 502 503 504 /500.html;
location = /500.html {
root /var/www/marciotrindade/current/public;
}
}Recomendo ler a wiki do nginx onde você irá encontrar mais detalhes destas e outras configurações interessantes pra melhorar a velocidade da sua aplicação.
Estas configurações) que utilizei foram retiradas do prórpio código do projeto que mostra estes e outros tantos exemplos, incluindo o arquivo abaixo pra iniciar, reiniciar e para o unicorn.
#!/bin/sh
set -e
# Example init script, this can be used with nginx, too,
# since nginx and unicorn accept the same signals
# Feel free to change any of the following variables for your app:
TIMEOUT=${TIMEOUT-60}
APP_ROOT=/var/www/marciotrindade/current
PID=$APP_ROOT/tmp/pids/unicorn.pid
CMD="unicorn -D -c $APP_ROOT/config/unicorn.rb -E production"
action="$1"
set -u
old_pid="$PID.oldbin"
cd $APP_ROOT || exit 1
sig () {
test -s "$PID" && kill -$1 `cat $PID`
}
oldsig () {
test -s $old_pid && kill -$1 `cat $old_pid`
}
case $action in
start)
sig 0 && echo >&2 "Already running" && exit 0
$CMD
;;
stop)
sig QUIT && exit 0
echo >&2 "Not running"
;;
force-stop)
sig TERM && exit 0
echo >&2 "Not running"
;;
restart|reload)
sig HUP && echo reloaded OK && exit 0
echo >&2 "Couldn't reload, starting '$CMD' instead"
$CMD
;;
upgrade)
if sig USR2 && sleep 2 && sig 0 && oldsig QUIT
then
n=$TIMEOUT
while test -s $old_pid && test $n -ge 0
do
printf '.' && sleep 1 && n=$(( $n - 1 ))
done
echo
if test $n -lt 0 && test -s $old_pid
then
echo >&2 "$old_pid still exists after $TIMEOUT seconds"
exit 1
fi
exit 0
fi
echo >&2 "Couldn't upgrade, starting '$CMD' instead"
$CMD
;;
reopen-logs)
sig USR1
;;
*)
echo >&2 "Usage: $0 <start|stop|restart|upgrade|force-stop|reopen-logs>"
exit 1
;;
esacAproveitei e mudei o meu arquivo de deploy do capistrano pra utilizar este script pra reiniciar a minha aplicação, mas como eu utilizo os releases o restart não estava funcionando então passei a utilizar o stop seguido pelo start.
... namespace :deploy do task :start do ; end task :stop do ; end task :restart, :roles => :app, :except => { :no_release => true } do run "#{deploy_to}/init.sh stop && sleep 2 && #{deploy_to}/init.sh start" end end ...
PS.: No dia 24 de outubro o Rain Bates publicou um screencast pro mostrando também esta combinação com uma configuração muito parecida com a que mostrei acima.