【问题标题】:NodeJs App - Repeated job - Single or multiple child processes?NodeJs App - 重复作业 - 单个或多个子进程?
【发布时间】:2016-07-07 01:56:46
【问题描述】:

我目前正在开发一个带有 REST API 的节点 js 应用程序,该应用程序公开来自 mongo db 的数据。

应用程序需要每 5 分钟通过调用外部服务更新一些数据(可能需要一分钟以上才能获取新数据)。

我决定将此任务隔离到一个子进程中,但我不确定我应该在这个子进程中添加什么:

  • 只有要执行的函数。调度由主进程管理。
  • 拥有一个独立的进程,每 5 分钟自动刷新一次数据,并在每次刷新完成时向主进程发送一条消息。

我真的不知道每 5 分钟启动一个新的子进程是否需要很大的成本,或者我是否应该只使用一个长时间运行的子进程,或者我是否过度考虑了问题^^

编辑 - 更新任务的信息

更新任务可能需要不到一分钟的时间,但它包含许多较小的任务(从许多外部提供者那里收集信息),而不是异步运行,我什至不需要子进程?

谢谢!

【问题讨论】:

    标签: node.js child-process


    【解决方案1】:

    Node.js 具有能够处理异步调用的事件驱动架构,因此它不同于典型的 C++ 程序,您将使用多线程/进程架构。

    对于您的用例,我想也许您可以利用setInterval 重复执行一个操作,您可以通过使用某种promises 框架(如bluebirdJS)来定义更多微小的异步调用?

    有关详细信息,请参阅:

    setIntervalhttps://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setInterval

    setInterval()

    反复调用一个函数或者执行一段代码sn-p,有固定的 每次通话之间的时间延迟。返回一个区间ID。

    示例代码:

    setInterval(function() {
        console.log("I was executed"); 
    }, MILLISECONDS_IN_FIVE_MINUTE);
    

    承诺http://bluebirdjs.com/docs/features.html

    示例代码:

    new Promise(function(resolve, reject) {
      updateExternalService(data)
        .then(function(response) {
            return this.parseExtResp(response);  
        })
        .then(function(parsedResp) {
            return this.refreshData(parsedResp);
        })
        .then(function(returnCode) {
            console.log("yay updated external data source and refreshed");
            return resolve();
        })
        .catch(function(error) {
            // Handle error
            console.log("oops something went wrong ->" + error.message);
            return reject();
        });
      }
    

    【讨论】:

    • 我已经在使用 promise 和 setInterval,我只是想知道是否需要将任务隔离到一个单独的进程中?有意义吗?
    • 您这样做仅仅是因为您遇到了一些性能问题吗?嗯,多进程节点架构对我来说不太有意义。您是否正在尝试利用所有 CPU 内核?可能首先检查lscpu 是什么样的,如果您意识到您的节点应用程序仅集中使用 10 个 CPU 内核中的 1 个并且程序无法再扩展,那么可能尝试多子项。否则做一个代码分析会更好吗?
    • 可能是我想太多问题了,因为我暂时没有任何性能问题......所以如果没有性能问题也没有阻塞代码,我只需要让事件循环完成这项工作吗?
    • 是的。相信 NodeJS 的事件驱动架构!哈哈。
    • @Thomas 但是如果你注意到你的核心由于某种原因没有得到充分利用,那么生成多子节点可能值得探索,但这可能是最后几个选项。
    【解决方案2】:

    只要您使用异步请求,从外部服务获取数据所需的总时钟时间并不重要。重要的是您在此过程中使用了多少 CPU。如果大部分时间都在等待外部服务响应或发送数据,那么您的 node.js 服务器大部分时间都处于空闲状态,您可能不需要子进程。

    由于 node.js 是异步的,它可以很高兴地拥有许多“正在运行”的打开请求,等待响应并且占用很少的系统资源。

    因为 node.js 是单线程的,所以 CPU 使用率通常会推动对子进程的需求。如果从外部服务获得响应需要 5 分钟,但实际 CPU 时间只需要 50 毫秒来处理该请求并对其进行处理,那么您可能不需要子进程。

    如果是我,我会将用于与外部服务通信的代码分离到它自己的模块中,但我不会增加子进程的复杂性,直到您实际拥有一些需要进行此类更改的数据.


    我真的不知道开始一个新孩子是否需要很大的成本 每 5 分钟处理一次,或者如果我应该只使用一次长时间运行 子进程,或者我想太多问题

    启动一个新的子进程肯定有一些成本。它不是很大,但是如果您打算每 5 分钟执行一次并且不需要大量内存,那么最好只启动一次子进程,让它管理与通信的调度外部服务完全依靠它自己,然后它可以根据需要将结果传回给您的其他 node.js 进程。这使得第二个节点进程更加独立,并且两个进程之间唯一的交互点是通信更新。这种功能和责任的分离通常被认为是一件好事。在多开发者项目中,您可以更轻松地让不同的开发者开发每个应用程序。

    【讨论】:

    • 好的解释,所以如果我没有一些阻塞任务,我不应该在问题(=性能问题)发生之前担心这个?
    • @Thomas - 是的,这就是我的建议。在你有实际证据证明需要之前,不要把事情复杂化。
    【解决方案3】:

    这取决于您的应用和自动刷新任务之间的凝聚力。

    如果自动刷新任务可以独立运行,无需与您的应用交互,那么最好将您的任务作为一个新进程启动。直接使用child_process不好,spawn/monitor/respawn子进程比较麻烦,可以使用crontab或者pm2来管理。

    如果自动刷新任务依赖于您的应用程序,您可以直接使用 child_process,向它发送消息以进行调度。但是首先尝试打破这种依赖关系,这将简化您的应用程序,易于单独部署和维护。子进程运行时间很长,或者只有在一台机器上运行数百个这样的任务之前,一次射击不是问题。

    【讨论】:

    • 很有趣,所以也许有一个队列让他们交流可能对我来说是一个解决方案!谢谢
    • 父子IPC通道已经内置:child.send
    • 是的,我看到了,但它只有在你有父/子进程时才有效
    • 如果刷新完成,子进程可以通过调用它的 REST API 来通知您的应用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-06-29
    • 1970-01-01
    • 2013-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-10
    相关资源
    最近更新 更多