1

私のノード サイトでは、標準の http get を使用して構築した RESTful API サービスを呼び出します。この通信が正常に機能してから数時間後、リクエストの送信が停止し、待機するだけで最終的にタイムアウトすることがわかりました。

呼び出されている API は、別の場所からのリクエストを引き続き完全に受信していますが、リクエストがサイトから送信されると、API に到達しません。

stream.pipe、util.pump を試し、ファイル システムにファイルを書き込むだけです。

Node 0.6.15 を使用しています。私のサイトと呼び出されているサービスは同じサーバー上にあるため、localhost への呼び出しが行われています。メモリ使用率は全体で約 25% で、CPU の平均使用率は約 10% です。

しばらく問題が発生した後、リクエストモジュールの使用を開始しましたが、同じ動作をします。失敗する前に行う呼び出しの数は、5 から 100 の間のようです。

サイト内のコードの大まかな内容は次のとおりです。

var Request = require('request');
downloadPDF: function(req, res) {
  Project.findById(req.params.Project_id, function(err, project) {
    project.findDoc(req.params.doc_id ,function(err, doc) {
      var pdfileName;
      pdfileName = doc.name + ".pdf";
      res.contentType(pdfileName);
      res.header('Content-Disposition', "filename=" + pdfileName);
      Request("http://localhost:3001/" + project._id).pipe(res);
    });
  });
}

私は何が起こっているのかについてたくさんのことを知っています。

4

5 に答える 5

4

ノードサーバーがどれだけビジーであるかはわかりませんが、すべてのソケットがTIME_WAITステータスになっている可能性があります。

このコマンドを実行すると、この状態にあるソケットの数がわかります。

netstat -an | awk '/tcp/ {print $6}' | sort | uniq -c

もちろん、いくつかあるのは普通のことです。システムで使用可能なソケットを最大限に活用して、それらをすべてTIME_WAITにする必要はありません。

この場合、実際にはagent.maxSockets設定を減らす必要があります(@ user1372624の提案とは異なります)。そうしないと、最近のソケットを再利用できたとしても、各リクエストは新しいソケットを受け取るだけです。応答しない状態に達するまでに時間がかかるだけです。

私はあなたを助けるかもしれないこの要点(http.Agentへのパッチ)を見つけました。

このサーバー障害の回答も役立つ場合があります:https ://serverfault.com/a/212127

最後に、ノードの更新が役立つ可能性もあります。これは、ノードがバージョン以降のキープアライブ動作に対処している可能性があるためです(変更ログを確認する場合があります)。

于 2012-06-07T23:29:39.563 に答える
4

agent.maxSockets を増やしたり、http.Agent 機能を無効にしたりしましたか? デフォルトでは、最近のノード バージョンは HTTP クライアント接続にソケット プールを使用します。これが問題の原因である可能性があります http://nodejs.org/api/http.html#http_class_http_agent

于 2012-06-03T17:43:28.630 に答える
0

Project.findById()は、提供されたコールバックが完了するのを待たずにすぐに戻るため、あまり意味のない値を返すためにコールバックを使用しています。

でも、気を悪くしないでください。nodejsが使用するプログラミングモデルは、最初は頭を包み込むのがやや難しいです。

イベントドリブンプログラミング(EDP)では、結果を達成するためのコールバックを提供します。コールバックが実際にいつ呼び出されるかわからないため、戻り値は無視されます。

これが簡単な例です。

HTTPリクエストの結果をファイルに書き込みたいとします。

手続き型(非EDP)プログラミング環境では、値を返す場合にのみ値を返す関数に依存しています。

したがって、(擬似コード)のようなものを書くかもしれません:

    url = 'http://www.example.com'

    filepath = './example.txt'

    content = getContentFromURL(url)

    writeToFile(filepath,content)

    print "Done!"

これは、 getContentFromURL()がリモートサーバーに接続して要求を行い、結果を待ってその結果をプログラムに返すまで、プログラムが待機することを前提としています。

次に、writeToFile()関数は、オペレーティングシステムに、書き込み用にファイルパスでローカルファイルを開くように要求し、ファイルを開く操作が完了したことが通知されるまで待機します(通常ディスクドライバーがそのような操作を実行できることを報告するのを待ちます。 )。

次に、writeToFile()は、オペレーティングシステムが新しく開いたファイルにコンテンツを書き込むように要求し、オペレーティングシステムがファイルの書き込みに使用するドライバーがこの目標を達成したことを通知するまで待機し、結果をプログラムに返します。プログラムが完了したことを教えてください。

nodejsが解決するために作成された問題は、上記で発生するすべての待機によって浪費されるすべての時間をより適切に使用することです。

これは、リモートWeb要求から結果を取得したり、ファイルシステムにファイルを書き込んだりするなどの操作が完了したときに呼び出される関数(コールバック)を使用して行われます。

イベント駆動型プログラミング環境で上記と同じタスクを実行するには、次のように同じプログラムを作成する必要があります。

    getContentFromURL(url,onGetContentFromURLComplete)

    function onGetContentFromURLComplete(content,err){
        writeToFile(content,onWriteToFileComplete);
    }

    function onWriteToFileComplete(err){
        print "Done!";
    }

どこ

  • getContentFromURL()を呼び出すと、Webリクエストの結果が得られた場合にのみonGetContentFromURLCompleteコールバックが呼び出されます。
  • writeToFile()を呼び出すと、コンテンツの書き込みが正常に完了したときにのみ、コールバックが呼び出されて成功メッセージが表示されます。

nodejsの本当の魔法は、手続き型関数が最も時間のかかる操作(入出力に関係する操作など)が完了するまで待機しなければならない驚くほど長い時間の間に、他のあらゆる種類のことを実行できることです。

(上記の例では、通常は悪いことと見なされるすべてのエラーを無視しています。)

于 2012-04-20T22:44:45.193 に答える
0

また、組み込み関数を使用して断続的なエラーが発生しました。回避策として、ネイティブの wget を使用します。私は次のようなことをします

var exec = require('child_process').exec;
function fetchURL(url, callback) {
    var child;
    var command = 'wget -q -O - ' + url;
    child = exec(command, function (error, stdout, stderr) {
            callback(error, stdout, stderr);
        });
}

いくつかの小さな適応により、ニーズに合わせて機能させることができます. これまでのところ、私にとっては堅実です。

于 2012-04-21T04:30:14.123 に答える
0

この関数の呼び出し中にパラメーターをログに記録しようとしましたか? エラーは、req.params.Project_id によって異なります。また、コールバック関数でエラー処理を提供する必要があります。

失敗したリクエストを特定のパラメーター セットに突き止めることができれば (それらを再現可能にすることができれば)、node-inspector を使用してアプリケーションを簡単にデバッグできます。

于 2012-06-06T07:50:40.407 に答える