Há algumas horas, iniciei um debate sobre o fato de o Node.JS ser muito lento para grandes projetos e preferir Golang, Rust, PHP etc. O principal argumento do lado oposto nessa disputa foi o fato de o JavaScript ser de thread único. Alegadamente, ao desenvolver um aplicativo, a produtividade simplesmente repousa contra esse encadeamento único e nada pode mais ser feito - apenas reescreva-o em outro idioma. No entanto, as coisas são um pouco melhores com o NodeJS do que parece à primeira vista. Antes de nos aprofundarmos neste tópico, quero declarar que respeito o direito de cada desenvolvedor de usar a linguagem de programação que ele gostava e que ele considera preferível em uma tarefa específica.
Tendo pesquisado por uma palavra-chave "PM2" em Habr, não encontrei nenhum artigo dedicado a esse gerente de processos. Apenas referências únicas em artigos de outros usuários. Fiquei empolgado (fortemente informado) com a idéia de atualizar e esclarecer esse canto escuro do desenvolvimento de back-end no Node.JS (que muitas pessoas conhecem, sim, eu sei). Peço a todos os interessados em gato.
Algumas palavras sobre o próprio PM2
O PM2 é um gerenciador de processos de código aberto licenciado sob a licença AGPL-3.0. No momento da redação deste artigo, ele possui ~ 350k downloads semanais, de acordo com o NPM. Ele é usado principalmente em ambientes em que você precisa executar um aplicativo no NodeJS e esquecê-lo (você também pode usá-lo com outros idiomas, mas mais adiante), o que permite agrupar o aplicativo e distribuir de forma flexível a carga entre os núcleos do processador. Um pequeno recorte do
repositório PM2 no GitHub :
O PM2 é um gerenciador de processos de produção para aplicativos Node.js. com um balanceador de carga interno. Ele permite manter os aplicativos ativos para sempre, recarregá-los sem tempo de inatividade e facilitar tarefas comuns de administração do sistema.
Ao desenvolver, muitos recém-chegados encontram um problema quando, depois de "distribuir" o aplicativo para o servidor de produção, não sabem como iniciá-lo "para sempre". Eles escrevem
set NODE_ENV=production && node app.js
no console SSH, está tudo bem, o aplicativo funciona. Feche o console e o aplicativo não funcionará mais. Pergunta sobre o StackOverflow -
Como executar o aplicativo node.js permanentemente? obteve mais de 237 mil visualizações em todos os tempos.
O PM2 resolve esse problema com um comando:
pm2 start app.js
Este comando “demoniza” (do inglês “daemonize”) o processo do NodeJS, monitora o consumo de memória e considera a carga do processador.
De volta aos nossos carneiros
À medida que a carga no back-end aumenta, torna-se necessário dimensioná-lo - vertical e horizontal - para quem é mais conveniente nas circunstâncias. Como sabemos, um processo pode usar vários núcleos de processador, mas somente se houver vários threads dentro do processo. Nos aplicativos NodeJS, o fluxo é um. O PM2 é capaz de ajudar nessa situação e distribuir a carga entre vários núcleos do processador. Ainda com apenas um comando:
pm2 start app.js -i max
Nesse caso, o parâmetro
max corresponde ao número de núcleos do processador. I.e. Serão criados 8 processos separados para o processador de 8 núcleos. Você também pode definir
-1 em vez de
max e
, em seguida, o número de processos corresponderá ao
número de núcleos
menos 1 . Todo o charme é que as conexões HTTP (S) / Websocket / TCP / UDP serão distribuídas igualmente entre esses processos. Por que não escala horizontal? Você pode ler mais sobre clustering no PM2 aqui -
Modo de cluster do PM2 .

