簡體   English   中英

節點 HTTP 請求永遠掛起

[英]Node HTTP request hangs forever

我們有一個每分鍾運行一次的 Node.js 腳本來檢查我們的應用程序的狀態。 通常,它工作得很好。 如果服務已啟動,則以 0 退出。如果服務已關閉,則以 1 退出。一切正常。

但每隔一段時間,它就會停止。 控制台報告“正在調用狀態 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);
    }
}

如果你們中的任何人都可以看到任何可能在沒有輸出或超時的情況下掛起的地方,那將非常有幫助!

謝謝你,詹姆斯·坦納

編輯: ps 我們直接使用https ,而不是request這樣腳本運行時我們就不需要進行任何安裝。 這是因為該腳本可以在分配給 Jenkins 的任何構建機器上運行,而無需自定義安裝。

在您的響應回調中,您沒有檢查狀態..

.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
  }
  ....

你不是錯過了.end()嗎?

http.request(options, callback).end()

這里解釋的東西

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM