Front End

9 jan, 2014

PM2 – mantendo o node.js no ar

Publicidade

O módulo PM2 é um gerenciador de processos para aplicações Node.js em modo cli (command line) bem como, um distribuidor automático de “cores”. Neste artigo iremos simular uma queda do processo node.js e sua reinicialização “auto-magicamente”. Para isto iremos usar o exemplo básico de um http server fornecido no próprio site node.js

# touch app.js
var http = require('http');  
http.createServer(function (req, res) {  
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello World\n');
}).listen(1337, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/');

Instalando o PM2 em modo global:

# npm install pm2 -g

Iniciando o PM2 em modo fork:

Estamos usando o modo Fork (-x) o qual inicia o node em um processo a parte:

`# pm2 start app.js -x

Verificando se o processo foi iniciado com sucesso:

pm2 start app.js -x  
PM2 Process successfully started  
┌──────────┬────┬──────┬──────┬────────┬──────┬───────────┬────────┬──────────┬─────────────────────────────┐
│ App Name │ id │ mode │ PID  │ status │ port │ Restarted │ Uptime │   memory │ err logs                    │
├──────────┼────┼──────┼──────┼────────┼──────┼───────────┼────────┼──────────┼─────────────────────────────┤
│ app      │ 0  │ fork │ 4715 │ online │      │         0 │ 0s     │ 4.941 MB │ /root/.pm2/logs/app-err.log │
└──────────┴────┴──────┴──────┴────────┴──────┴───────────┴────────┴──────────┴─────────────────────────────┘

Agora vamos criar uma rota e forçar um erro:

var http = require('http');  
http.createServer(function (req, res) {  
  res.writeHead(200, {'Content-Type': 'text/plain'});

    if (req.url=='/test'){  
        res.end('Hello World\n');
        qq.coisa = qq.coisa; // Aqui forçamos o erro
    }else
        console.log('a rota é: /test');
}).listen(1337, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/');

Agora vamos realizar um acesso para o erro ocorrer:

curl http://localhost:8080/test

Notem que este acesso não apresentou o output error no terminal/console.

# pm2 list
Notem que agora temos "1"  na coluna Restarted

Verificando se o erro ocorreu e reiniciando o node.js “auto-magicamente”:

# pm2 list

PM2  Process listing  
┌──────────┬────┬──────┬──────┬────────┬──────┬───────────┬────────┬──────────┬─────────────────────────────┐
│ App Name │ id │ mode │ PID  │ status │ port │ Restarted │ Uptime │   memory │ err logs                    │
├──────────┼────┼──────┼──────┼────────┼──────┼───────────┼────────┼──────────┼─────────────────────────────┤
│ app      │ 0  │ fork │ 4719 │ online │      │         1 │ 29s    │ 9.297 MB │ /root/.pm2/logs/app-err.log │
└──────────┴────┴──────┴──────┴────────┴──────┴───────────┴────────┴──────────┴─────────────────────────────┘

Acessando os logs de erros que agora estão no PM2:

#cat /root/.pm2/logs/app-err.log 

app.js:7  
        qq.coisa = qq.coisa;  //aqui está o erro que forçamos...
        ^
ReferenceError: qq is not defined  
    at Server.<anonymous> (/root/node-http/app.js:7:3)
    at Server.EventEmitter.emit (events.js:98:17)
    at HTTPParser.parser.onIncoming (http.js:2108:12)
    at HTTPParser.parserOnHeadersComplete [as onHeadersComplete] (http.js:121:23)
    at Socket.socket.ondata (http.js:1966:22)
    at TCP.onread (net.js:525:27)

Outros comandos interessantes:

#pm2 monit -exibe o consumo de CPU e memória para cada processo
#pm2 web -  API que escuta na porta 9615 e gera um log em JSON mais completo do que o monit
#pm2 reload all - reinicia o node sem perder as conexões (somente na versão do node v0.11 que está em desenvolvimento)