Você pode executar quantos processos quiser, mas ainda assim é recomendável seguir a recomendação "um processo por núcleo".
Respeito pela memória
Ao desenvolver em PHP, uma vez encontrei um problema. Devido à inexperiência, ele inconscientemente colocou um bug no mecanismo do sistema, devido ao qual, sob certas condições, os processos começaram a consumir muita RAM. Além disso, o processador foi carregado, por causa do qual a máquina virtual acabou de desligar e eu não tive acesso a ela.
Como os desenvolvedores de PHP sabem, no PHP-FPM você pode especificar o tipo de distribuição de processos (se você não soubesse de repente, no PHP-FPM um novo processo é criado para cada nova solicitação) - estático, quando os limites mínimo e máximo são definidos e dinâmico - alocação de quanto tantos processos grandes quanto necessário. O que acontecerá no PM2 se você iniciar 8 processos e todos começarem a consumir muita memória? E o PM2 é capaz de resolver esse problema - com apenas um parâmetro na linha de comando:
# Set memory threshold for app reload pm2 start app.js -i max --max-memory-restart <200MB>
Cada vez que o limite de memória é atingido, o PM2 reiniciará automaticamente o processo. Distribuir memória é mais fácil do que processos, não é? 8 processos * 200 megabytes = 1,6 gigabytes. Matemática de segunda classe.
Além de reiniciar o processo, você também pode configurar a reinicialização após um N intervalo de tempo. Ainda não descobri em que casos isso pode ser útil, mas sinta-se à vontade para apontar alguns exemplos nos comentários :)
E se eu reiniciar a máquina virtual?
Surpresa-surpresa! O PM2 também resolve esse problema para você. Ainda com não mais de um único comando no console:
pm2 startup
O PM2 gerará um script que aumentará todos os processos necessários quando o sistema operacional for iniciado. No entanto, você deve estar vigilante - ao atualizar a versão do Node.JS, tudo pode quebrar. Para evitar isso, após o upgrade para a nova versão do Node.JS, execute
pm2 unstartup
e
pm2 startup
. Você pode ler mais sobre isso no link -
PM2 Startup Script Generator .
É necessário reiniciar os clusters manualmente ao fazer alterações?
Claro que não! Bem, mais precisamente, você, é claro, pode reiniciar o aplicativo manualmente, mas por quê? Automatize tudo o que puder e que a força venha com você!
pm2 start env.js --watch --ignore-watch="node_modules"
Você pode usar isso ao mesclar uma ramificação principal em um repositório local com uma ramificação principal de um repositório remoto. No meu projeto paralelo, isso é feito simplesmente -
git pull origin master && npm run build
. Ao alterar os arquivos nas pastas
servidor / compilação e
cliente / compilação , os processos serão reiniciados automaticamente. Entendo que esse é um recurso muito simples e nem merece ser mencionado neste texto. Vou diluir isso com algo sério e escrever que, se você usar cluster, todos os processos serão reiniciados por sua vez. Sim, para que pelo menos um deles esteja sempre disponível. Esta é uma implantação com tempo de inatividade zero!
E você não pode reiniciar processos. Há recarga para isso (algo semelhante ao nginx reload):
pm2 reload all
Muitas equipes! Em geral, eu prefiro configurações
Eu já estou entediado em criar frases engraçadas, então é simples e banal: existe um arquivo do ecossistema. Os formatos suportados são JSON, YAML e JS. Por exemplo, quando você precisa monitorar arquivos nas pastas do
servidor e do
cliente :
module.exports = { apps: [{ script: "app.js", watch: ["server", "client"], env_production : { "NODE_ENV": "production" } }] }
Para obter mais informações, consulte o link -
Declaração de aplicativo do PM2 .
E até o monitoramento é!
E não um. Escolha o que você mais gosta. Você pode monitorar no console com o comando:
pm2 monit

Ou use a versão completa de monitoramento baseado na Web:

Você, é claro, não vai acreditar em mim, mas é instalado e iniciado com
um comando:
pm2 plus
E muito, muito mais ...
Suporte declarado ao Heroku e Docker, incremento automático de porta com a capacidade de transferir para
process.env
(quando você precisa executar cada processo em uma porta separada), o lançamento de várias instâncias do PM2 no mesmo sistema operacional, a presença de uma API de software e a capacidade de executar scripts demoníacos do Bash e Python!
Provavelmente perdi algo mais importante ou interessante, que você sempre pode me lembrar nos comentários. Espero que você tenha aprendido algo novo com este artigo.