Zero Downtime Deployment / TypeScript

Сегодня поговорим о деплое с нулевым даунтаймом в NodeJs приложении.

Для того что бы это было возможным, ваше приложение должно быть запущено в child process. Например используйте PM2 / ts-node-dev

Итак:

Первое что нам нужно сделать, это сообщить о том, что новый (задеплоенный) процесс готов принимать на себя работу передеплоемого приложения. Для этого необходимо вызвать

process.send(“ready”)

В вашем приложении, после того как все необходимые зависимости перейдут в состояние готовности. Например коннект с базой установится и т.п.

Так же в нашем приложении нужно добавить логику, по завершению всех текущих операций при получении сигнала терминации (SIGINT)

process.on(“SIGINT”, () => {
  this.connection.close(); // Например закроем текущие соединение с AMQP и перестанем принимать новые сообщения
  setTimeout(() => {
    process.exit()
  }, 5000) // Подождем 5 сек пока завершаться текущие процессы
})

Запуская такое приложение, например при помощи ts-node-dev, вы можете заметить что после control+c приложение завершается не сразу, а через 5 минут.

Что произойдет:

  • Новое приложение, запущенное в child process запускается и сообщает ready, после чего начинает бизнес логику
  • одновременно с этим старому процессу посылается SIGINT и оно переходит в режим завершения работы и финализазции, после чего уничтожается.

Пример

class App {
  private isOnline = true

  public start() {
    console.log(“Started”)
    this.restartListener()
    this.loop()
  }

  private loop() {
    if (!this.isOnline) return
    console.log(“Some business logic like redis/sql/amqp and others operation”)
    this.loop()
  }

  private restartListener() {
     if (typeof process.send !== “function”) return

     process.send(“ready”)
     process.on(“SIGINT”, () => {
       this.isOnline = false
       setTimeout(() => {
         process.exit()  
       }, 3000)
     })
  }

}