Ejecutar la aplicación en producción con PM2 (10ª parte de creación de una API REST con Express y TypeScript)

Publicado el 14 diciembre 2022 por Daniel Rodríguez @analyticslane

Una vez finalizada la implementación del API REST con Express y TypeScript para ejecutar esta simplemente habrá que compilar el código e indicarle a Node el archivo de inicio. También se puede usar ts-node para ejecutar el programa sin la necesidad de compilarlo previamente. Aunque esta no es la mejor opción para publicar una aplicación Node en producción. En el caso de que se de un error de ejecución, la aplicación simplemente se apagará al no estar monitorizada. Además, cada vez que se reincide el sistema será necesario volver a iniciar la aplicación manualmente. Problemas que se pueden solucionar en producción con PM2, un gestor de procesos.

¿Qué es PM2?

PM2 es un gestor de procesos para Node con el que se pueden gestionar aplicaciones en producción de una forma sencilla. Haciendo sencillas las tareas habituales de administración. Entre otras características, ofrece la posibilidad de monitorizar las aplicaciones y volverlas a lanzar en el caso de que estas se caigan, evitando de este modo una caída de los servicios. Incluyendo también un balanceador de carga con el que mejorar el rendimiento de los servicios. Además de poder llevar un registro de las aplicaciones.

Algunas de las características más destacadas de PM2 son:

  • Permite gestionar múltiples aplicaciones Node
  • Monitoriza el uso de recursos de cada una de las aplicaciones (memoria, procesador y tiempo en marcha)
  • Almacenado en logs de los mensajes que produce el servidor en la terminal.
  • Permite realizar un balanceo de carga.
  • Reinicio automático de las aplicaciones cuando estas se caen o el código cambia.
  • Inicio automático de las aplicaciones después de un reinicio del servidor.

Instalación de PM2

PM2 es un programa de Node, por lo que la instalación se realiza mediante npm. Así para instalarlo hay que instalar previamente Node y luego escribir en la terminal el comando

npm install -g pm2

Lo que instalara el paquete globalmente. En el caso de que se trabaje en Linux o en macOS se debe anteponer el comando sudo para realizar la instalación.

Arrancar una aplicación con PM2

Ahora para iniciar una aplicación con PM2 solamente se debe ir a la carpeta del proyecto y en lugar de ejecutar el comando

node index.js

Se debe ejecutar el comando

pm2 start index.js

donde index.js es el archivo donde se encuentra la aplicación. Si esto se hace en nuestro proyecto se tendría una salida como la siguiente.

% pm2 start ./dist/index.js  
[PM2] Starting /Users/analyticslane/expresslanets/dist/index.js in fork_mode (1 instance)
[PM2] Done.
┌────┬────────────────────┬──────────┬──────┬───────────┬──────────┬──────────┐
│ id │ name               │ mode     │ ↺    │ status    │ cpu      │ memory   │
├────┼────────────────────┼──────────┼──────┼───────────┼──────────┼──────────┤
│ 0  │ index              │ fork     │ 0    │ online    │ 0%       │ 716.0kb  │
└────┴────────────────────┴──────────┴──────┴───────────┴──────────┴──────────┘

Por defecto la aplicación tomará el nombre del archivo, lo que puede no ser significativo, por lo que se puede asignar un nombre con la opción --name. Aunque antes de asignar un nombre se debe borrar previamente el servicio con el comando delete seguido del id.

pm2 delete 0

Lo que detiene y borrara el proceso. Ahora ya se le puede dar un nombre más significativo al servicio.

% pm2 start ./dist/index.js --name expresslanets
[PM2] Starting /Users/analyticslane/expresslanets/dist/index.js in fork_mode (1 instance)
[PM2] Done.
┌────┬────────────────────┬──────────┬──────┬───────────┬──────────┬──────────┐
│ id │ name               │ mode     │ ↺    │ status    │ cpu      │ memory   │
├────┼────────────────────┼──────────┼──────┼───────────┼──────────┼──────────┤
│ 0  │ expresslanets      │ fork     │ 0    │ online    │ 0%       │ 716.0kb  │
└────┴────────────────────┴──────────┴──────┴───────────┴──────────┴──────────┘

Detener un proceso con PM2

Para detener un proceso se debe usar el comando stop seguido del nombre o id del proceso. Así para detener nuestro servidor se deberá escribir el comando

