2014-10-01 59 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