2014-10-01 67 views
0

我正在实施REST服务进行财务计算。因此,每个请求被认为是一个CPU密集型任务,我认为最好的地方创建线程它在以下功能:Node.js多线程使用线程-gogo

exports.execute = function(data, params, f, callback) { 

    var queriesList = []; 
    var resultList = []; 

    for (var i = 0; i < data.lista.length; i++) 
    { 
     var query = (function(cod) { 

      return function(callbackFlow) { 

       params.paramcodneg = cod; 

       doCdaQuery(params, function(err, result) 
       { 
        if (err) 
        { 
         return callback({ERROR: err}, null); 
        } 

        f(data, result, function(ret) 
        { 
         resultList.push(ret); 
         callbackFlow(); 
        }); 
       }); 
      } 
     })(data.lista[i]); 

     queriesList.push(query); 
    } 

    flow.parallel(queriesList, function() { 
     callback(null, resultList); 
    }); 
}; 

我不知道什么是最好的,在运行flow.parallel分离线程或在其自己的线程中运行queriesList的每个函数。什么是最好的?以及如何使用threads-a-gogo模块呢?

我试过了,但是无法写出正确的代码。

在此先感谢。 克莱森里奥斯。

回答

1

我承认我对node.js比较新,而且我还没有使用线程gogo,但是我对多线程编程有一些经验,所以我会采取一些措施来回答这个问题。

为每个查询创建一个线程(我假设这些查询是CPU绑定计算而不是IO绑定调用数据库)并不是一个好主意。在昂贵的操作中创建和销毁线程,因此为每个需要计算的请求创建一个线程组将会对性能产生巨大的拖累。处理器在它们之间切换时,线程太多会导致更多开销。拥有比处理器内核更多的工作线程没有任何优势。另外,如果每个查询都不占用太多的处理时间,那么与运行查询相比,创建和销毁线程将花费更多的时间。大部分时间将用于线程开销。在这种情况下,使用流或异步的单线程解决方案会更好,它将处理分配到多个滴答以允许node.js事件循环运行。

单线程解决方案是最容易理解和调试的,但如果查询阻止主线程完成其他任务,则需要多线程解决方案。

您提出的多线程解决方案非常好。在单独的线程中运行所有查询可防止主线程陷入停滞状态。但是,在这种情况下使用流或异步没有任何意义。这些模块通过将处理分布在多个节点上来模拟多线程.js滴答和并行运行的任务不以任何特定顺序执行。但是,这些任务仍然在单线程中运行。由于您在自己的线程中处理查询,并且它们不再干扰node.js事件循环,因此只需在循环中一个接一个地运行它们。由于所有操作都发生在没有node.js事件循环的线程中,因此使用flow或async只会引入更多的开销,而没有额外的好处。

一个更有效的解决方案是让线程池在后台挂出并抛出任务。理想情况下,线程池的线程数与处理器内核的线程数相同,并且在应用程序启动时创建,并在应用程序关闭时销毁,所以线程的昂贵创建和销毁只发生一次。我看到线程Gogo有一个可以使用的线程池,但是我担心我还不够熟悉它,因为它给你所有使用它的细节。

我正在进入我不熟悉的领域,但我相信你可以通过将每个查询分别推送到全局线程池并在所有回调完成后完成。

该节点。流模块在这里很方便,并不是因为它会使处理速度更快,而是因为它可以帮助您管理所有查询任务和回调。您将使用循环来使用flow.parallel(...)在流栈上推送一堆并行任务,其中每个任务都会使用threadpool.any.eval()向全局线程池发送查询,然后调用ready ()在线程池回调中告诉流程任务已完成。并行任务排队后,使用flow.join()运行所有任务。这应该在线程池上运行查询,线程池可以一次运行尽可能多的任务,使用所有内核并避免创建或销毁线程,并且所有查询都将被处理。

其他请求也会将它们的任务抛到线程池上,但是您不会注意到,因为正在处理的请求只会获得请求提供给线程池的任务的回调。请注意,这将全部在主线程上完成。线程池将完成所有非主线程处理。

你需要做一些线程gogo和node.flow文档阅读并找出一些细节,但这应该让你有一个良好的开端。使用单独的线程比使用主线程更复杂,并且使用线程池更加复杂,因此您必须选择哪一个最适合您。额外的复杂性可能会或可能不值得。

+0

谢谢凯文。 – 2015-02-02 10:30:57