2017-09-18 12 views
0

アプリケーションのステータスを確認するために1分に1回実行されるNode.jsスクリプトがあります。通常、正常に動作します。サービスが稼働中の場合は0で終了します。停止している場合は1で終了します。すべて正常です。ノードHTTPリクエストは永久にハングします

しかし、しばらくの間、それはちょっとだけ止まります。コンソールは「Calling status API ...」と報告し、無期限にそこで停止します。 Nodeのビルトイン2分のタイムアウトではタイムアウトしません。エラーはありません。ただそこに座って、待って、永遠に。これは、次のステータスチェックジョブの実行をブロックするため、問題です。

この時点で私のチーム全体がそれを見ていて、どんな状況が起こるのか把握することはできません。開始から終了までのタイムアウトで構築されているので、次の仕事に進むことができますが、基本的にはステータスチェックをスキップして盲目を作ります。だから、私はあなたに良い人に質問を開きます。ここで

は(取り外し名前/ URLを含む)スクリプトです:あなたのいずれかが、これはおそらく、出力やタイムアウトせずにハングアップする可能性のある場所を見ることができる場合

#!/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); 
    } 
} 

、それは非常に参考になると思います! P.S.:

は、 ジェームズ・タナー

EDITをありがとうrequestの代わりにhttpsを直接使用するので、スクリプトの実行時にインストールする必要はありません。これは、Jenkinsに割り当てられた任意のビルドマシンでカスタムインストールを実行せずにスクリプトを実行できるためです。あなたの応答のコールバックあなたの状態をチェックしませインサイド

+0

レスポンスコールバックのステータスコードが200に等しくない場合はエラーを表示します。 – Keith

+0

ああ、申し訳ありません@キース、私はそれについてはっきりしていないと思います。成功は応答によって決まります。 200コードでは必ずしも十分ではありません。 –

+0

私のコメントを編集しました。私は入力を終える前に "Add"を押すでしょう。 –

答えて

1

..

.on('error', handle_error);は、サーバへの接続に発生したエラーのためにある、ステータス・コードのエラーは、サーバーが接続に成功した後で応答したものです。

通常200のステータス応答は、あなたが成功したリクエストに期待するものです。..

だから、これを処理するために、あなたのhttp.getに小さなmodは...

などを行う必要があります。

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)ハングするのを待たなければなりません。基本的にランダムで、一晩で起こるようです。 –

関連する問題