PM2: abordar a questão do gerenciamento de processos com sabedoria

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 .

cluster_mode

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.

Source: https://habr.com/ru/post/pt480670/


All Articles