% pm2 stop expresslanets
[PM2] Applying action stopProcessId on app [expresslanets](ids: [ 0 ])
[PM2] [expresslanets](0) ✓
┌────┬────────────────────┬──────────┬──────┬───────────┬──────────┬──────────┐
│ id │ name               │ mode     │ ↺    │ status    │ cpu      │ memory   │
├────┼────────────────────┼──────────┼──────┼───────────┼──────────┼──────────┤
│ 0  │ expresslanets      │ fork     │ 0    │ stopped   │ 0%       │ 0b       │
└────┴────────────────────┴──────────┴──────┴───────────┴──────────┴──────────┘

Como se puede ver el estado pasa de online a stopped y el uso de memoria se vuelve 0.

Reiniciar un proceso con PM2

El comando con el que se puede reiniciar un servicio detenido es restart, depuesto del cual se debe indicar el nombre del proceso o su id. Para volver a poner en marcha el servicio detenido solamente se tendrá que escribir el comando.

% pm2 restart expresslanets
Use --update-env to update environment variables
[PM2] Applying action restartProcessId on app [expresslanets](ids: [ 0 ])
[PM2] [expresslanets](0) ✓
┌────┬────────────────────┬──────────┬──────┬───────────┬──────────┬──────────┐
│ id │ name               │ mode     │ ↺    │ status    │ cpu      │ memory   │
├────┼────────────────────┼──────────┼──────┼───────────┼──────────┼──────────┤
│ 0  │ expresslanets      │ fork     │ 0    │ online    │ 0%       │ 888.0kb  │
└────┴────────────────────┴──────────┴──────┴───────────┴──────────┴──────────┘

Lo que hace que el estado de servicio vuelva a ser online.

Listado de los proceso en PM2

En cualquier momento se puede consultar el listado de procesos, activos o no, que están gestionados con PM2. Lo que se consigue escribiendo el pm2 con el comando list. Así, para ver el listado de tareas se puede hacer con

% pm2 list
┌────┬────────────────────┬──────────┬──────┬───────────┬──────────┬──────────┐
│ id │ name               │ mode     │ ↺    │ status    │ cpu      │ memory   │
├────┼────────────────────┼──────────┼──────┼───────────┼──────────┼──────────┤
│ 0  │ expresslanets      │ fork     │ 0    │ online    │ 0%       │ 55.5mb   │
└────┴────────────────────┴──────────┴──────┴───────────┴──────────┴──────────┘

Obteniendo una tabla como la anterior.

Consulta de los logs

PM2 también almacena los mensajes que saca por pantalla la aplicación Node, lo que permite mantener un log básico del servidor. Para ello se debe escribir pm2 seguido del comando log para ver el de todas las aplicaciones. Aunque también se puede indicar el nombre o id de un proceso para limitar la salida solo a este. Así, el comando

pm2 log

mientras que

pm2 log expresslanets

mostrará solo el log de expresslanets. Algo que es más interesante ya que habitualmente sólo se revisa el log de una aplicación.

Uso de monit para el monitoreo visual de las aplicaciones en producción con PM2

Además de lo visto hasta ahora PM2 también ofrece la posibilidad de monitorizar el estado de los servicios con una aplicación de terminal llamada monit. Para iniciarla solamente se debe escribir en la terminal el comando

pm2 monit

obteniendo como resultado una ventana como la siguiente.

Reiniciar los procesos tras el inicio del sistema

Para reiniciar los procesos después de un reinicio del sistema es necesario crear un script de inicio. Una de las características clave a la hora de poner un programa en producción con PM2. La creación de este script lo puede realizar el propio PM2 ejecutando el siguiente comando en la terminal

pm2 startup

El cual detectará automáticamente el sistema operativo y realizará las tareas necesarias. En caso de que no sea así se puede indicar el nombre del sistema operativo detrás como parámetro.

Ahora PM2 se iniciará automáticamente después de cada reinicio del sistema, pero todavía no iniciarán los servicios. Para que los servicios se reinicien es necesario guardar la configuración con el comando save de pm2, esto es, escribiendo en la terminal

pm2 save

Nótese que esta operación se tendrá que repetir cada vez que se cambie alguna opción de algún servicio.

Conclusiones

En esta última publicación de la serie creación de una API REST con Express y TypeScript se ha visto cómo se puede poner en producción el servicio con PM2. Aunque no es necesario, ya que se puede iniciar el programa solo con Node, el uso de PM2 facilita las tareas de mantenimiento. Permite que todas las aplicaciones que se encuentren en un servidor puedan reiniciarse automáticamente cuando este se inicie. Además de monitorizar y garantizar que estas están funcionando.

Imagen de Tayeb MEZAHDIA en Pixabay