2017-09-18 267 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)挂起。这基本上是随机的,似乎是在一夜之间发生的。 –