Continuando a introdução dada pelo nosso amigo que vence guerras, falarei um pouco mais sobre o Starman e, como ele, não falarei sobre PSGI/Plack porque esses assuntos já foram muito bem explorados em outros e equinocios.
Essa arquitetura é baseada na arquitetura que o Github usa/usava que eles explicam nesse post eles falam sobre como eles utilizam o Unicorn, o Starman foi baseado nesse cara o Miyagawa inclusive usou o nome Unicorn como "inspiração" para o nome Starman:
"The name Starman is taken from the song (Star na Otoko) by the Japanese rock band Unicorn (yes, Unicorn!). It's also known as a song by David Bowie, a power-up from Super Mario Brothers and a character from Earthbound, all of which I love."
Mais um pouco sobre a historia do nome do Starman no blog dele:
Good name for Perl UNIX forking web server?
O fonte desse artigo, assim como todos os arquivos de configuração e inicialização estão nesse gist não fique copiando e colando daqui, você pode pegar o arquivo separado lá ;)
Eu fiz uma busca no APT agora, e não vi nenhum pacote do Starman.
Mas isso não significa que você vai jogar essa bomba na mão do seu sysadmin, seja gentil com ele como diria o Bruce Lee:
"Be L<Devops my friend|http://devops.com/>"
Faça scripts de inicialização, não é algo tão dificil e Shell Script é uma linguagem fácil e que faz de você um desenvolvedor melhor eu precisei subir o Starman em um CentOS e no Debian, abaixo estão os arquivos de inicialização para cada uma dessas distribuições a versão do Debian teve a revisão e ajustes do Nuba - eu tinha esquecido algum header/conf ;)
Debin:
#!/bin/bash
### BEGIN INIT INFO
# starman - this script starts and stops the starman daemon
# Provides: starman_sppm
# Required-Start: $local_fs $remote_fs $network $syslog
# Required-Stop: $local_fs $remote_fs $network $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: starts the starman server
# Description: starts starman using start-stop-daemon
### END INIT INFO
NAME=starman
DESC=starman
test -x $DAEMON || exit 0
set -e
. /lib/lsb/init-functions
## Variáveis de conf da sua App, ALTERE ISSO ANTES DE QUALQUER COISA.
export starman="/usr/bin/starman"
export myapp_path="/var/www/myapp"
export pidfile="/var/run/starman.pid"
start() {
echo -n $"Starting Starman: "
## eu inicio o starman para debug na porta 8080, é bom para testar algumas coisas dando bypass no nginx e tanto o log, quando o PID são criados com o usuário do nginx, para ficar mais fácil
$starman -I${myapp_path}/lib --user=nginx --listen :8080 --listen /var/run/nginx/starman.sock --daemonize --pid ${pidfile} --error-log /var/log/nginx/starman.log ${myapp_path}/${myapp}.psgi
RETVAL=$?
echo
[ $RETVAL = 0 ]
return $RETVAL
}
restart() {
echo -n $"Restarting Starman: "
export PID=`cat ${pidfile}`
kill -s USR2 $PID
RETVAL=$?
echo
[ $RETVAL = 0 ]
return $RETVAL
}
stop() {
echo -n $"Stopping Starman: "
killproc -p ${pidfile} -d 10 $starman
RETVAL=$?
echo
[ $RETVAL = 0 ] && rm -f ${pidfile}
}
# See how we were called.
case "$1" in
start)
start
;;
restart)
restart
;;
stop)
stop
;;
*)
echo $"Usage: starman {start|restart|stop}"
exit 1
esac
exit $RETVAL
CentOS
#!/bin/bash
# starman - this script starts and stops the starman daemon
#
# chkconfig: - 85 15
# description: Starman
# processname: starman
# pidfile : /var/run/starman.pid
# www file: /var/www/myapp
# Source function library.
. /etc/rc.d/init.d/functions
## Variáveis de conf da sua App, ALTERE ISSO ANTES DE QUALQUER COISA.
export starman="/usr/bin/starman"
export myapp_path="/var/www/myapp"
export pidfile="/var/run/starman.pid"
start() {
echo -n $"Starting Starman: "
## eu inicio o starman para debug na porta 8080, é bom para testar algumas coisas dando bypass no nginx e tanto o log, quando o PID são criados com o usuário do nginx, para ficar mais fácil
$starman -I${myapp_path}/lib --user=nginx --listen :8080 --listen /var/run/nginx/starman.sock --daemonize --pid ${pidfile} --error-log /var/log/nginx/starman.log ${myapp_path}/${myapp}.psgi
RETVAL=$?
echo
[ $RETVAL = 0 ]
return $RETVAL
}
restart() {
echo -n $"Restarting Starman: "
export PID=`cat ${pidfile}`
kill -s USR2 $PID
RETVAL=$?
echo
[ $RETVAL = 0 ]
return $RETVAL
}
stop() {
echo -n $"Stopping Starman: "
killproc -p ${pidfile} -d 10 $starman
RETVAL=$?
echo
[ $RETVAL = 0 ] && rm -f ${pidfile}
}
# See how we were called.
case "$1" in
start)
start
;;
restart)
restart
;;
stop)
stop
;;
*)
echo $"Usage: starman {start|restart|stop}"
exit 1
esac
exit $RETVAL
Como vocês leram, ou não, no post do github a arquitetura deles consistem em usar o servidor do Unicorn atrás do Nginx e a comunidação entre eles é feita via Unix Socket \,,/
O Nginx fala diretamente com os "workers" do Starman atráves do Starman Master, quando o Starman inicia ele sobe 'n' workers que são controlados pelo processo principal, toda requisição é processado pelos workers.
Com isso você ganha algumas funcionalidades interessantes como hotdeploy, que é o ato de você subir uma nova versão da sua aplicação com ZERO DOWNTIME!!!!111
Como funciona, basta você atualizar os arquivos da sua aplicação - não irá alterar nada até você reiniciar o serviço - e na hora de reiniciar o serviço é só mandar o sinal USR2 para o PID Master do Starman, isso irá dizer para ele que a aplicação precisa ser reiniciada ele irá reiniciar os seus workers paulatinamente, assim que eles ficarem ociosos até que todos estejam rodando a nova versão da aplicação.
Ah, a função restart dos arquivos de inicialização que eu falei lá em cima já faz esse trabalho :)
Por padrão o Starman inicia apenas 5 workers, eles podem aguentar bastante coisa, mas dependendo da sua configuração de hardware você pode ter mais mas cuidado com swap, se a memoria está indo para swap é bom você diminuir esse número.
upstream myapp_starman {
server unix:/tmp/starman.sock fail_timeout=0;
}
server {
listen 80;
client_max_body_size 1024m;
client_body_buffer_size 8k;
proxy_read_timeout 300;
##
# basic
##
server_name www.localhost.com;
root /home/user/MyApp/root;
keepalive_timeout 0;
##
# logging
##
access_log /var/log/nginx/myapp.access combined;
error_log /var/log/nginx/myapp.error;
location /static {
root /home/user/MyApp/root/;
autoindex on;
}
##
# proxy
##
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_buffering off;
if (!-f $request_filename) {
proxy_pass http://myapp_starman;
}
}
}
Lindolfo "Lorn" Rodrigues - lorn at cpan.org