【问题标题】:How to have heavy processing operations done in node.js如何在 node.js 中完成繁重的处理操作
【发布时间】:2013-02-25 09:11:14
【问题描述】:

我有一个繁重的数据处理操作,我需要每 10-12 个模拟请求完成一次。我已经读到,对于更高级别的并发,Node.js 是一个很好的平台,它通过非阻塞事件循环来实现。

我所知道的是,对于查询数据库之类的事情,我可以将一个事件生成到一个单独的进程(如mongodmysqld),然后有一个回调来处理该进程的结果。很公平。

但是,如果我想在回调中完成大量计算,该怎么办。在该回调中的代码完全执行之前,它不会阻止其他请求。例如,我想处理高分辨率图像,而我拥有的代码在 Javascript 本身中(no separate 进行图像处理的进程)。

我认为实现的方式是这样的

get_image_from_db(image_id, callback(imageBitMap) {
    heavy_operation(imageBitMap); // Can take 5 seconds.
});

heavy_operation 是否会阻止节点在这 5 秒内接收任何请求。还是我在想错误的方式来完成这项任务。请指导,我是JS新手。

更新

或者我可以处理部分图像并让事件循环返回以接收其他回调并返回处理该部分图像。 (类似于优先事件)。

【问题讨论】:

    标签: node.js image-processing


    【解决方案1】:

    是的,它会阻止它,因为回调函数在主循环中执行。只有异步调用的函数不会阻塞循环。据我了解,如果您希望图像处理异步执行,则必须使用单独的进程来执行此操作。

    请注意,您可以编写自己的异步进程来处理它。首先,您可以阅读How to write asynchronous functions for Node.js 的答案。

    更新

    how do i create a non-blocking asynchronous function in node.js? 也可能值得一读。这个问题实际上在我链接的另一个问题中被引用,但为了简单起见,我想我会在这里包含它。

    【讨论】:

    • 但是,如果我有单独的进程来处理那个繁重的操作,并且如果我说有 15 个请求进来。它不会创建 15 个进程。那将是非常昂贵的。我不能喜欢在节点中创建线程吗?顺便感谢您的回答。一旦我的疑虑消除,我会接受它:)
    • 是的,它将创建 15 个进程,据我所知,您无法在 Node.js 中创建线程。它有一个线程,这是您的主事件循环。另一种选择是编写一个单独的 Node worker 应用程序,它对通过消息队列(RabbitMQ 或其他东西)传递给它的任务进行图像处理。然而,这只会同步处理图像(一次一个)。如果您希望同时处理它们,则必须创建单独的进程。
    • 我想我现在明白了。感谢伙伴的帮助和时间。
    【解决方案2】:

    很遗憾,我还没有足够的声望点来评论尼克的回答,但你有没有看过Node's cluster API?它目前仍处于试验阶段,但它允许您生成多个线程。

    【讨论】:

      【解决方案3】:

      当在回调中完成大量计算时,事件循环将被阻塞,直到计算完成。这意味着回调将阻塞事件循环 5 秒。

      我的解决方案

      可以使用生成器函数将控制权交还给事件循环。我将使用运行 3 秒的 while loop 作为长时间运行的回调。

      没有生成器函数

      let start = Date.now();
      
      setInterval(() => console.log('resumed'), 500);
      function loop() {
          while ((Date.now() - start) < 3000) { //while the difference between Date.now() and start is less than 3 seconds
              console.log('blocked')
          }
      }
      
      loop();
      

      输出将是:

      // blocked
      // blocked
      //
      //  ... would not return to the event loop while the loop is running
      //
      // blocked
      //...when the loop is over then the setInterval kicks in
      // resumed
      // resumed
      

      带有生成器功能

      let gen;
      let start = Date.now();
      
      setInterval(() => console.log('resumed'), 500);
      
      function *loop() {
          while ((Date.now() - start) < 3000) { //while the difference between Date.now() and start is less than 3 seconds
              console.log(yield output())
          }
      }
      
      function output() {
          setTimeout(() => gen.next('blocked'), 500)
      }
      
      gen = loop();
      gen.next();
      

      输出是:

      // resumed
      // blocked
      //...returns control back to the event loop while though the loop is still running
      // resumed
      // blocked
      //...end of the loop
      // resumed
      // resumed
      // resumed
      

      使用 javascript 生成器可以帮助运行繁重的计算函数,在事件循环仍在计算时将控制权交还给

      要了解有关事件循环的更多信息,请访问 https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/function*

      https://davidwalsh.name/es6-generators

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-02-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-04-17
        相关资源
        最近更新 更多