2017-09-18 189 views
0

我們有一個Node.js腳本,每分鐘運行一次以檢查我們的應用程序的狀態。通常,它工作得很好。如果服務啓動,它將以0退出。如果服務停止,它將以1退出。一切都很好。節點HTTP請求永久掛起

但每隔一段時間,它只是有點停止。控制檯報告「呼叫狀態API ...」並在那裏無限期地停止。它甚至不會在Node內置的兩分鐘超時時間內超時。沒有錯誤,沒有。它只是坐在那裏,等待着,永遠。這是一個問題,因爲它會阻止正在運行的以下狀態檢查作業。

在這一點上,我的整個團隊已經看過它,我們誰也無法弄清楚什麼情況會使它掛起。我們已經建立了一個從開始到結束的超時時間,以便我們可以繼續進行下一個工作,但實際上這會跳過狀態檢查並創建盲點。所以,我向你們提出了一個好問題。

這裏的腳本(除去名稱/網址):

#!/usr/bin/env node 

// SETTINGS: ------------------------------------------------------------------------------------------------- 
/** URL to contact for status information. */ 
const STATUS_API = process.env.STATUS_API; 

/** Number of attempts to make before reporting as a failure. */ 
const ATTEMPT_LIMIT = 3; 

/** Amount of time to wait before starting another attempt, in milliseconds. */ 
const ATTEMPT_DELAY = 5000; 

// RUNTIME: -------------------------------------------------------------------------------------------------- 
const URL = require('url'); 
const https = require('https'); 

// Make the first attempt. 
make_attempt(1, STATUS_API); 

// FUNCTIONS: ------------------------------------------------------------------------------------------------ 
function make_attempt(attempt_number, url) { 
    console.log('\n\nCONNECTION ATTEMPT:', attempt_number); 
    check_status(url, function (success) { 
     console.log('\nAttempt', success ? 'PASSED' : 'FAILED'); 

     // If this attempt succeeded, report success. 
     if (success) { 
       console.log('\nSTATUS CHECK PASSED after', attempt_number, 'attempt(s).'); 
       process.exit(0); 
     } 

     // Otherwise, if we have additional attempts, try again. 
     else if (attempt_number < ATTEMPT_LIMIT) { 
      setTimeout(make_attempt.bind(null, attempt_number + 1, url), ATTEMPT_DELAY); 
     } 

     // Otherwise, we're out of attempts. Report failure. 
     else { 
      console.log("\nSTATUS CHECK FAILED"); 
      process.exit(1); 
     } 
    }) 
} 

function check_status(url, callback) { 
    var handle_error = function (error) { 
     console.log("\tFailed.\n"); 
     console.log('\t' + error.toString().replace(/\n\r?/g, '\n\t')); 
     callback(false); 
    }; 

    console.log("\tCalling status API..."); 
    try { 
     var options = URL.parse(url); 
     options.timeout = 20000; 
     https.get(options, function (response) { 
      var body = ''; 
      response.setEncoding('utf8'); 
      response.on('data', function (data) {body += data;}); 
      response.on('end', function() { 
       console.log("\tConnected.\n"); 
       try { 
        var parsed = JSON.parse(body); 
        if ((!parsed.started || !parsed.uptime)) { 
         console.log('\tReceived unexpected JSON response:'); 
         console.log('\t\t' + JSON.stringify(parsed, null, 1).replace(/\n\r?/g, '\n\t\t')); 
         callback(false); 
        } 
        else { 
         console.log('\tReceived status details from API:'); 
         console.log('\t\tServer started:', parsed.started); 
         console.log('\t\tServer uptime:', parsed.uptime); 
         callback(true); 
        } 
       } 
       catch (error) { 
        console.log('\tReceived unexpected non-JSON response:'); 
        console.log('\t\t' + body.trim().replace(/\n\r?/g, '\n\t\t')); 
        callback(false); 
       } 
      }); 
     }).on('error', handle_error); 
    } 
    catch (error) { 
     handle_error(error); 
    } 
} 

如果你們能看到的任何地方,這可能可能掛無輸出或超時,那會是非常有幫助!

謝謝 詹姆斯·坦納

編輯:附:我們直接使用https而不是request,這樣腳本運行時我們不需要進行任何安裝。這是因爲腳本可以在沒有自定義安裝的情況下在分配給Jenkins的任何構建機器上運行。

+0

我會檢查您的響應回調中的狀態碼,如果它不等於200,則會引發錯誤。 – Keith

+0

哦,對不起@凱斯,我不認爲我清楚這一點。成功取決於迴應。 200代碼不一定足夠。 –

+0

編輯我的評論。在完成打字之前,我會點擊「添加」。 –

回答

1

裏面你的迴應你的回調不檢查狀態..

.on('error', handle_error);是對發生連接到服務器錯誤,狀態代碼的錯誤是那些在服務器連接成功後進行響應。

通常一個200個狀態響應是,你會從一個成功的請求會發生什麼..

所以小國防部您http.get來處理這應該做的..

如。

https.get(options, function (response) { 
    if (response.statusCode != 200) { 
    console.log('\tHTTP statusCode not 200:'); 
    callback(false); 
    return; //no point going any further 
    } 
    .... 
+0

不幸的是,這似乎並不是解決方案。我添加了這個,並且它還是在一夜之間定期掛起。我已經添加了一些額外的日誌記錄來試圖確定它到底在哪裏。當我得到它們時,我會用更多細節更新我的文章。 –

+0

哦,另一個想法。也許錯誤沒有得到連接,但在連接期間..嘗試把'response.on('error',handle_error);' – Keith

+0

現在就試試這個!只需等待它a)錯誤,或b)掛起。這基本上是隨機的,似乎是在一夜之間發生的。 –