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)