如何在 Node.js Web 服务器中执行重复的长时间运行的后台任务

dob*_*ler 2 node.js express

我正在使用express.js 开发一个node.js Web 服务器,它应该提供一个仪表板来监视数据库服务器。

该架构非常简单:

  • 收集器以预定义的时间间隔检索信息并存储数据
  • express.js 监听用户请求并根据存储的数据显示仪表板

我现在想知道如何最好地实现收集器以确保它不会阻塞主循环,最简单的解决方案似乎是仅使用基于方法,setTimeout但我想知道构建此架构的“正确方法”是什么?

O. *_*nes 6

您关心的是您的信息收集步骤。它可能并不像看起来那样占用大量 CPU 资源。因为它是一个监控应用程序,所以它可能通过联系其他机器来收集信息,就像这样。

async function  gather () {
    const results = []
    let result
    result = await getOracleMetrics ('server1')
    results.push(result)
    result = await getMySQLMetrics ('server2')
    results.push(result)
    result = await getMySQLMetrics ('server3')
    results.push(result)
    await storeMetrics(results)
}
Run Code Online (Sandbox Code Playgroud)

这不是一个 CPU 密集型功能。(如果您要对图像进行快速傅里叶变换,将是一个 CPU 密集型函数。)

它大部分时间都在等待结果,然后用一点时间存储结果。使用 async/await 会给你一种它同步运行的错觉。但是,每个等待都会产生其他事情的主循环。

您可能每分钟都会调用它,就像这样。这些.then().catch()东西异步调用它。

setInterval (
  function go () {
    gather()
      .then()
      .catch(console.error)
  }, 1000 * 60 * 60)
Run Code Online (Sandbox Code Playgroud)

如果您确实需要进行一些 CPU 密集型计算,那么您有几种选择。

  1. 将其卸载到工作线程

  2. 把它分成小块,在它们之间睡觉。

    sleep = function sleep (howLong) {
      return new Promise(function (resolve) {
        setTimeout(() => {resolve()}, howLong)
      })
    }
    
    async function gather () {
       for (let chunkNo = 0; chunkNo < 100; chunkNo++) {
           doComputationChunk(chunkNo)
           await sleep(1)
       }
    }
    
    Run Code Online (Sandbox Code Playgroud)

sleep()函数通过等待超时到期而进入主循环。

抱歉,这些都没有调试。