2011-04-15 91 views
2

我有一個node.js腳本不斷地請求頁面,有點像cron作業。Node.js http請求內存和cpu豬

但是,幾分鐘後,Node開始使用大量的CPU(高達70%)和內存(高達200MB)。

我的腳本有什麼問題?

function cron(path) 
{ 
    var http = require('http'); 
    var site = http.createClient(443, 'www.website.com', true); 
    var request = site.request('GET', path, {'host': 'www.website.com'}); 
    request.end(); 

    request.on('response', function (response) { 

     setTimeout(function(){cron(path)},15000); 
    }); 


} 

cron('/path/to/page'); 

回答

4
request.on('response', function (response) { 
    setTimeout(function(){cron(path)},15000); 
}); 

對於每一個響應創建一個新的cron工作。記錄你的迴應。如果你從你的請求中獲得更多的1,那麼你指數地創建更多的cron作業。

您創建一個function() {}並參照path。因此整個範圍狀態都保持不變。你想加入這個以釋放內存:

var site = null; 
var request = null; 

你在模塊範圍調用require("http")在函數內部而不是外部。您只需要獲取http一次,以便在模塊範圍內放置在文件頂部。

var http = require('http'); 
var site = http.createClient(443, 'www.website.com', true); 
function cron(path) 
{ 

    var request = site.request('GET', path, {'host': 'www.website.com'}); 
    request.end(); 

    var once = true; 
    request.on('response', doIt); 

    function doIt(response) { 
     if (!once) { 
      once = null; 
      doIt = function() {}; 
      setTimeout(function(){cron(path)},15000); 
     } 
    }); 

    site = null; 
    request = null; 
} 

cron('/path/to/page'); 
+0

太好了,我正在測試新的腳本。我不明白爲什麼在request.on()回調中使用「once」變量,每個請求只能有一個響應? – koen 2011-04-15 13:26:16

+0

@koen以確保它只被調用一次。您是否想在獲得_a_響應時創建新的'cron'作業,或者是否希望爲從請求中獲得的_every_響應創建新的'cron'作業?請注意,我的一些「優化」可能由V8解釋器爲您完成。我不知道V8是否知道什麼時候釋放內存,當不需要時將變量設置爲'null'基本上標記該內存以供GC清除。 – Raynos 2011-04-15 13:28:19

+0

我想在舊請求完成時創建一個新的響應。有時候,頁面加載需要更長的時間,我只需要一個cron,這就是爲什麼我使用request.on()回調。我只是檢查並且頁面只返回一個響應。 – koen 2011-04-15 13:36:09

0

除了來自@Raynos的提示之外,還有另外一個。我發現在長時間運行的過程中,像這樣的遞歸調用讓我有點緊張,所以我會錯誤地使用setInterval來代替。如果您想嘗試重新使用該邏輯,我可能會拆分cron和http行爲,但這將取決於您的上下文:

例如,在節點0.4.7中:

var https = require('https'); 

function poll(path) 
{ 
    https.get({ 
     host: 'www.website.com', 
     port: 443, 
     path: path 
    }, function(res) { 
     console.log("Got response: " + res.statusCode); 
    }).on('error', function(e) { 
     console.log("Got error: " + e.message); 
    }); 

} 

function cron(path) 
{ 
    return setInterval(function(){ 
     poll(path); 
    },15000); 
} 

var intervalId = cron('/path/to/page'); // keep in case you need to use clearInterval